本地通知很简单喽,关键是这个零行如何实现? 也许你已经知道了,runtime 嘛,只需要将 AppDelegate 的分类 .m文件拖进工程即可,彻底解放你的 AppDelegate.m;
一.原理解析:
使用runtime 在 +(void)load
替换 UIApplicationDelegate
一些方法的实现,比如:
application:didFinishLaunchingWithOptions:
application:handleActionWithIdentifier:forLocalNotification:completionHandler:
...等等通知相关的代理方法,在自己的方法实现处理通知;
二.上代码:
1.新建 AppDelegate 分类,只要 .m文件即可:
2. 实现基本的方法交换接口:+(void)swapSelector:(SEL)systemSelector toSelector:(SEL)customSelector;
3. 在自己的方法实现中处理通知相关代码:
如下:
1 . 新建 AppDelegate 分类: 略过 ....
2 . 基本接口实现骨架:
+(void)swapSelector:(SEL)systemSelector toSelector:(SEL)customSelector{
// static dispatch_once_t onceToken;
// dispatch_once(&onceToken, ^{
SEL org_Selector = systemSelector;
SEL new_Selector = customSelector;
Method org_method = class_getInstanceMethod([self class], org_Selector);
Method new_method = class_getInstanceMethod([self class], new_Selector);
BOOL isAdd = class_addMethod(self, org_Selector, method_getImplementation(new_method), method_getTypeEncoding(new_method));
if (isAdd) {
class_replaceMethod(self, customSelector, method_getImplementation(new_method), method_getTypeEncoding(new_method));
}else{
method_exchangeImplementations(org_method, new_method);
}
// });
}
注意: 这里的 dispatch_once 是注释掉的!!!!
3 . 在自己的方法实现中处理通知相关代码:
@implementation AppDelegate (LocalNotification)
+(void)load{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{ // 知道为什么上面没有 dispatch_once 了吧;
[self swapSelector:@selector(application:didFinishLaunchingWithOptions:) toSelector:@selector(GIN_application:didFinishLaunchingWithOptions:)];
[self swapSelector:@selector(application:didRegisterUserNotificationSettings:) toSelector:@selector(GIN_application:didRegisterUserNotificationSettings:)];
[self swapSelector:@selector(application:handleActionWithIdentifier:forLocalNotification:completionHandler:) toSelector:@selector(GIN_application:handleActionWithIdentifier:forLocalNotification:completionHandler:)];
[self swapSelector:@selector(application:handleActionWithIdentifier:forLocalNotification: withResponseInfo: completionHandler:) toSelector:@selector(GIN_application:handleActionWithIdentifier:forLocalNotification: withResponseInfo: completionHandler:) ];
[self swapSelector:@selector(application:didReceiveLocalNotification:) toSelector:@selector(GIN_application:didReceiveLocalNotification:)];
});
}
-(BOOL)GIN_application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
[self GIN_application:application didFinishLaunchingWithOptions:launchOptions];
[self configLocalNotificationWithApplication:application];
return YES;
}
-(void)GIN_application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings{
[self GIN_application:application didRegisterUserNotificationSettings:notificationSettings];
/*
* your code (通知相关)
*/
}
-(void)GIN_application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification completionHandler:(void (^)())completionHandler{
[self GIN_application:application handleActionWithIdentifier:identifier forLocalNotification:notification completionHandler:completionHandler];
/*
* your code (通知相关)
*/
}
-(void)GIN_application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void (^)())completionHandler{
[self GIN_application:application handleActionWithIdentifier:identifier forLocalNotification:notification withResponseInfo:responseInfo completionHandler:completionHandler];
/*
* your code (通知相关)
*/
}
-(void)GIN_application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification{
[self GIN_application:application didReceiveLocalNotification:notification];
/*
* your code (通知相关)
*/
}
三.完整代码:
//
// AppDelegate+LocalNotification.m
#import "AppDelegate.h"
#import <UserNotifications/UserNotifications.h>
#import "NSObject+swapMethod.h"
@interface AppDelegate ()<UNUserNotificationCenterDelegate>
@end
NSInteger badge;
@implementation AppDelegate (LocalNotification)
+(void)load{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self swapSelector:@selector(application:didFinishLaunchingWithOptions:) toSelector:@selector(GIN_application:didFinishLaunchingWithOptions:)];
[self swapSelector:@selector(application:didRegisterUserNotificationSettings:) toSelector:@selector(GIN_application:didRegisterUserNotificationSettings:)];
[self swapSelector:@selector(application:handleActionWithIdentifier:forLocalNotification:completionHandler:) toSelector:@selector(GIN_application:handleActionWithIdentifier:forLocalNotification:completionHandler:)];
[self swapSelector:@selector(application:handleActionWithIdentifier:forLocalNotification: withResponseInfo: completionHandler:) toSelector:@selector(GIN_application:handleActionWithIdentifier:forLocalNotification: withResponseInfo: completionHandler:) ];
[self swapSelector:@selector(application:didReceiveLocalNotification:) toSelector:@selector(GIN_application:didReceiveLocalNotification:)];
});
}
-(BOOL)GIN_application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
[self GIN_application:application didFinishLaunchingWithOptions:launchOptions];
[self configLocalNotificationWithApplication:application];
return YES;
}
-(void)configLocalNotificationWithApplication:(UIApplication *)application {
if ([[UIDevice currentDevice] systemVersion].floatValue >= 10.0) {
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
[center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert) completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted) //点击允许
{
NSLog(@"注册通知成功");
[center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
[self registerCalendarNotificationTrigger:YES locationNotificationTrigger:YES];
}];
} else//点击不允许
{
NSLog(@"注册通知失败");
}
}];
//注册推送(同iOS8)
[[UIApplication sharedApplication] registerForRemoteNotifications];
}else if([[UIDevice currentDevice] systemVersion].floatValue < 10.0 &&[[UIDevice currentDevice] systemVersion].floatValue >= 8.0){//iOS8到iOS10
//1.创建消息上面要添加的动作(按钮的形式显示出来)
UIMutableUserNotificationAction *action = [[UIMutableUserNotificationAction alloc] init];
action.identifier = @"action";//按钮的标示
action.title=@"Accept";//按钮的标题
action.activationMode = UIUserNotificationActivationModeForeground;//当点击的时候启动程序
// action.authenticationRequired = YES;
// action.destructive = YES;
UIMutableUserNotificationAction *action2 = [[UIMutableUserNotificationAction alloc] init];
action2.identifier = @"action2";
action2.title=@"Reject";
action2.activationMode = UIUserNotificationActivationModeBackground;//当点击的时候不启动程序,在后台处理
action.authenticationRequired = YES;//需要解锁才能处理,如果action.activationMode = UIUserNotificationActivationModeForeground;则这个属性被忽略;
action.destructive = YES;
//2.创建动作(按钮)的类别集合
UIMutableUserNotificationCategory *categorys = [[UIMutableUserNotificationCategory alloc] init];
categorys.identifier = @"alert";//这组动作的唯一标示,推送通知的时候也是根据这个来区分
[categorys setActions:@[action,action2] forContext:(UIUserNotificationActionContextMinimal)];
//3.创建UIUserNotificationSettings,并设置消息的显示类类型
if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)]) {
UIUserNotificationType type = UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound;
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:type categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
}
}else {//iOS8以下
[application registerForRemoteNotificationTypes: UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound];
}
}
-(void)GIN_application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings{
[self GIN_application:application didRegisterUserNotificationSettings:notificationSettings];
if(notificationSettings.types & UIUserNotificationTypeBadge){
}else if (notificationSettings.types & UIUserNotificationTypeAlert){
}else if (notificationSettings.types & UIUserNotificationTypeSound){
}else if (notificationSettings.types & UIUserNotificationTypeNone){
}else{
// what happened ??
}
}
-(void)registerCalendarNotificationTrigger:(BOOL)calendarTrigger locationNotificationTrigger:(BOOL)locationTrigger{
// 1、创建通知内容,注:这里得用可变类型的UNMutableNotificationContent,否则内容的属性是只读的
UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
content.title = @"小主,还有15分钟就要上班了哦";
content.subtitle = @"快让列车长开快点";
content.body = @"我知道小主很着急,但是注意安全哦";
badge++;
content.badge = [NSNumber numberWithInteger:badge];
content.sound = [UNNotificationSound defaultSound];
NSString *path = [[NSBundle mainBundle] pathForResource:@"search_blue@2x" ofType:@"png"];
UNNotificationAttachment *attachment = [UNNotificationAttachment attachmentWithIdentifier:@"imageIndetifier" URL:[NSURL fileURLWithPath:path] options:nil error:nil];
// 附件 可以是音频、图片、视频 这里是一张图片
content.attachments = @[attachment];
// 标识符
content.categoryIdentifier = @"categoryIndentifier";
// 2、创建通知触发
/* 触发器分三种:
UNTimeIntervalNotificationTrigger : 在一定时间后触发,如果设置重复的话,timeInterval不能小于60
UNCalendarNotificationTrigger : 在某天某时触发,可重复
UNLocationNotificationTrigger : 进入或离开某个地理区域时触发
*/
// UNCalendarNotificationTrigger
if (calendarTrigger) {
NSDateComponents *components = [[NSDateComponents alloc] init];
components.hour = 8;
components.minute = 45;
components.second = 0;
UNCalendarNotificationTrigger *cTrigger = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:components repeats:YES];
UNNotificationRequest *calendarNotificationRequest = [UNNotificationRequest requestWithIdentifier:@"KFGroupNotification" content:content trigger:cTrigger];
[[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:calendarNotificationRequest withCompletionHandler:^(NSError * _Nullable error) {
if (!error) {
NSLog(@"已成功添加calendar推送%@",calendarNotificationRequest.identifier);
}
}];
}
//UNLocationNotificationTrigger
if (locationTrigger) {
CLCircularRegion *circularRegion = [[CLCircularRegion alloc] initWithCenter:CLLocationCoordinate2DMake(39.9573921487, 116.2690370559) radius:1000.f identifier:@"circularRegionNotification"];
UNLocationNotificationTrigger *localTrigger = [UNLocationNotificationTrigger triggerWithRegion: circularRegion repeats:YES];
UNNotificationRequest *localNotificationRequest = [UNNotificationRequest requestWithIdentifier:@"circularRegionNotification" content:content trigger:localTrigger];
[[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:localNotificationRequest withCompletionHandler:^(NSError * _Nullable error) {
if (!error) {
NSLog(@"已成功添加circular推送%@",localNotificationRequest.identifier);
}
}];
}
// if (UNTimeIntervalNotificationTrigger) {}
}
//Begin ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ iOS10 - lastest 推送回调 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#pragma mark - iOS10 及 10以上 __IOS_AVAILABLE(10.0) 推送代理
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
NSLog(@"应用在前/后台收到通知%@", notification.request.identifier);
//如果需要在应用在前台也展示通知
completionHandler(UNNotificationPresentationOptionBadge|UNNotificationPresentationOptionSound|UNNotificationPresentationOptionAlert);
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)())completionHandler {
NSLog(@"点击通知栏:%@",response.notification.request.identifier);
// 根据类别标识符处理目标反应
if ([response.notification.request.content.categoryIdentifier isEqualToString:@"categoryIndentifier"]) {
[self handleResponse:response];
}
completionHandler();
}
- (void)handleResponse:(UNNotificationResponse *)response {
// response.actionIdentifier;
// The action identifier that the user chose:
// * UNNotificationDismissActionIdentifier if the user dismissed the notification
// * UNNotificationDefaultActionIdentifier if the user opened the application from the notification
// * the identifier for a registered UNNotificationAction for other actions
if ([response.actionIdentifier isEqualToString:UNNotificationDismissActionIdentifier]) {
}else if ([response.actionIdentifier isEqualToString:UNNotificationDefaultActionIdentifier]){
}else{
// what happened ??
}
NSString *actionIndentifier = response.actionIdentifier;
NSLog(@"%@",@"处理通知");
}
//End ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ iOS10 - lastest 推送回调 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//Begin ****************************************** iOS8 - 10 推送回调 ***************************************************
#pragma mark - iOS8 - 10 NS_DEPRECATED_IOS(8_0, 10_0) 推送代理
- (void)GIN_application:(UIApplication *)application handleActionWithIdentifier:(nullable NSString *)identifier forLocalNotification:(UILocalNotification *)notification completionHandler:(void(^)())completionHandler{
[self GIN_application:application handleActionWithIdentifier:identifier forLocalNotification:notification completionHandler:completionHandler];
if ([identifier isEqualToString:@"alert"]) {
}
completionHandler();
}
#pragma mark - NS_DEPRECATED_IOS(9_0, 10_0)
- (void)GIN_application:(UIApplication *)application handleActionWithIdentifier:(nullable NSString *)identifier forLocalNotification:(UILocalNotification *)notification withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void(^)())completionHandler{
[self GIN_application:application handleActionWithIdentifier:identifier forLocalNotification:notification withResponseInfo:responseInfo completionHandler:completionHandler];
NSLog(@"handleActionWithIdentifier");
}
#pragma mark - NS_DEPRECATED_IOS(4_0, 10_0) 收到推送消息
- (void)GIN_application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification{
[self GIN_application:application didReceiveLocalNotification:notification];
NSLog(@"didReceiveLocalNotification notification");
}
//End ****************************************** iOS8 - 10 推送回调 ***************************************************
@end
网友评论