ios UNNotificationServiceExtension app和extension的通信

前言:网上一搜这个关键词【UNNotificationServiceExtension】,一片片的教程。但是每一个都特么转载自【徐不同】,窝草,毫无更改。只想淡淡吐槽一句MMP!!

本文说的一种app和extension的通信问题。
需求:需要统计推送到达率。再extension中进行数据上报处理操作。废话不多提开始操作。

1、新建target(网上一坨,这里不赘述了)
ios UNNotificationServiceExtension app和extension的通信_第1张图片
image.png
ios UNNotificationServiceExtension app和extension的通信_第2张图片
image.png
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

ios UNNotificationServiceExtension app和extension的通信_第3张图片
1.0.png
ios UNNotificationServiceExtension app和extension的通信_第4张图片
2.0.png
ios UNNotificationServiceExtension app和extension的通信_第5张图片
3.0.png
ios UNNotificationServiceExtension app和extension的通信_第6张图片
4.0.png
3、证书问题
ios UNNotificationServiceExtension app和extension的通信_第7张图片
image.png

NotificationService自动签名,但代码签名身份iPhone开发人员:xxxxx已手动指定。在build settings编辑器中为“iPhone开发人员”设置代码签名标识值,或者在项目编辑器中切换到手动签名。

方法1 点击Automatically manage siging 系统会帮你生成一个证书


image.png

方法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的)


    ios UNNotificationServiceExtension app和extension的通信_第8张图片
    image.png
  • 然后打开容器应用的项目配置的Capabilities页签,激活App Groups特性,如图:

ios UNNotificationServiceExtension app和extension的通信_第9张图片
image.png
  • 点击+号添加一个App Groups,点击OK按钮
ios UNNotificationServiceExtension app和extension的通信_第10张图片
image.png
  • 创建完成后,XCode会自动把应用添加到新建的分组中。如图:
ios UNNotificationServiceExtension app和extension的通信_第11张图片
image.png
  • 上述步骤完成后,容器程序的App Groups已经算是设置完成。然后轮到Share Extension插件需要激活App Groups服务,设置步骤跟容器程序相同,唯一不同的是,插件不需要创建新的App Group,只要加入到容器程序刚才创建的Group即可(这里可以理解为,哪些应用要实现共享数据,那么他们必须在同一个Group里面)。如图:
ios UNNotificationServiceExtension app和extension的通信_第12张图片
image.png

至此,应用和扩展的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

你可能感兴趣的:(ios UNNotificationServiceExtension app和extension的通信)