App Extension 是 iOS8之后推出的一个新的功能,从开发者的角度来说,苹果提供的接口更加开放了。我们可以通过App Extension去拓展Today,分享,键盘等。在iOS10 又推出了iMessage 和 Siri 的拓展。可见App Extension也越来越重要。
如图所示:
这篇文章主要说明一下App Extension 与 App 之间的数据共享,至于如何创建 App Extension,将会在下一篇iMessage开发中列举。
虽然拓展App 和 原先的App(称作宿主App)在同一个项目中,但他们是两个不同的Targets,各自拥有属于自己的沙盒环境。然而在实际操作中,有时候我们需要在拓展App中使用宿主App的一个数据(比如用户的token),需要引用宿主App的pod库,以及宿主App的一些类。
下面就这三种情况说一下:
1、本地数据
由于沙盒的限制, 通过
NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
无法再拓展App中获取到宿主App的数据。但苹果还是给了我们一调道路,每个拓展App会有一个唯一的GroupID,我们可以通过这个 GroupID 去进行数据交互。如:
在宿主App里保存值
NSUserDefaults *userDefault = [[NSUserDefaults alloc]initWithSuiteName:@"group.xxxxx.IMessageExtension"];
[userDefault setObject:userToken forKey:@"IMessage_User_Token"];
在拓展App里取值
NSUserDefaults *userDefault = [[NSUserDefaults alloc]initWithSuiteName:@"group.xxxxx.IMessageExtension"];
NSString *token = [userDefault objectForKey:@"IMessage_User_Token"];
2、Pod 文件
如果在宿主App里使用了CocoaPods来管理第三方库,那么在拓展App里就无法引入这些第三方库的头文件。否则会报 ‘❌找不到文件’ 的错误。解决方法是:
在宿主App的 podfile 文件中加入下面一句话:
link_with '宿主App的名字', '拓展App的名字'
然后执行 pod update --no-repo-update
。如果你是使用了bundle,执行 bundle exec update --no-repo-update
这样就在宿主App和拓展App之间的建立了pod文件的连接。
也许你会问,如果我只想引入其中的一个或者几个库,这样全部连接是不是有些不妥,如果这样,你也可以这样做:
target '宿主App的名字' do
pod ...
pod ...
pod ...
end
target '拓展App的名字' do
pod ...
end
这样就能自由的在宿主和拓展之间引入的想要的库。
3、宿主App的类文件
在App Extension里是无法使用宿主App的类文件的。但自然有解决之道。
1、直接将宿主App的相关的类拷贝到Extension中。
这种方式简单粗暴。但需要注意的如果这个类中会包含其他类的对象,要把这些类一块拷贝过来。
准确来说,就是把你要引用的类的相关类全部拷贝。至于引用的Pod库中的文件,通过上面的 link_with '宿主App的名字', '拓展App的名字'
已经引用,就不用考虑这些类的引用问题。
2、通过Xcode提供的FrameWork引入文件
相比第一种方式,这样做确实优雅了不少。首先我们要创建一个framework:
打开 file ——>New ——>Target
选择 Cocoa Touch Framework, 我这里命名为FeiAppExtensionKit。完成后如图所示:
我们就可以分别看到了我们的宿主App, App Extension 以及我们刚刚创建的Framework。
这里假设我们要在App Extesion中使用我们的宿主App的 ViewConreoller2 这个类。
首先我们要在该Framework中的 Build Phases —> Complie Sources 中引入该文件。
到这里,我们的Fromework已经包含了我们要引入的头文件。下面要做的就是在宿主App 和 App Extension 中引入我们创建的Framework。
首先我们要 删除 宿主App对 ViewController2的引用
然后,在下方的 的 Link Binary With Library 中引入我们的Framework。
到这里,就剩下最后一步了,就是把我们的Framework引入到App Extension中。
再次运行,成功编译!
需要注意的是,使用Framework这种方法共享文件,也是需要把相关的类全部引入到Framework中去。
但如果类中使用了pod库中的,就需要把Framework与pod文件关联,然后去除宿主App 以及 拓展App 对Pod的引用。最后再引入Framework。
至于哪个方法好,我个人觉得都可以。一般App Extension都不会有太多文件,如果要引入,直接拷贝对App的大小几乎没有影响。当然,Framework的使用也是需要掌握的。