欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

iOS Widget开发

程序员文章站 2022-05-30 17:38:11
...

前言:

想了解什么是Widget的童鞋请绕道,想在项目中添加Widget的同学,请耐心往下看

首先看一下我们需要实现的效果:仿网易云音乐和仿支付宝两个效果

iOS Widget开发  iOS Widget开发

总效果图(左)  仿网易云音乐展开后的效果图(右)


一、打开你的Project,添加一个Today Extension

首先,打开Target,然后点左下角的“+”,在“iOS”选项下边找到Application Extension,然后选择“Today Extension”,如图1、图2所示:

iOS Widget开发

图1 添加Target



iOS Widget开发

图2 找到Today Extension


然后点击Next,填写Target名称,这里是“HJFirstWidget”,下一步会有一个**的弹窗,点击**按钮,如图3所示

iOS Widget开发

图3 **Target


**之后,就添加好了,如图4所示,这时候你需要改Deployment Target,也就是最低支持的系统版本,需要注意的是Widget是iOS 8的新特性,因此此处的Deployment Target不能低于iOS 8.0;

iOS Widget开发

图4 添加Today Extension完成以及需改Deployment Target示意图


这时候,运行项目就可以在通知页面看到一个空的Widget效果了,此时默认的视图控制器是TodayViewController,与之对应的是一个叫“MainInterface”的storyboard,如果需要纯代码布局,那么就要在plist文件最下边的NSExtension里修改一些配置,删除NSExtensionMainStoryboard键值对,新增NSExtensionPrincipalClass键值对,修改之前如图5所示,修改后如图6所示

iOS Widget开发

图5 未修改配置的示意图


iOS Widget开发

图6 修改配置后的示意图

需要说明的是:我们添加的Target叫Extension,最初创建的项目叫Containing APP

运行Containing APP,效果图如图7所示

iOS Widget开发

图7 更改完配置后运行效果图


到这一步呢,项目基本成型,只需要我们在TodayViewController里边添加相应的空间即可实现相应的效果,下边我们将实现Widget最难也是最重要的功能

二、共享数据

要想通过Widget和Containing APP共享数据需要对他们分别进行配置,首先我们对Containing APP配置

打开Target,点击capability选项,找到APP Groups,点击右侧打开按钮,并添加Item,如图8 所示,配置完成之后再项目中会看淡一个后缀为.entitlements的文件;

iOS Widget开发

图8 打开APP Groups以及添加Item示意图

然后配置Widget,操作同上步,操作完成后效果图如图9所示

iOS Widget开发

图9 配置Widget完成后效果图

此时配置已经完成,通过相应代码即可实现数据共享,我们都知道,Extension 和 Containing APP之间共享数据的方式有两种,NSUserDefaults和NSFileManager,

1.通过NSFileManager存取:

存数据:

/**
 通过NSFileManager存数据

 @return 是否存储成功
 */
- (BOOL)saveDataByNSFileManager
{
    NSError *err = nil;
    
    /**    这里的groupIdentifier是在APP Groups里添加的Item    **/
    NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.hjfirst"];
    containerURL = [containerURL URLByAppendingPathComponent:@"Library/Caches/widget"];
    
    NSString *value = @"你要存的内容";
    BOOL result = [value writeToURL:containerURL atomically:YES encoding:NSUTF8StringEncoding error:&err];
    if (!result)
    {
        NSLog(@"存入数据失败,原因 : %@",err);
    }
    else
    {
        NSLog(@"存入数据成功,数据 : %@ success.",value);
    }
    return result;
}

取数据:

/**
 通过NSFileManager读取数据

 @return 读取到的数据
 */
- (NSString *)readDataByNSFileManager
{
    NSError *err = nil;
    NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.hjfirst"];
    containerURL = [containerURL URLByAppendingPathComponent:@"Library/Caches/widget"];
    NSString *value = [NSString stringWithContentsOfURL:containerURL encoding:NSUTF8StringEncoding error:&err];
    return value;
}


2.通过NSUSerDefaults来共享数据

存数据:

/**    这里是采用NSUserDefaults来实现   **/
    NSUserDefaults *sharedDefault = [[NSUserDefaults alloc] initWithSuiteName:@"group.hjfirst"];
    [sharedDefault setObject:@{@"name" : [_titleArray objectAtIndex:sender.tag - 120]} forKey:@"firstStatus"];
    [sharedDefault setBool:NO forKey:@"isSendData"];
    [sharedDefault synchronize];

取数据

/**    这是一个获取Today Extension数据的例子    **/
    NSUserDefaults *sharedDefault = [[NSUserDefaults alloc] initWithSuiteName:@"group.hjfirst"];
    NSLog(@"共享的数据 : %@",[sharedDefault objectForKey:@"firstStatus"]);


三、通过Extension唤醒Containing APP

如果想通过Extension唤醒Containing APP,需要在Containing APP的Target进行配置,在Info的URL Types里边新增一项内容,配置后效果图如图10所示

iOS Widget开发

图10 配置Containing APP效果图


配置完上述信息之后,就可以通过代码唤醒Containing APP,示例代码如下,其中://后边的内容是传递的参数,用以区分响应不同的事件

/*
     这里的URL是有固定格式的,://前边的“hjWidgetDemo”是Containing APP添加的URL Types里添加的URL Schemes,这里是必须一致,否则会跳转失败的
     */
    NSString *urlString = [NSString stringWithFormat:@"hjWidgetDemo://action=%ld",sender.tag-120];
    
    [self.extensionContext openURL:[NSURL URLWithString:urlString] completionHandler:^(BOOL success) {
        if (success == YES) {
            NSLog(@"跳转成功");
        }
        else
        {
            NSLog(@"跳转失败");
        }
    }];

四、iOS 10新特性

Widget可以折叠和展开,示例代码:

/*
     设置Widget的样式,这是iOS 10的新特性,也就是所谓的“折叠”、“打开”模式,
     NCWidgetDisplayModeCompact, // Fixed height
     NCWidgetDisplayModeExpanded, // Variable height
     */
    self.extensionContext.widgetLargestAvailableDisplayMode = NCWidgetDisplayModeExpanded;

系统封装的有点击折叠或者展开按钮的方法:

/**
 这是Widget改变展示样式时候的回调
 
 @param activeDisplayMode activeDisplayMode
 @param maxSize 尺寸
 */
- (void)widgetActiveDisplayModeDidChange:(NCWidgetDisplayMode)activeDisplayMode withMaximumSize:(CGSize)maxSize
{
    
}



最终效果图为:

iOS Widget开发


注意事项:

  1. Widget的展开和折叠是iOS 10的新特性,在iOS 8 到iOS 10 之间的系统只支持类似于折叠起来的效果;
  2. 如果需要自定义Widget某一部分控件的背景颜色,需要设计透明度,因为TodayViewController的背景色有透明度的,在不同颜色桌面壁纸上显示效果有较大差异;
  3. Widget目前暂不支持输入内容,只能做展示以及点击事件,也就是说不能再TodayViewController里边添加输入类的控件,比如说UITextField、UITextView等; 

特别说明:如果发现错误或者不合理的地方,恳请批评指正


源码下载地址:https://github.com/HJZone/HJWidgetDemo