前言:网上一搜这个关键词【UNNotificationServiceExtension】,一片片的教程。但是每一个都特么转载自【徐不同】,窝草,毫无更改。只想淡淡吐槽一句MMP!!
本文说的一种app和extension的通信问题。
需求:需要统计推送到达率。再extension中进行数据上报处理操作。废话不多提开始操作。
1、新建target(网上一坨,这里不赘述了)
2、断点调试!!!
这个问题MMP困扰了我好长时间。
1运行app
2【Xcode】——【Debug】——【Attach to Process PID or Name】添加新建的target名字 如图1.0,添加之后会出现NotificationService Waiting to Attach
如图2.0
3 点击工程,选择target运行 如图3.0
4 选择自己的宿主app 如图4.0
3、证书问题
NotificationService自动签名,但代码签名身份iPhone开发人员:xxxxx已手动指定。在build settings编辑器中为“iPhone开发人员”设置代码签名标识值,或者在项目编辑器中切换到手动签名。
方法1 点击Automatically manage siging 系统会帮你生成一个证书
方法2 app总会上架,还是自己新建证书为好。手把手教你推送证书
4、用工具进行推送测试
工具1:SmartPush
工具2:Easy APNS Provider
推送格式:
{
"aps": {
"alert": "This is some fancy message.",
"badge": 1,
"sound": "default",
"mutable-content": "1",
"imageAbsoluteString": "http://upload.univs.cn/2012/0104/1325645511371.jpg"
}
}
这里我们要注意一定要有"mutable-content": "1",以及一定要有Alert的字段,否则可能会拦截通知失败。(苹果文档说的)。
打个断点,可以调试了!!!
怎么通信呢?
在app Podfile里加入target 与app同级
target 'NotificationService' do
pod 'xxx'
end
但是我引用的库中使用了 [UIApplication sharedApplication]
extexsion中是不允许这样使用的、
怎么办?只能换方式
在默认情况下,iOS的应用是存在一个沙盒里面的,不允许应用与应用直接进行数据的交互。为此,苹果提供了一项叫App Groups的服务,该服务允许开发者可以在自己的应用之间通过NSUserDefaults、NSFileManager或者CoreData来进行相互的数据传输。
下面介绍如何激活App Groups服务:
-
首先要有一个独立的AppID(带通配符*号的AppID是不允许激活App Groups的)
然后打开容器应用的项目配置的Capabilities页签,激活App Groups特性,如图:
- 点击+号添加一个App Groups,点击OK按钮
- 创建完成后,XCode会自动把应用添加到新建的分组中。如图:
- 上述步骤完成后,容器程序的App Groups已经算是设置完成。然后轮到Share Extension插件需要激活App Groups服务,设置步骤跟容器程序相同,唯一不同的是,插件不需要创建新的App Group,只要加入到容器程序刚才创建的Group即可(这里可以理解为,哪些应用要实现共享数据,那么他们必须在同一个Group里面)。如图:
至此,应用和扩展的App Groups服务都已经启动,现在就要进行分享内容的传输操作。下面分别介绍一下NSUserDefaults、NSFileManager以及CoreData三种方式是如何实现App Groups下的数据操作:
-
NSUserDefaults
:要想设置或访问Group的数据,不能在使用standardUserDefaults方法来获取一个NSUserDefaults对象了。应该使用initWithSuiteName:方法来初始化一个NSUserDefaults对象,其中的SuiteName就是创建的Group的名字,然后利用这个对象来实现,跨应用的数据读写,代码如下:
//初始化一个供App Groups使用的NSUserDefaults对象
NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.cn.vimfung.ShareExtensionDemo"];
//写入数据
[userDefaults setValue:@"value" forKey:@"key"];
//读取数据
NSLog(@"%@", [userDefaults valueForKey:@"key"]);
-
NSFileManager
:通过调用 containerURLForSecurityApplicationGroupIdentifier:方法可以获得AppGroup的共享目录,然后在此目录的基础上实现任意的文件操作。代码如下:
//获取分组的共享目录
NSURL *groupURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.cn.vimfung.ShareExtensionDemo"];
NSURL *fileURL = [groupURL URLByAppendingPathComponent:@"demo.txt"];
//写入文件
[@"abc" writeToURL:fileURL atomically:YES encoding:NSUTF8StringEncoding error:nil];
//读取文件
NSString *str = [NSString stringWithContentsOfURL:fileURL encoding:NSUTF8StringEncoding error:nil];
NSLog(@"str = %@", str);
- CoreData:其实CoreData是基于NSFileManager取得共享目录后来实现数据共享的。即在初始化CoreData时,先使用NSFileManager取得共享目录,然后再指定共享目录为存储数据文件的目录(如存储的sqlite文件)。代码如下:
//获取分组的共享项目
NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.cn.vimfung.ShareExtensionDemo"];
NSURL *storeURL = [containerURL URLByAppendingPathComponent:@"DataModel.sqlite"];
//初始化持久化存储调度器
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"DataModel" withExtension:@"momd"];
NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
[coordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeURL
options:nil
error:nil];
//创建受控对象上下文
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[context performBlockAndWait:^{
[context setPersistentStoreCoordinator:coordinator];
}];
我使用的是NSUserDefault
然后在app中- (void)applicationDidBecomeActive:(UIApplication *)application
中进行数据的读取。
参考文章:
App Extension
iOS扩展开发攻略(一) - Share Extension