美文网首页
iOS-为项目添加widget(手机最左侧页面的小工具)

iOS-为项目添加widget(手机最左侧页面的小工具)

作者: Y_3c23 | 来源:发表于2019-08-06 17:05 被阅读0次

    Widget开发步骤

    建议先阅读Widget的配置篇,再开始开发,因为开发的过程中需要提前准备一些东西【iOS】Widget开发-配置篇

    1. 创建新的Target,选择Today Extension。点击Next后,会生成如下图的几个文件

    image image

    2. 查看新生成的Info.plist

    Bundle display name:Widget在通知栏显示的名称

    NSExtension

    如果你是使用纯代码进行开发,请按照下面进行操作:

    (1)请删除NSExtensionMainStoryboard 的键值对和MainInterface.storyboard文件;

    (2)请添加NSExtensionPrincipalClass这个key,并将value设置为控制器(如TodayViewController)

    3. 准备工作都已经完成,正式进入开发工作

    iOS 8

    ①、iOS8下没有折叠和展开功能,默认的Widget高度为self.preferredContentSize设置的高度。

    self.preferredContentSize =CGSizeMake(kScreenW,100);

    ②、iOS8下所有组件默认右移30单位,可以通过下面的方法修改上下左右的距离

    - (UIEdgeInsets)widgetMarginInsetsForProposedMarginInsets:(UIEdgeInsets)defaultMarginInsets {returnUIEdgeInsetsMake(0,0,0,0);}

    iOS 10

    iOS 10以后,Widget可玩性更高了,有了两种显示模式

    NCWidgetDisplayModeCompact, // Fixed height,高度固定,最低高度为110

    NCWidgetDisplayModeExpanded, // Variable height,高度可变

    // 5s模拟器下:

    // NCWidgetDisplayModeCompact模式下:{304, 110}

    // NCWidgetDisplayModeExpanded模式下:{304, 528}

    // 6s模拟器下:

    // NCWidgetDisplayModeCompact模式下:{359, 110}

    // NCWidgetDisplayModeExpanded模式下:{359, 616}

    设定显示模式,需要在设定Size前设定这个属性!!!

    if([[UIDevicecurrentDevice] systemVersion].intValue >=10) {

    self.extensionContext.widgetLargestAvailableDisplayMode = NCWidgetDisplayModeCompact;

    // self.extensionContext.widgetLargestAvailableDisplayMode = NCWidgetDisplayModeExpanded;

    }

    viewDidLoad的代码如下:

    - (void)viewDidLoad { 

      [superviewDidLoad];

    if([[UIDevicecurrentDevice] systemVersion].intValue >=10) {

    self.extensionContext.widgetLargestAvailableDisplayMode = NCWidgetDisplayModeCompact;   

    }

    self.preferredContentSize =CGSizeMake(kScreenW,100);     

      [selfsetupUI];

    }

    当显示模式设置为NCWidgetDisplayModeExpanded时,点击折叠和打开时,会触发下面这个方法,在这个方法中可以修改对应状态的高度

    - (void)widgetActiveDisplayModeDidChange:(NCWidgetDisplayMode)activeDisplayMode withMaximumSize:(CGSize)maxSize {

    if(activeDisplayMode == NCWidgetDisplayModeCompact) {

    self.preferredContentSize =CGSizeMake(maxSize.width,110); 

      }else{

    self.preferredContentSize =CGSizeMake(maxSize.width,200);   

    }

    }

    在下面的方法中更新视图

    -(void)widgetPerformUpdateWithCompletionHandler:(void(^)(NCUpdateResult))completionHandler {

    //    NCUpdateResultNewData  新的内容需要重新绘制视图

    //    NCUpdateResultNoData    部件不需要更新

    //    NCUpdateResultFailed    更新过程中发生错误

    completionHandler(NCUpdateResultNoData);

    }

    开发中可能会遇上的一些问题

    代码共享

    目前我见到了四种共享代码的方法:

    将代码打包成Framework,然后link到主App和Widget中(推荐)

    不怕安装包变大的话,可以考虑将需要的第三方库在主App和Widget中分别复制一份(推荐)

    将需要共享的文件按图中进行勾选配置

    image

    通过Pods导入,不太建议通过pod分别向两个Target中导入第三方库,因为很容易发生一些不好处理的问题

    数据共享

    数据共享有两种常用的方法:

    NSUserDefaults,和我们常用的方法一样,不过在创建NSUserDefaults时,需要填写我们之前的GroupID。通过GroupID,我们就可以进行主App和Widget之间的数据共享了。

    /// 写入数据

    NSString*groupID =@"group.com.aaa.bbb";

    NSUserDefaults*ud = [[NSUserDefaultsalloc] initWithSuiteName:groupID];

    [ud setObject:@"我是测试的数据"forKey:@"test"];

    [ud synchronize];

    /// 读取数据

    NSString*groupID =@"group.com.aaa.bbb";

    NSUserDefaults*ud = [[NSUserDefaultsalloc] initWithSuiteName:groupID];

    NSString*value = [ud objectForKey:@"test"];

    NSFileManager

    /// 写入数据

    NSString*groupID =@"group.com.aaa.bbb";

    NSError*err =nil;

    NSURL*containerURL = [[NSFileManagerdefaultManager] containerURLForSecurityApplicationGroupIdentifier:groupID];

    containerURL = [containerURL URLByAppendingPathComponent:@"Library/Caches/test"];

    NSString*value =@"我是测试的数据";

    BOOLresult = [value writeToURL:containerURL atomically:YESencoding:NSUTF8StringEncodingerror:&err];

    if(result){

    NSLog(@"写入成功");

    }

    /// 读取数据

    NSString*groupID =@"group.com.aaa.bbb";

    NSError*err =nil;

    NSURL*containerURL = [[NSFileManagerdefaultManager] containerURLForSecurityApplicationGroupIdentifier:groupID];

    containerURL = [containerURL URLByAppendingPathComponent:@"Library/Caches/test"];

    NSString*value = [NSStringstringWithContentsOfURL:containerURL encoding:NSUTF8StringEncodingerror:&err];

    打开App

    设置App的URLSchemes,打开APP主要通过URLScheme打开和传递参数值。

    设置URLSchemes时,要独特一些,避免与其他App重复

    image

    在Widget中添加点击事件,用于触发打开App的操作和传递参数

    NSString*schemeString =@"zhangpeng://actionName?paramName=paramValue";

    [self.extensionContext openURL:[NSURLURLWithString:schemeString] completionHandler:^(BOOLsuccess) {

    }];

    app的appdelegate的代理方法中,截取URL,做响应处理:

    // 所有版本的都可以使用

    - (BOOL)application:(UIApplication*)application openURL:(NSURL*)url sourceApplication:(NSString*)sourceApplication annotation:(id)annotation {   

        [selfappCallbackWithOpenUrl:url];returnYES;

    }

    /// iOS 8 以后

    - (BOOL)application:(UIApplication*)app openURL:(NSURL*)url options:(NSDictionary *)options {   

        [selfappCallbackWithOpenUrl:url];

    returnYES;

    }

    /// iOS 7

    - (BOOL)application:(UIApplication*)application handleOpenURL:(NSURL*)url {   

        [selfappCallbackWithOpenUrl:url];

    returnYES;

    }

    - (void)appCallbackWithOpenUrl:(NSURL*)url{

    NSLog(@"url: %@", url.host);

    // 针对url进行不同的操作

    }

    数据刷新

    当widget从屏幕上消失2s左右,再次出现在屏幕中时,都会重新调用viewDidLoad方法。所以每次出现都请求最新数据,进行刷新操作,widget都会闪一下,根据产品需求,可以做一下控制;

    - (void)viewDidLoad { 

      [superviewDidLoad];

    }

    如果短时间内让Widget频繁地消失显示,那只会执行viewWillAppear方法;

    - (void)viewWillAppear:(BOOL)animated {

        [superviewWillAppear:animated];

    }

    相关文章

      网友评论

          本文标题:iOS-为项目添加widget(手机最左侧页面的小工具)

          本文链接:https://www.haomeiwen.com/subject/qiewdctx.html