《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
相关文章
相关标签/搜索