widget, 快速便捷、功能单一、使用频繁,如图,是支付宝的widget效果图。
widget开发步骤:
就发widget并不难,就那么简单的几个步骤,请往下看↓↓↓↓
-
第一步 新建target
新建的方式有两种
1: File-> New -> Target;
2: 点击工程,点击target列表下方的加号进行添加
选择Today Extension
点击next
,输入Product Name等信息。需要注意的是最后面有一个Embed in Application
选项,这里请选择你的App。
完成之后,左侧会多一个testWidget
文件夹,以及对应的文件,如图
第二步 布局:
默认是采用interface.storyboard,如果使用纯代码需要在Info.plist文件进行相应的修改, 删除key - NSExtensionMainStoryboard
, 添加key-NSExtensionPrincipalClass
, value-TodayViewController
,如果使用xib可忽略。
默认值:
修改后:
如果采用Xib,这一步可以忽略。
第三步 版本适配:
版本<iOS 10
self.preferredContentSize = CGSizeMake(self.view.bounds.size.width, 110); // 指定宽高
页边距设置
-(UIEdgeInsets)widgetMarginInsetsForProposedMarginInsets:(UIEdgeInsets)defaultMarginInsets
{
return UIEdgeInsetsMake(0, 0, 0, 0);
}
版本>iOS 10
设置是否支持widget展开与折叠,NCWidgetDisplayModeExpanded
是一个枚举值,这里支持折叠。
if ([[UIDevice currentDevice].systemVersion doubleValue] >= 10.0) {
self.extensionContext.widgetLargestAvailableDisplayMode = NCWidgetDisplayModeExpanded;// 支持折叠
}
NCWidgetDisplayMode代理回调:
-(void)widgetActiveDisplayModeDidChange:(NCWidgetDisplayMode)activeDisplayMode withMaximumSize:(CGSize)maxSize
{
if (activeDisplayMode == NCWidgetDisplayModeCompact) { // 折叠时大小
self.preferredContentSize = CGSizeMake(self.view.bounds.size.width, 110);
}else{ // 展开时大小
self.preferredContentSize = CGSizeMake(self.view.bounds.size.width, 220);
}
}
第四步 数据处理:
数据刷新:每一次切换到widget页面和下拉widget页面会刷新todayviewcontroller,执行viewwillappear方法
数据共享:widget与应用程序共享一些数据,使用App Groups,组内的app共享一个沙盒空间,App Groups是什么呢?,首先先去 开发中心 注册申请App Groups。进入开发者中心后根据提示一步一步操作即可,这里很简单。
新建时,填写的ID通常以group.开头。
证书配置
widget是个独立的target,需要使用单独的Boundle id以及对应的证书。个人建议先把APP的Boundle id确定以后再去创建target。这样就可以不用修改boundle id了,否则,运行的时候回提示错误信息,widget的Bundle id的包含App的Bundle id。
进入工程,将App和widgt中的App Groups打开,选中需要共享数据的group,就是在上一步中创建的id,这里会自动出来的,不用担心。如果创建了多个groups,这里会把该开发者账号里面所有都列出来,然后选择你要用的那一个就可以了。
数据共享:
widget与App之间的数据交互有两种方式,可以采用NSUserDefaults或者是NSFileManager进行实现。
通过NSUserDefaults
#define GROUP_ID @"这里是创建app groups的id"
// 保存数据
+(void) saveObject:(id) object forkey:(NSString *) key{
if (object && key) {
NSUserDefaults *userDefault = [[NSUserDefaults alloc] initWithSuiteName:GROUP_ID];
if (userDefault) {
[userDefault setObject:object forKey:key];
[userDefault synchronize];
}
}
}
// 读取数据
+(id) objectForKey:(NSString *) key{
NSUserDefaults *userDefault = [[NSUserDefaults alloc] initWithSuiteName:GROUP_ID];
if (userDefault) {
id object = [userDefault objectForKey:key];
return object;
}
return nil;
}
NSFileManager方式:
// 保存数据
- (void) saveObject{
NSError *error = nil;
NSURL *url = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.com.xxxx"];
url = [url URLByAppendingPathComponent:@"Library/Caches/wodget"];
NSString *value = @"data";
BOOL result = [value writeToURL:url atomically:YES encoding:NSUTF8StringEncoding error:&error];
if (!result) {
NSLog(@"%@", error);
}
else{
NSLog(@"save value:%@ success.", value);
}
}
// 读取数据 返回类型以实际数据为准
-(NSString *) readData{
NSError *error = nil;
NSURL *url = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.com.xxx"];
url = [url URLByAppendingPathComponent:@"Library/Caches/widget"];
NSString *dataStr = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];
return dataStr;
}
与App进行交互
首先我们需要在APP中的添加url schemes ,可以直接写app的bound id嘛
通过widget来打开app应用
//#define APP_URL_SCHEMES @"com.icoming.MacBee"// app的urlschemes
NSString * urlSchemes = [NSString stringWithFormat:@"%@://",APP_URL_SCHEMES];
NSURL * url = [NSURL URLWithString:urlSchemes];
[self.extensionContext openURL:url completionHandler:^(BOOL success) {
}];
```