自iOS8之后煤蹭,蘋果支持了擴(kuò)展(Extension)的開發(fā)码泛,開發(fā)者可以通過系統(tǒng)提供給我們的擴(kuò)展接入點(diǎn) (Extension point) 來為系統(tǒng)特定的服務(wù)提供某些附加的功能逝变。
所謂Widget憎夷,就是我們熟知的小組件佛舱,這是獨(dú)立于應(yīng)用之外的又一個(gè)新小應(yīng)用,但是和主應(yīng)用之間又有著一定的關(guān)系掏膏。
本文介紹的是iOS14系統(tǒng)以下的widget組件,也就是Todat Extension
iOS14系統(tǒng)以上widget請見:
iOS14 Widget(Widget Extension)小組件開發(fā)
widget實(shí)現(xiàn)
1.創(chuàng)建添加Todat Extension
File
-> New
-> Target
-> Todat Extension
2.添加widget的URL Schemes
由于extension 和主app 是兩個(gè)完全獨(dú)立的進(jìn)程腰池,所以它們之間不能直接相互跳轉(zhuǎn)尾组。為了實(shí)現(xiàn) Widget 調(diào)起 APP忙芒,這里通過 openURL
的方式來啟動(dòng) 主app示弓。
主APP中 Target
-> Info
-> URL Types
-> +
調(diào)用方式
widget中點(diǎn)擊跳轉(zhuǎn)事件添加如下代碼
[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"]){
//執(zhí)行跳轉(zhuǎn)后的操作
}
return YES;
}
3.數(shù)據(jù)共享
由于widget跟APP間相互獨(dú)立,如果想用相同的數(shù)據(jù)則需要兩者間數(shù)據(jù)共享呵萨,創(chuàng)建App Group
主APP中 Target
-> Signing & Capability
-> +Capability
-> 添加 App Group
ps:網(wǎng)上說的還需創(chuàng)建申請 APPID 但在開啟自動(dòng)管理 Automatically manage signing
的情況下xcode會(huì)自動(dòng)給你創(chuàng)建相關(guān)聯(lián)的APPID
兩者間的數(shù)據(jù)共享主要通過NSFileManager
和NSUserDefaults
兩種形式奏属。
- 通過NSUserDefaults共享數(shù)據(jù)
//存數(shù)據(jù)
NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.imoblife.now"];
[userDefaults setObject:@"content" forKey:@"widget"];
[userDefaults synchronize];
//取數(shù)據(jù)
NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.imoblife.now"];
NSString *content = [userDefaults objectForKey:@"widget"];
- 通過NSFileManager共享數(shù)據(jù)
-(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.開啟折疊及尺寸規(guī)定
不需要折疊功能忽略此步驟
- (void)viewDidLoad {
[super viewDidLoad];
//添加折疊效果
self.extensionContext.widgetLargestAvailableDisplayMode = NCWidgetDisplayModeExpanded;
}
//折疊及非折疊樣式更改
-(void)widgetActiveDisplayModeDidChange:(NCWidgetDisplayMode)activeDisplayMode withMaximumSize:(CGSize)maxSize {
/**
iOS10以后,重新規(guī)定了Today Extension的size潮峦。寬度是固定(例如在iPhone6上是359)囱皿,所以無法改變勇婴;但是高度方面,提供了兩種模式:
NCWidgetDisplayModeCompact:固定高度嘱腥,則為110
NCWidgetDisplayModeExpanded:可以變化的高度耕渴,區(qū)間為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);
}
}
//此方法主要執(zhí)行刷新操作
- (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共享
-
文件共享
勾選共享widget選項(xiàng)即可 pods共享
正常使用下widget中無法使用pods導(dǎo)入的第三方SDK如Masonry等,會(huì)造成布局等極其不便齿兔,因此需要共享pods橱脸,在Podfile中需要另設(shè)置并重新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使用錯(cuò)誤提示
如果在pods導(dǎo)入共享第三方庫,或者使用[UIApplication sharedApplication]
方法報(bào)錯(cuò)如下時(shí)
not available on iOS (App Extension) - Use view controller based solutions where appropriate instead.
則需要在pods Target
里面分苇,選中出錯(cuò)的SDK并點(diǎn)擊buildSettings
搜索Require
然后把Require Only App-Extension-Safe API
然后把YES改為NO
即可
ps:工程項(xiàng)目里也可按照這個(gè)方法去排查原因
在調(diào)試widget功能時(shí)不要忘記將Device
變更為widget項(xiàng)目 ??♀???♀???♀?