iOS 本地推送开发记录一

2018-05-15  本文已影响176人  Vson2016

前段时间接手到一个关于本地推送的活,还可以设置重复本地推送,把此次记录拆分成两篇,第一篇主要是记录推送的设置,第二篇主要来讲一下如何实现重复推送。

iOS 本地推送开发记录二

初始化推送设置(项目支持最低iOS8.0)

头文件导入,需要增加版本的判断

#ifdef NSFoundationVersionNumber_iOS_9_x_Max
#import <UserNotifications/UserNotifications.h>
#endif

由于涉及到iOS版本的兼容,需要考虑iOS10以下及iOS8以上的设置

if (@available(iOS 10.0, *)) {
        //iOS10特有
        UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
       
        // 必须写代理,不然无法监听通知的接收与点击
        center.delegate = self;
        [center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionBadge | UNAuthorizationOptionSound) completionHandler:^(BOOL granted, NSError * _Nullable error) {
            if (granted) {
                // 点击允许
                NSLog(@"注册成功");
                [center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
                    NSLog(@"%@", settings);
                }];
            } else {
                // 点击不允许
                NSLog(@"注册失败");
            }
        }];
    } else {
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes: (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound) categories:nil];
        [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
    }

推送的设置

if (@available(iOS 10.0, *)) {
        // 使用 UNUserNotificationCenter 来管理通知
        UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
        
        //需创建一个包含待通知内容的 UNMutableNotificationContent 对象,注意不是 UNNotificationContent ,此对象为不可变对象。
        UNMutableNotificationContent* content = [[UNMutableNotificationContent alloc] init];
        content.title = title;       
        content.body  = body;
        UNNotificationSound *sound = [UNNotificationSound soundNamed:soundName];
        content.sound = sound;
        content.userInfo = param;
      
        // 在 alertTime 后推送本地推送
        UNTimeIntervalNotificationTrigger* trigger = [UNTimeIntervalNotificationTrigger
                                                      triggerWithTimeInterval:timeInterval repeats:NO];
        
        UNNotificationRequest* request = [UNNotificationRequest requestWithIdentifier:notificationId
                                                                              content:content trigger:trigger];
        
        //添加推送成功后的处理!
        [center addNotificationRequest:request withCompletionHandler:nil];
    } else {
        NSDate *fireDate = nil;
        if (time > 0) {
            // 定时时间存在,以定时时间为准
            fireDate = [NSDate dateWithTimeIntervalSinceNow:time];
        } else {
            fireDate = [NSDate dateWithTimeIntervalSince1970:dateTime];
        }
        
        // 1.创建通知
        UILocalNotification *localNotification = [[UILocalNotification alloc] init];

        // 2.设置通知
        // 设置通知标题
        if (@available(iOS 8.2, *)) {
            localNotification.alertTitle = title ? title : @"";
        }
        // 设置通知显示的内容
        localNotification.alertBody = body ? body : @"";
        // 设置通知的发送时间,单位秒
        localNotification.fireDate = fireDate;
        //收到通知时App icon的角标
        localNotification.applicationIconBadgeNumber = 1;
        //推送是带的声音提醒,设置默认的字段为UILocalNotificationDefaultSoundName
        localNotification.soundName = soundName;

        // 3.发送通知
        // 方式一: 根据通知的发送时间(fireDate)发送通知
        NSMutableDictionary *newParam = [NSMutableDictionary dictionaryWithDictionary:param];
        newParam[@"identifier"] = notificationId;
        localNotification.userInfo = newParam;
        [[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
    }

推送的处理

在接收到推送的处理方式上,iOS8和iOS10上有所不同
iOS8上需要通过UIApplicationDelegate的代理方法如下:

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
    NSLog(@"notification:%@", notification);
}

iOS10上需要通过UNUserNotificationCenterDelegate相关代理方法,iOS10上在应用内收到推送时,可以通过willPresentNotification这个代理方法里面通过completionHandler(0)关闭推送的展示

//在展示通知前进行处理,即有机会在展示通知前再修改通知内容。
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler  API_AVAILABLE(ios(10.0)){
    if (@available(iOS 10.0, *)) {
        if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
            NSLog(@"iOS10 收到远程通知:%@", notification);
        }
        else {
            NSLog(@"iOS10 收到本地通知:%@", notification);
        }
    }
    
    // 避免APP打开的状态下在iOS10+下出现本地推送
    completionHandler(0);
}

- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler  API_AVAILABLE(ios(10.0)){
    if (@available(iOS 10.0, *)) {
        if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
            NSLog(@"iOS10 收到远程通知:%@", response);
        }
        else {
            NSLog(@"iOS10 收到本地通知:%@", response);
        }
    }
}

推送的更新

iOS8上通过注册时添加一个identifier,在更新时找到这个identifier的推送,并取消,然后重新注册推送即可实现更新。
iOS10上因为有identifier的存在,所以可以直接复用之前的identifier可以更新成最新的推送

if (@available(iOS 10.0, *)) {
        // iOS10+  只要重新设置一次 就能完成更新
    } else {
        // 获取所有本地通知数组
        NSArray *localNotifications = [UIApplication sharedApplication].scheduledLocalNotifications;
        for (UILocalNotification *notification in localNotifications)
        {
            NSDictionary *userInfo = notification.userInfo;
            if (userInfo)
            {
                NSString *identifier = [self getNoticeIdentifierWithId:param[@"id"]];
                // 如果找到需要取消的通知,则取消
                if ([identifier isEqualToString:userInfo[@"identifier"]]) {
                    [[UIApplication sharedApplication] cancelLocalNotification:notification];
                    break;
                }
            }
        }
    }

推送的删除

iOS8和iOS10上思路都是通过一个identifier来找到之前的推送分别调用自己的取消方法即可,所以如果涉及到修改、删除推送的操作,identifier的设置很重要。

if (@available(iOS 10.0, *)) {
        [[UNUserNotificationCenter currentNotificationCenter] removePendingNotificationRequestsWithIdentifiers:@[identifier]];
    } else {
        // 获取所有本地通知数组
        NSArray *localNotifications = [UIApplication sharedApplication].scheduledLocalNotifications;
        for (UILocalNotification *notification in localNotifications)
        {
            NSDictionary *userInfo = notification.userInfo;
            if (userInfo)
            {
                // 如果找到需要取消的通知,则取消
                if ([identifier isEqualToString:userInfo[@"identifier"]]) {
                    [[UIApplication sharedApplication] cancelLocalNotification:notification];
                    break;
                }
            }
        }
    }
上一篇下一篇

猜你喜欢

热点阅读