iOS - Widget小部件(Today Extension)

Today Extension是iOS8新开放的一种对几个固定系统区域的扩展机制,它可以在一定程度上弥补iOS的沙盒机制对应用间通信的限制,iOS10之后又添加了一些功能。可能好多人不知道或不怎么用Widget。那到底什么小部件呢?看图:
这里写图片描述
看到这个图你应该就知道Widget这是什么了吧,可能你正在使用它。

之后我们研究下面几个问题:

1、为什么要使用widget;
2、如何在现有的工程添加widget;
3、如何试图布局;
4、如何调起主App以及进入相应的页面;
5、如何与主App共享数据。

为什么要使用widget呢?

它为我们的应用提供了一种便捷的服务方式,比如用户可以在Today Extension中查看应用展示的简略信息,而不用再进到我们的应用中,同样可以快捷操作app的功能,这将是一种全新的用户体验。重点就是便捷、快,这是苹果在iOS12中所追求的。

特点:Widget你可以看作是一个独立的小项目,当你添加好之后,你会发现它和主App不互通,想要很好的应用它,需要配置一些文件。如下面这些步骤:

如何在现有的工程添加widget

首先打开你的项目,在原有的工程基础上,想要使用Today Extension,我们需要创建一个新的target,点击File–>New–>Target–>Today Extention,如下图所示:
这里写图片描述
这里写图片描述
添加成功后项目的目录会如下图所示:
这里写图片描述
运行项目会看到如下图所示的效果:
这里写图片描述
注意:这里你运行的项目时会发现有两个可运行项目(Widget是独立的),当你运行主项目时,是无法调试Widget的,无法打断点调试,无法打印一些数据等。

如何试图布局

试图布局这里分两种,纯代码和storyboard,如果想用纯代码,需要在plist文件里配置一点东西:选择删除默认创建的MainInterface.storyboard,并在info.plist中删除NSExtensionMainStoryboard,添加NSExtensionPrincipalClass为TodayViewController。
这里写图片描述
设置视图的大小:

- (void)viewDidLoad {
    [super viewDidLoad];
    // iOS10,设置展开折叠
    self.extensionContext.widgetLargestAvailableDisplayMode = NCWidgetDisplayModeExpanded;
}
#pragma mark - NCWidgetProviding
- (void)widgetActiveDisplayModeDidChange:(NCWidgetDisplayMode)activeDisplayMode withMaximumSize:(CGSize)maxSize NS_AVAILABLE_IOS(10_0){
    if (activeDisplayMode == NCWidgetDisplayModeCompact){
        // 折叠后默认高度110
        self.preferredContentSize = CGSizeMake(SCREEN_WIDTH, 110);
    }else{
        // 展开后的高度由你来定
        self.preferredContentSize = CGSizeMake(SCREEN_WIDTH, 485);
    }
}

注意:这里如果你想用masonry库来做约束,主App里Cocoapods导入的masonry是用不了的,你可以把masonry再导入你的 CNTodayViewController 里面,因为它是一个独立的项目,所以好多东西都需要你重新导入,但是Widget讲的是便捷,不会有太复杂的布局,一般就几个按钮,调起主App页面用的,像QQ音乐就三个按钮,很简洁。

如何调起主App以及进入相应的页面

Today Extension只能通过openURL的方式来调起app,并且需要在info.plist文件中配置参数URL types。

主App工程中配置:
这里写图片描述
Today Extension配置:
这里写图片描述
URL identifier为app的bundle ID,URL Schemes配置为app的scheme

#pragma mark - Widget 通过openURL的方式启动Containing APP
- (void)openURLContainingAPP{
    //scheme为app的scheme
    [self.extensionContext openURL:[NSURL URLWithString:@"CNCrm://"]
                 completionHandler:^(BOOL success) {
                     NSLog(@"open url result:%d",success);
                 }];
}
#pragma mark - Widget 进入主App不同的页面
- (void)openDiffirentPage{
[self.extensionContext openURL:[NSURL URLWithString:@"CNCrm://Action=HomePage"]
                     completionHandler:^(BOOL success) {
                         NSLog(@"open url result:%d",success);
                     }];
[self.extensionContext openURL:[NSURL URLWithString:@"CNCrm://Action=DetailPage"]
                     completionHandler:^(BOOL success) {
                         NSLog(@"open url result:%d",success);
                     }];
[self.extensionContext openURL:[NSURL URLWithString:@"CNCrm://Action=MyPage"]
                     completionHandler:^(BOOL success) {
                         NSLog(@"open url result:%d",success);
                     }];
 }

在主App的AppDelegate.m里面:

- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options NS_AVAILABLE_IOS(9_0){
     NSString* prefix = @"CNCrm://Action=";
        if ([[url absoluteString] rangeOfString:prefix].location!=NSNotFound) {
            NSString *action = [[url absoluteString] substringFromIndex:prefix.length];
            if ([action isEqualToString:@"HomePage"]) {
            // 自行处理事件
            } else if ([action isEqualToString:@"DetailPage"]){
            // 自行处理事件
            } else if ([action isEqualToString:@"MyPage"]){
            // 自行处理事件
            }
        }
    return YES;
}

如何与主App共享数据

首先需要去苹果开发者中心的APP Groups中创建一个APP Group,命名方式”group.com.companyName.xxx”,如下图:
这里写图片描述
创建好Group ID之后,回到项目里面配置(主App和Today Extension都要配置):

主App和Today Extension的配置都如下图所示:
这里写图片描述

通过App Groups提供的同一group内app共同读写区域,可以用NSUserDefaults和NSFileManager两种方式实现Today Extension和containing app之间的数据共享。

通过NSUserDefaults共享数据

- (void)saveDataByNSUserDefaults
{
    NSUserDefaults *shared = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.xxx.xxx"];
    [shared setObject:@"哈哈" forKey:@"Widget"];
    [shared synchronize];
}
- (NSString *)readDataFromNSUserDefaults
{
    NSUserDefaults *shared = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.xxx.xxx"];
    NSString *value = [shared valueForKey:@"Widget"];

    return value;
}

通过NSFileManager共享数据

- (BOOL)saveDataByNSFileManager
{
    NSError *error = nil;
    NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.com.xxx.xxx"];
    containerURL = [containerURL URLByAppendingPathComponent:@"Library/Caches/test"];

    NSString *value = @"test";
    BOOL result = [value writeToURL:containerURL atomically:YES encoding:NSUTF8StringEncoding error:&error];
    if (!result) {
        NSLog(@"%@",error);
    } else {
        NSLog(@"save value:%@ success.",value);
    }

    return result;
}
- (NSString *)readDataByNSFileManager
{
    NSError *error = nil;
    NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.com.xxx.xxx"];
    containerURL = [containerURL URLByAppendingPathComponent:@"Library/Caches/test"];
    NSString *value = [NSString stringWithContentsOfURL:containerURL encoding:NSUTF8StringEncoding error:&error];

    return value;
}

通过这两个方法就可以实现了Today Extension与主App的数据共享,类似于主App里面的数据存取。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值