App Today Extension开发注意事项
从iOS 8起,就有了App Extension。Extension的种类至今也扩充到了19种,应用也很广泛,值得重点关注起来。
Extension几乎可以看做一个内嵌的独立App,拥有独立的BundleID、证书、概要配置文件、进程空间、沙盒等等。只是需要打包在App内,类似于寄生在宿主App内,捆绑安装。不过一旦安装应用后,扩展可以由系统独立调用,执行扩展内的代码逻辑。
这篇只记录之前开发Today Extension的过程中,值得注意的事项。其实大多都是通用的。
1.创建Extension和证书管理
在已创建的项目中,新建File->New->Target->Today Extension,确定名称后,就可以在工程文件的Targets列表中,看到新建的extension。
在General栏可以看到,Extension有独立的Identity内容,Bundle Identifier一般具有宿主应用的Bundle Identifier前缀。如果使用Xcode8的自动管理证书,并登录了开发者账号,可以在开发者中心看到自动创建的该AppID。
接着为该AppID创建Provisioning files即可。
2.MainInterface.storyboard和主要的类
新创建的Extension与App的主Target分别在不同的文件目录下,彼此隔离。主界面、Info.plist和本地化文件等都是单独管理的,所以可创建并修改InfoPlist.strings的本地化文件中CFBundleDisplayName字段,单独为扩展命名,如果不修改,将默认使用宿主App的显示名称。
扩展和宿主App是隔离的,不能使用彼此的类、框架、资源,如果想使用宿主的类库或者资源文件等,最直接的办法就是拷贝到当前Target或者增加需要Link的框架。不过,查看Extension的Build Settings,Prefix Header可以填写宿主App的Prefix Header,并使用其引用头文件中的宏定义。
扩展默认使用了MainInterface.storyboard,并绑定了一个类TodayViewController,并已经创建了一个Hello World视图,我们可以直接使用并修改。但是如果不想使用storyboard或者需要修改启动类,可以将Info.plist文件中NSExtension字典的NSExtensionMainInterface项去掉,增加NSExtensionPrincipalClass项,value则为指定启动类的类名,例如TodayViewController。
3.生命周期
扩展的视图控制器与宿主的视图控制器一样,具有常见的生命周期方法。例如当第一次在下拉的“今日”列表中显示本应用扩展,则会执行viewDidLoad方法,然后依次执行其他方法;消失和再次出现,则会调用disappear和appear系列方法;即将被销毁时候,调用dealloc方法。
4.Today Extension的size
iOS10以后,重新规定了Today Extension的size。宽度是固定(例如在iPhone6上是359),所以无法改变;但是高度方面,提供了两种模式:
NCWidgetDisplayModeCompact:固定高度,则为110
NCWidgetDisplayModeExpanded:可以变化的高度,区间为110~616
使用如下代码可以修改模式:
if ([[UIDevice currentDevice].systemVersion floatValue] >= 10) {
self.extensionContext.widgetLargestAvailableDisplayMode = NCWidgetDisplayModeExpanded;
}
我们可以在NCWidgetProviding协议的如下代理方法中,取到size的最大范围:
- (void)widgetActiveDisplayModeDidChange:(NCWidgetDisplayMode)activeDisplayMode withMaximumSize:(CGSize)maxSize NS_AVAILABLE_IOS(10_0);
用如下方法确定边距:
- (UIEdgeInsets)widgetMarginInsetsForProposedMarginInsets:(UIEdgeInsets)defaultMarginInsets NS_DEPRECATED_IOS(8_0, 10_0, "This method will not be called on widgets linked against iOS versions 10.0 and later.");
如果需要修改Widget展示的背景高度,可以修改属性:self.preferredContentSize
5.数据共享
既然扩展与宿主App是隔离的,那么数据共享就需要使用App Groups了。
在App主Target的Capabilities栏,找到App Groups项,开启功能,并点击“+”符号添加一个共享的数据容器名称,例如group.xxx。然后会发现主Target和扩展Target目录中都生成了一个entitlements类型文件,记录了一个App Groups项。
这个共享的容器,就是存放扩展和宿主App共用的数据的空间。
为了正常编译,还需要前往开发者中心,编辑主应用和扩展的AppID,开启支持App Groups功能,类似于开启推送功能。
配置完成后,就是使用了。不管是采用UserDefaults、Archive、CoreData、FMDB、LevelDB等哪种数据存储或操作方式,只需要将路径指向共享的容器路径就可以。
例如使用UserDefaults方式:
NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.xxx"]; [defaults setObject:@"xxxxx" forKey:@"phoneNum"];
只是打开了指定的UserDefaults对象,使用的实例方法为initWithSuiteName。
其他方式同理。
6.类库和资源共享
前面提到,扩展需要使用宿主Target的类库和资源,可以直接拷贝到扩展Target目录下,但是这样做会增加应用体积。
另一个方法,就是创建framework动态链接库。新建File->New->Target->Framework,得到一个新的Target,与系统的框架类似,我们可以自由添加类文件封装功能,只暴露public头文件供调用。在Build Phases栏的Headers项中,将Project组的头文件拖动到Public组即可。
framework也有Bundle ID,但是不需要关注,并且不需要配置证书。
需要注意的是,新建的动态链接库,一般会自动创建同名的头文件,可以直接在其中引用需要暴露的自定义类头文件。但是如果删除了该头文件,可能会有如下警告:
warning: no umbrella header found for target 'OrderFoodTodayKit', module map will not be generated
另外一个需要特别注意的地方,因为我们创建的动态链接库是需要提供给扩展使用的,而扩展不支持部分Api,所以该framework中就需要除去扩展不支持的部分Api。在framework的General栏的Deployment Info中,勾选Allow app extension API only。这样的话,如果在framework中使用了扩展不支持的Api,编译会报错。
7.Today Extension调起宿主App
如果需要从Today Extension中调起宿主App,可以使用宿主App的Url Scheme方式:
[self.extensionContext openURL:[NSURL URLWithString:@"xxxx://xxxx"] completionHandler:nil];
以上就是开发过程中,需要注意的事项记录。
完整的开发教程,推荐查阅:http://www.cocoachina.com/ios/20141023/10027.html
App Today Extension开发注意事项的更多相关文章
- 跨平台移动APP开发进阶(一)mui开发注意事项
mui开发注意事项 Mui HTML5开发框架 mui是一个高性能的HTML5开发框架,从UI到效率,都在极力追求原生体验:这个框架自身有一些规则,刚接触的同学不很熟悉,特总结本文:想了解mui更详细 ...
- MUI开发注意事项
mui开发注意事项,有需要的朋友可以参考下. mui是一个高性能的HTML5开发框架,从UI到效率,都在极力追求原生体验:这个框架自身有一些规则,刚接触的同学不很熟悉,特总结本文:想了解mui更详细的 ...
- Android Library开发注意事项
Android Library开发注意事项 App Module添加依赖Android Library时可以设置library的优先级, 在编译时,app按照library从低到高的优先级依次与每个l ...
- 移动端App uni-app + mui 开发记录
前言 uni-app uni-app是DCloud推出的终极跨平台解决方案,是一个使用Vue.js开发所有前端应用的框架,官网:https://uniapp.dcloud.io/ mui 号称最接近原 ...
- 【VS开发】ActiveX开发注意事项
[VS开发]ActiveX开发注意事项 标签:[VS开发] 注意:必须在工程的app文件的InitInstance()中加入如下代码,否则动态创建控件不会成功: AfxEnableControlCon ...
- 使用IBM Blockchain Platform extension开发你的第一个fabric智能合约
文章目录 安装IBM Blockchain Platform extension for VS Code 创建一个智能合约项目 理解智能合约 打包智能合约 Local Fabric Ops 安装智能合 ...
- uni-app开发注意事项
关于vue 1.注意 如果使用老版的非自定义组件模式,即manifest中"usingComponents":false,部分模版语法不支持,但此模式已于2019年11月起下线. ...
- delphi 串口 关于RS485总线通信协议开发注意事项
http://blog.csdn.net/shjhuang/article/details/9426739 关于RS485总线通信协议开发注意事项 1 前言 近段时间发现我们系统在进行设备 ...
- 实战使用Axure设计App,使用WebStorm开发(6) – 迈向后端
系列文章 实战使用Axure设计App,使用WebStorm开发(1) – 用Axure描述需求 实战使用Axure设计App,使用WebStorm开发(2) – 创建 Ionic 项目 实战使 ...
随机推荐
- jQuery选择器(二)
jQuery中有"过滤选择器",通过特定的规则来筛选出所需的DOM元素,都是以(:)开头的. $("div:first")//选取出所有<div>元 ...
- 想要提高网页转换率?试试这16 个UI 秘诀
优异的使用者介面(user interface,UI)让使用者用得顺心,从而提高转换率(conversion rate),换言之,好的UI在使用与销售层面上形成双赢.UI设计师Jakub Linows ...
- 利用Travis CI 让你的github项目持续构建
Travis CI 是目前新兴的开源持续集成构建项目,它与jenkins,GO的很明显的特别在于采用yaml格式,简洁清新独树一帜.目前大多数的github项目都已经移入到Travis CI的构建队列 ...
- Wamp 简单使用方法
1.在wamp的安装目录 \bin\apache\Apache2.4.4\conf 中找到 httpd.conf文件删除 Include conf/extra/httpd-vhosts.conf 这 ...
- AMD64和i386的区别
下载Debian系统时,出现两个选项:ADM64和i386,那么这两者的区别是什么? i386=Intel 80386.其实i386通常被用来作为对Intel(英特尔)32位微处理器的统称. AMD6 ...
- 自己对Debug的一些感悟
A.13-03-06记. 1.当项目中发现bug的时候,首先考虑如何重现,能够重现的bug比较好找寻根源. 2.思考下以前是否发现过类似bug,是否由一些外部配置所决定. 3.有循环时候注意临界条件.
- 线程池ThreadPool的初探
一.线程池的适用范围 在日常使用多线程开发的时候,一般都构造一个Thread示例,然后调用Start使之执行.如果一个线程它大部分时间花费在等待某个事件响应的发生然后才予以响应:或者如果在一定期间内重 ...
- CSRF 防御策略
在业界目前防御 CSRF 攻击主要有三种策略:验证 HTTP Referer 字段:在请求地址中添加 token 并验证:在 HTTP 头中自定义属性并验证.下面就分别对这三种策略进行详细介绍. 验证 ...
- hibernate----N-N--(人与地点)
package com.ij34.dao; import java.util.HashSet; import java.util.Set; import javax.persistence.*; @E ...
- 实现在Android 进程和线程
进程和线程 如果某个应用程序组件是第一次被启动,且这时应用程序也没有其他组件在运行,则Android系统会为应用程序创建一个包含单个线程的linux进程.默认情况下,同一个应用程序的所有组件都运行在同 ...