美文网首页
Today Extension

Today Extension

作者: 黄定师 | 来源:发表于2019-05-19 12:45 被阅读0次

前言

简单介绍下APP Extension(应用扩展)中的Today Extension的使用方法。下图就是一个TodayExtension示例。


TodayExtension示例.PNG

实现Today Extension

创建Today Extension

创建TodayExtension.png

有两种方式调出以上会话窗口:
1.点击工程 -> TARGETS -> "+" -> 选择Today Extension;
2.点击File -> New -> Target... -> 选择Today Extension。

工程中的Today Extension文件夹结构:


TodayExtension文件夹.png

代码实现

我一般习惯用Masonry布局,所以要删除MainInterface.storyboard,然后修改info.plist中的NSExtension:


NSExtension.png

下面是主要代码:

// TodayViewController.m中的代码
#import "TodayViewController.h"
#import <NotificationCenter/NotificationCenter.h>
#import <Masonry.h>
#import "TodayTableHeaderView.h"

@interface TodayViewController () <NCWidgetProviding,  UITableViewDataSource, UITableViewDelegate>

@property (nonatomic, strong) UITableView *tableView;

@end

@implementation TodayViewController

#pragma mark - life cycle
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    // 将小组件的展现模式设置为可展开
    if (@available(iOS 10.0, *)) {
        self.extensionContext.widgetLargestAvailableDisplayMode = NCWidgetDisplayModeExpanded;
    }
    
    [self.view addSubview:self.tableView];
    
    [_tableView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.mas_offset(0);
    }];
}

#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 5;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *identifier = @"cellIdentifier";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
    if (!cell) {
        cell = [[UITableViewCell alloc]initWithStyle:(UITableViewCellStyleDefault) reuseIdentifier:identifier];
    }
    
    NSArray *titleArr = @[@"帮助",@"反馈",@"个人信息",@"客服",@"设置"];
    cell.imageView.image = [UIImage imageNamed:titleArr[indexPath.row]];
    cell.textLabel.text = titleArr[indexPath.row];
    
    return cell;
}

#pragma mark - UITableViewDelegate
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    
    UIView *headerView = [[TodayTableHeaderView alloc]init];
    
    return headerView;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSString *path = [NSString stringWithFormat:@"TodayExtension://%zd",indexPath.row];
    NSURL *url = [NSURL URLWithString:path];
    [self openContainingAPPWithURL:url];
}

- (void)openContainingAPPWithURL:(NSURL *)URL {
    [self.extensionContext openURL:URL completionHandler:nil];
}

#pragma mark - NCWidgetProviding
- (void)widgetActiveDisplayModeDidChange:(NCWidgetDisplayMode)activeDisplayMode withMaximumSize:(CGSize)maxSize  API_AVAILABLE(ios(10.0)){
    if (activeDisplayMode == NCWidgetDisplayModeExpanded) {
        // 设置展开的新高度
        self.preferredContentSize = CGSizeMake(0, 335.0);
    }else{
        self.preferredContentSize = maxSize;
    }
}

- (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);
}

#pragma mark - lazy load
- (UITableView *)tableView {
    if (!_tableView) {
        _tableView = [[UITableView alloc]init];
        _tableView.dataSource = self;
        _tableView.delegate = self;
    }
    return _tableView;
}

@end

针对上述代码有两点需要说明:

  1. "TodayExtension://"的作用:实现点击Today Extension时,通过openURL的方式主动调起Containing App(包含Today Extension的宿主应用),所以需要在Containing App中添加URL scheme;


    URL scheme.png
  2. 示例中Today Extension的展示内容是固定的,如果要求内容是由宿主应用决定的,那要怎么实现呢?通常做法是通过app group实现,即宿主应用往app group里写入内容,Today Extension去读取并展示。

// TodayTableHeaderView.m中的代码
#import "TodayTableHeaderView.h"
#import <Masonry.h>

@interface TodayTableHeaderView ()

@property (nonatomic, strong) UIImageView *imageView;
@property (nonatomic, strong) UILabel *label;

@end

@implementation TodayTableHeaderView

- (instancetype)init {
    self = [super init];
    if (self) {
        [self addSubview:self.imageView];
        [self addSubview:self.label];

        // 布局子视图
        [self mas_layoutSubviews];
    }
    return self;
}

- (void)mas_layoutSubviews {
    [self.imageView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.left.mas_offset(15.0);
        make.bottom.mas_offset(-15.0);
        make.height.mas_equalTo(80.0);
        make.width.mas_equalTo(70.0);
    }];
    
    [self.label mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerY.equalTo(self.imageView);
        make.left.equalTo(self.imageView.mas_right).mas_offset(10.0);
    }];
}

#pragma mark - lazy load
- (UIImageView *)imageView {
    if (!_imageView) {
        _imageView = [[UIImageView alloc]init];
        _imageView.image = [UIImage imageNamed:@"son"];
        _imageView.layer.cornerRadius = 8.0;
        _imageView.layer.masksToBounds = YES;
    }
    return _imageView;
}

- (UILabel *)label {
    if (!_label) {
        _label = [[UILabel alloc]init];
        _label.text = @"Hello World";
    }
    return _label;
}

@end
// 宿主应用的AppDelegate.m中的代码
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
    // 处理跳转逻辑
    NSString *absStr = url.absoluteString;
    if ([absStr hasPrefix:@"TodayExtension"]) {
        NSArray *titleArr = @[@"帮助",@"反馈",@"个人信息",@"客服",@"设置"];
        NSInteger index = [[absStr substringFromIndex:absStr.length -1] integerValue];
        HLog(@"用户点击了----%@",titleArr[index]);
    }
    return YES;
}

可能遇到的问题

1.Today Extension展示不出来
解决:检查下是否将Extension的deployment target设置的比宿主应用的deployment target高。如果是的话,将它设置的低于宿主应用。

2.在功能上,宿主应用和Extension是相互独立的,如果Extension想借用宿主应用的代码或者资源,那应该怎么办?
解决:选中要借用的资源,设置Target Membership就好了。

Target Membership.png

3.如果想与宿主应用共享三方框架,如masonry,那应该怎么办?
解决:在podfile里添加一个target,在target里写上你要用的三方框架。

target 'TodayExtension' do
  # Uncomment the next line if you're using Swift or would like to use dynamic frameworks
  # use_frameworks!

  # Pods for TodayExtension

pod 'Masonry'

end

参考文献

iOS - App Extension 整体总结
iOS应用扩展(APP Extension)- Today Extension使用
ios TodayExtension 在真机上不显示简单解决方案

相关文章

  • IOS开发--通知栏扩展(Today Extension)

    使用Today Extension 1.file--new--target--today Extension 提示...

  • Extension

    Today Extension Share Extension Action Extension(UI) 1.插件...

  • Today Extension

    一、前言 extension是iOS8新开放的一种对几个固定系统区域的扩展机制,它可以在一定程度上弥补iOS的沙盒...

  • Today Extension

    前言 简单介绍下APP Extension(应用扩展)中的Today Extension的使用方法。下图就是一个T...

  • iOS Widget 开发小结

    一、 什么是Extension ? 二、 添加Widget 1. 添加Today Extension Xcode菜...

  • iOS Today Extension

    我们项目中想要添加iPhone Today Extension功能,之前没有自己接触过Extension的新功能今...

  • iOS:Today Extension

    PS:此文仅作对TodayExtension的一些简单的使用,且大多参看前辈文章所写,作者目前水平尚水…. 学无止...

  • 关于Today Extension

    第一次写有关技术的博客,有错误的地方请及时纠正。 扩展介绍 效果图: 最近写了一个app需要用到app扩展(App...

  • iOS Today Extension

    什么是Today Extension? 怎么创建? 怎么使用? 不想使用sb? 代码共享 数据共享 什么是Toda...

  • iOS开发一些知识Demo

    RunTime、GCD、KVO、Block、RunLoop、Widget(today extension)、sha...

网友评论

      本文标题:Today Extension

      本文链接:https://www.haomeiwen.com/subject/rnhaaqtx.html