iOS10.0发布啦(貌似过去有点时间了吧 - -),在宏观带给我们使用体验的提升之外,更多的是带给iOS开发者一定的欣喜。
因为我们又要学习新东西来适配10啦。
博文所说的Widget(以下称之为拓展应用)并不是iOS10系统新推出的插件化应用(其实早在iOS8上就已经出现啦,只不过楼主是在iOS10发布之后才算真正的关注它,实在是惭愧呀)。iOS10之前它仅仅是存在于通知那一栏中,至于多隐蔽我就不说了吧。但在iOS10之后获得重生,地位获得了巨大的提升,从这点也不难看出苹果增加了对它的重视。尽管公司的App没有适配Widget,但作为一个“后知后觉”的iOS开发者,注意到了但不研究一下就说不过去了吧?
为了避免真实情况与博文的图不太符合,这里声明一下:楼主用的IDE是最新版的Xcode8.0(没办法,还是迫不及待的进行了升级0.0),可能会与其他版本的Xcode界面不太一样
博文中的所有代码:https://github.com/RITL/WidgetDemo(如果有用请star支持一下,感谢)
预览图
这里附上Widget Demo中完成后的预览图: 这里会稍有不同,如果使用Xcode7及之前版本IDE编译的应用(后面称作宿主应用),那么找到Widget的方法如图1;如果是Xcode8编译的宿主应用,那么可以直接通过3D Touch唤起Widget,当然通过第一种也是可以的。不过两者本质是一样的。
创建Widget Extension
1.首先创建一个新的Target: New->Target,Xcode8 会出现如下界面,选择Today Extension,命名为WidgetExtension:
2、创建完毕,则会出现如下文件夹,名字什么的不是问题,一般创建好的名字都为TodayViewController,我只不过是改了改名字而已O(∩_∩)O
3、这里啰嗦一句,虽然作为应用的拓展,但这两个应用是“独立”存在的,你也可以认为这拓展应用与宿主应用是两个完全独立的应用,这也就是说明在开发过程中会出现一些共享的问题,不过共享问题下面博文会有介绍。在此之前,对于拓展应用,我们也是要去开发者申请APP ID以及开发,发布证书的。
由于楼主只是为了学习,用了Xcode8的Automatically manager signing,它的作用是自动生成id以及证书。
作用细说一点就是:如果开发Team没有相应的APP ID,那么Xcode会自动生成APP ID; 如果没有创建相应的证书,那么它会自动创建证书 (当然,正常开发过程中,还是建议手动去创建ID以及配置证书吧)
4、证书都配置完毕,运行,添加Widget,就可以看到咱们的项目已经具备了Widget的拓展功能,默认的是MainInterface.storyboard上的内容啦:(我改了改Label上的字,O(∩_∩)O)
布局方式interface builder or coding
如果牵扯到UI绘制的方式,这里只需要调整一点东西即可。Demo中楼主选用的是使用storyboard完成快速布局,当然,如果开发者习惯使用代码来完成布局,依旧是可以的。需要对拓展应用的info.plist文件做如下操作:
使用interface builder
这个是默认的,如果修改了默认的storyboard,只需要将NSExtensionMainStoryboard
的value修改成相应的storyboard名字即可
使用coding
首先将NSExtensionMainStoryboard
字段删除,添加NSExtensionPrincipalClass
字典,value为主控制器的类名即可。
使用这个方法不要忘记在todayViewController的ViewDidLoad中设置preferredContentSize属性调整大小。
数据共享
很多的时候我们需要Widget与宿主应用共享一些数据,想到数据共享,如果是单一的APP,我们的方法是很多的,比如单例,文件等形式,但由于拓展与宿主应用是两个完全独立的App,并且iOS应用基于沙盒的形式,所以一般的共享数据方法都是实现不了数据共享,这里就需要使用App Groups。
App Groups
1、首先需要在开发者网站注册一个App Groups
2、在 宿主应用 以及 拓展应用 中将App Groups打开,选中需要共享数据的group
两种共享数据的方式
使用UserDefaults共享数据
NSUserDefaults大家应该都是非常熟悉的了,通常用法就是
//获取UserDefaults的单例对象,完成对应用内相关数据的持久化储存
[NSUserDefaults standardUserDefaults];
正像之前所说,由于沙盒机制,拓展应用是不允许访问宿主应用的沙盒路径的,因此上述用法是不对的,需要搭配app group完成实例化UserDefaults,使用UserDefaults类进行数据共享楼主封装为RITL_ShareDataDefaultsManager
通过groups实例化UserDefaults对象的代码如下:
//组名
private static let groupIdentifier : String = "group.com.yue.WidgetTest"
/// 获得userDefualt对象
private