Today Extension是ios8開始推出的一個重大更新,它與宿主工程是相互獨立的,到目前已經有不少app實現了這一功能,可是該功能在ios10系統上才得以真正的發揮。
extension規定不能直接與它的宿主工程host app進行通信,也不能共享之間的代碼,可是能夠經過添加framework
共享代碼塊。
在ios八、9中today extension沒有摺疊和展開功能,在這兩個系統中只有下拉刷新;而後在ios10系統中,today extension是經過右滑界面而出現的,此時只要實現摺疊、展開這兩項就能實現該功能。
同時ios八、ios9與ios10中的toaday extension界面有些區別,iOS10之前的版本中today extension 的背景顏色是黑色帶有磨砂效果的;而ios10及以上系統是白色帶磨砂的
Extension可使用的內存遠遠低於app可使用的內存,所以當內存吃緊的時候,會優先殺死extension。因此在開發的過程當中應該注意內存的使用
開發過程當中,有些API接口不可用與Extension中,在系統中使用NS_EXTENSION_UNAVAILABLE
標明html
先建立宿主功能,若在已有的工程上添加today extension可忽略第一步ios
項目
--->General
---> +
編程
此時運行工程後,加載extension便可顯示Hello World字樣是工程原配的bash
我的比較喜歡純代碼開發,storyboard在多人合做時,容易產生衝突和矛盾。
步驟:網絡
storyboard
以及Info.plist
中的NSExtension
->NSExtensionMainStoryboard
Info.plist
中的NSExtension
添加NSExtensionPrincipalClass
字段,對應的value值TodayViewController
注意:宿主工程中的App Groups
必須與Extension中的App Groups
保持一致app
在extension中能夠用NSUserDefault
、NSFileManager
、NSFileCoordination
、CoreData
、Sqlite
等進行數據共享。
官方建議在iOS8.2以上系統中使用UIDocument
來協調共享數據,在ios9以上系統中使用NSFileCoordinator
類進行數據共享,可是當應用程序擴輾轉換到後臺時,必須刪除NSFilePresenter
對象
首先咱們在宿主工程中,存點數據框架
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSUserDefaults *userDefault = [[NSUserDefaults alloc] initWithSuiteName:@"group.dyTodayExtension"];
[userDefault setObject:@"tips" forKey:@"group.dyTodayExtension.tips"];
}
@end複製代碼
在Extension取出數據顯示ide
#import "TodayViewController.h"
#import <NotificationCenter/NotificationCenter.h>
@interface TodayViewController () <NCWidgetProviding>{
UILabel *_textLabel;
UIView *_subView;
}
@end
@implementation TodayViewController
- (void)viewDidLoad {
[super viewDidLoad];
//設置extension的size
self.preferredContentSize = CGSizeMake(0, 150);
_subView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 150)];
_subView.backgroundColor = [UIColor grayColor];
[self.view addSubview:_subView];
_textLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 10, _subView.frame.size.width, 50)];
_textLabel.numberOfLines = 0;
_textLabel.textAlignment = NSTextAlignmentCenter;
_textLabel.backgroundColor = [UIColor brownColor];
_textLabel.textColor = [UIColor greenColor];
[_subView addSubview:_textLabel];
NSUserDefaults *userDefault = [[NSUserDefaults alloc] initWithSuiteName:@"group.DonYau.today"];
NSString *textStr = [userDefault valueForKey:@"group.DonYau.today.tips"];
_textLabel.text = textStr;
}複製代碼
此時運行工程,能夠看到咱們在宿主工程保存的數據,在Extension中也能夠獲取到工具
在宿主工程中配置URL Schemes
,而後添加點擊事件,當咱們點擊button時,就會跳轉到宿主工程ui
#import "TodayViewController.h"
#import <NotificationCenter/NotificationCenter.h>
@interface TodayViewController () <NCWidgetProviding>{
UILabel *_textLabel;
UIView *_subView;
}
@end
@implementation TodayViewController
- (void)viewDidLoad {
[super viewDidLoad];
//設置extension的size
self.preferredContentSize = CGSizeMake(0, 150);
_subView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 150)];
_subView.backgroundColor = [UIColor grayColor];
[self.view addSubview:_subView];
_textLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 10, _subView.frame.size.width, 50)];
_textLabel.numberOfLines = 0;
_textLabel.textAlignment = NSTextAlignmentCenter;
_textLabel.backgroundColor = [UIColor brownColor];
_textLabel.textColor = [UIColor greenColor];
[_subView addSubview:_textLabel];
NSUserDefaults *userDefault = [[NSUserDefaults alloc] initWithSuiteName:@"group.DonYau.today"];
NSString *textStr = [userDefault valueForKey:@"group.DonYau.today.tips"];
_textLabel.text = textStr;
UIButton *openApp = [[UIButton alloc] initWithFrame:CGRectMake(0, 60 , _subView.frame.size.width, 30)];
openApp.backgroundColor = [UIColor blueColor];
[openApp setTitle:@"打開app" forState:UIControlStateNormal];
[openApp setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[_subView addSubview:openApp];
[openApp addTarget:self action:@selector(openApp) forControlEvents:UIControlEventTouchUpInside];
}
- (void)openApp{
[self.extensionContext openURL:[NSURL URLWithString:@"todayExtension:"] completionHandler:^(BOOL success) {
}];
}複製代碼
咱們能夠在宿主工程中經過AppDelegate的代理方法獲取從Extension傳過來的數據
-(BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options{
return YES;
}複製代碼
咱們建立好Today Extension
時,工程已經自動建立好更新的回調,所以咱們能夠在該代理方法中監控Today Extension
的更新操做
- (void)widgetPerformUpdateWithCompletionHandler:(void (^)(NCUpdateResult))completionHandler {
-
completionHandler(NCUpdateResultNewData);
}複製代碼
一樣Today Extension
給咱們提供了代理方法,以肯定內容的偏移
-(UIEdgeInsets)widgetMarginInsetsForProposedMarginInsets:(UIEdgeInsets)defaultMarginInsets{
return UIEdgeInsetsZero;
}複製代碼
當咱們須要收縮擴展功能的時候,首先須要肯定視圖剛開始顯示的時候,添加狀態的顯示。
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
self.extensionContext.widgetLargestAvailableDisplayMode = NCWidgetDisplayModeCompact;
}複製代碼
當咱們在willAppear中設置該屬性後,運行工程便可看到收縮、擴展
功能按鈕
而後遵循代理,以便在狀態發生變化時,更新界面
-(void)widgetActiveDisplayModeDidChange:(NCWidgetDisplayMode)activeDisplayMode withMaximumSize:(CGSize)maxSize{
if (self.extensionContext.widgetActiveDisplayMode == NCWidgetDisplayModeCompact) {
self.preferredContentSize = CGSizeMake(0, 150);
}else{
self.preferredContentSize = CGSizeMake(0, 300);
}
}複製代碼
在使用Today Extension
的過程當中,或者咱們在extension使用的工具類恰好在宿主工程中也須要使用,這個時候cocoapods
就幫上咱們的大忙了
好比須要在宿主工程和Extension中使用AFN框架獲取一些網絡的數據,這時候咱們只需配置Podfile
文件便可共享工具類
platform :ios, ‘8.0’
use_frameworks!
def shared_pods
pod 'AFNetworking', '~> 3.1.0'
end
target 'DYTodayDemo' do
shared_pods
end
target 'DYTodayExtensionDemo' do
shared_pods
end複製代碼
當執行pod install
後,工程的配置如圖
error: Embedded binary's bundle identifier is not prefixed with the parent app's bundle identifier
的錯誤時,是由於宿主工程和Extension
的bundle identifier
不符合規範。Extension
中的identifier應該是在宿主工程的bundle identifier
後面加上後綴,好比宿主工程 bundle identifier : com.todayDemo.Example
Extension bundle identifier : com.todayDemo.Example.today複製代碼