自iOS8之后,苹果支持了扩展(Extension)的开发,开发者可以通过系统提供给我们的扩展接入点 (Extension point) 来为系统特定的服务提供某些附加的功能。
所谓Widget,就是我们熟知的小组件,这是独立于应用之外的又一个新小应用,但是和主应用之间又有着一定的关系。
本文介绍的是iOS14系统以下的widget组件,也就是Todat Extension
iOS14系统以上widget请见:
iOS14 Widget(Widget Extension)小组件开发
widget实现
1.创建添加Todat Extension
File
-> New
-> Target
-> Todat Extension
2.添加widget的URL Schemes
由于extension 和主app 是两个完全独立的进程,所以它们之间不能直接相互跳转。为了实现 Widget 调起 APP,这里通过 openURL
的方式来启动 主app。
主APP中 Target
-> Info
-> URL Types
-> +
调用方式
widget中点击跳转事件添加如下代码
[self.extensionContext openURL:[NSURL URLWithString:@"NowWidget://"] completionHandler:nil];
主APP的AppDelegate中接收
-(BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options{
if ([url.scheme isEqualToString:@"NowWidget"]){
//执行跳转后的操作
}
return YES;
}
3.数据共享
由于widget跟APP间相互独立,如果想用相同的数据则需要两者间数据共享,创建App Group
主APP中 Target
-> Signing & Capability
-> +Capability
-> 添加 App Group
ps:网上说的还需创建申请 APPID 但在开启自动管理 Automatically manage signing
的情况下xcode会自动给你创建相关联的APPID
两者间的数据共享主要通过NSFileManager
和NSUserDefaults
两种形式。
- 通过NSUserDefaults共享数据
//存数据
NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.imoblife.now"];
[userDefaults setObject:@"content" forKey:@"widget"];
[userDefaults synchronize];
//取数据
NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.imoblife.now"];
NSString *content = [userDefaults objectForKey:@"widget"];
- 通过NSFileManager共享数据
-(BOOL)saveDataByNSFileManager:(NSData *)data
{
NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.com.imoblife.now"];
containerURL = [containerURL URLByAppendingPathComponent:@"widget"];
BOOL result = [data writeToURL:containerURL atomically:YES];
return result;
}
-(NSData *)readDataByNSFileManager
{
NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.com.imoblife.now"];
containerURL = [containerURL URLByAppendingPathComponent:@"widget"];
NSData *value = [NSData dataWithContentsOfURL:containerURL];
return value;
}
4.开启折叠及尺寸规定
不需要折叠功能忽略此步骤
- (void)viewDidLoad {
[super viewDidLoad];
//添加折叠效果
self.extensionContext.widgetLargestAvailableDisplayMode = NCWidgetDisplayModeExpanded;
}
//折叠及非折叠样式更改
-(void)widgetActiveDisplayModeDidChange:(NCWidgetDisplayMode)activeDisplayMode withMaximumSize:(CGSize)maxSize {
/**
iOS10以后,重新规定了Today Extension的size。宽度是固定(例如在iPhone6上是359),所以无法改变;但是高度方面,提供了两种模式:
NCWidgetDisplayModeCompact:固定高度,则为110
NCWidgetDisplayModeExpanded:可以变化的高度,区间为110~616
*/
if (activeDisplayMode == NCWidgetDisplayModeCompact) {
self.preferredContentSize = CGSizeMake([UIScreen mainScreen].bounds.size.width-16, 110);
} else {
self.preferredContentSize = CGSizeMake([UIScreen mainScreen].bounds.size.width-16, 250);
}
}
//此方法主要执行刷新操作
- (void)widgetPerformUpdateWithCompletionHandler:(void (^)(NCUpdateResult))completionHandler {
// Perform any setup necessary in order to update the view.
// If an error is encountered, use NCUpdateResultFailed
// If there's no update required, use NCUpdateResultNoData
// If there's an update, use NCUpdateResultNewData
completionHandler(NCUpdateResultNewData);
}
5.文件共享及pods共享
-
文件共享
文件共享.png
勾选共享widget选项即可 -
pods共享
正常使用下widget中无法使用pods导入的第三方SDK如Masonry等,会造成布局等极其不便,因此需要共享pods,在Podfile中需要另设置并重新install
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '9.0'
inhibit_all_warnings!
#共享Masonry
def share_pods
pod 'HandyJSON'
end
target "targetName" do
pod 'AFNetworking'
share_pods
end
target "widgetTargetName" do
share_pods
end
完成后即可使用pods中的第三方SDK了
#import <Masonry.h>
#import <SDWebImage/UIImageView+WebCache.h>
#import <SDWebImageDownloader.h>
#import <SDImageCache.h>
#import <AFNetworking.h>
...
Pods第三方SDK使用错误提示
如果在pods导入共享第三方库,或者使用[UIApplication sharedApplication]
方法报错如下时
not available on iOS (App Extension) - Use view controller based solutions where appropriate instead.
则需要在pods Target
里面,选中出错的SDK并点击buildSettings
搜索Require
然后把Require Only App-Extension-Safe API
然后把YES改为NO
即可
ps:工程项目里也可按照这个方法去排查原因
在调试widget功能时不要忘记将Device
变更为widget项目 🤦♀️🤦♀️🤦♀️
网友评论