《Today Extension》

簡介

  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

1、宿主工程

  先建立宿主功能,若在已有的工程上添加today extension可忽略第一步ios

2、建立Extension

  項目--->General---> +編程

  此時運行工程後,加載extension便可顯示Hello World字樣是工程原配的bash

3、純代碼開發Extension

  我的比較喜歡純代碼開發,storyboard在多人合做時,容易產生衝突和矛盾。
步驟:網絡

  • 刪除Extension中的storyboard以及Info.plist中的NSExtension->NSExtensionMainStoryboard
  • Info.plist中的NSExtension添加NSExtensionPrincipalClass字段,對應的value值TodayViewController

4、與宿主工程產生關聯

1.建立證書中的APP Groups

2.配置宿主工程的App Groups

3.配置Extension中的App Groups

  注意:宿主工程中的App Groups必須與Extension中的App Groups保持一致app

5、與宿主工程的數據共享

  在extension中能夠用NSUserDefaultNSFileManagerNSFileCoordinationCoreDataSqlite等進行數據共享。
  官方建議在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中也能夠獲取到工具

6、跳轉宿主工程

在宿主工程中配置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;
}複製代碼

7、監控Today Extension的更新

  咱們建立好Today Extension時,工程已經自動建立好更新的回調,所以咱們能夠在該代理方法中監控Today Extension的更新操做

- (void)widgetPerformUpdateWithCompletionHandler:(void (^)(NCUpdateResult))completionHandler {
- 
    completionHandler(NCUpdateResultNewData);
}複製代碼

8、Today Extension偏移的控制

  一樣Today Extension給咱們提供了代理方法,以肯定內容的偏移

-(UIEdgeInsets)widgetMarginInsetsForProposedMarginInsets:(UIEdgeInsets)defaultMarginInsets{
    return UIEdgeInsetsZero;
}複製代碼

9、顯示收縮、擴展功能

  當咱們須要收縮擴展功能的時候,首先須要肯定視圖剛開始顯示的時候,添加狀態的顯示。

-(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);
    }
}複製代碼

十、Cocoapods庫的共用

  在使用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後,工程的配置如圖

遇到的問題

  1. 當運行工程的出現error: Embedded binary's bundle identifier is not prefixed with the parent app's bundle identifier的錯誤時,是由於宿主工程和Extensionbundle identifier不符合規範。
    Extension中的identifier應該是在宿主工程的bundle identifier後面加上後綴,好比
    宿主工程 bundle identifier : com.todayDemo.Example
    Extension bundle identifier : com.todayDemo.Example.today複製代碼

    參考文章

    App Extension編程指南(iOS8/OS X v10.10)中文版
    App Extension Programming Guide
相關文章
相關標籤/搜索