iOS 10前后两种本地通知

通知大家都不陌生,其实通知分两种,远程通知和本地通知。

远程通知是指服务器发出的通知,通过苹果的推送然后到达用户设备。本地通知是指不通过网络,直接安装应用后就可以接到通知了,典型的例子是日历、待办、闹钟等应用。

不过就表现形式来说两者基本一样,都会出现在通知中心,都可以出现在锁屏界面,都可以出现在界面上部,都可以添加应用上的红点。

iOS 10前后两种本地通知_第1张图片
image.png
iOS 10前后两种本地通知_第2张图片
image.png

这里我定时不断发送通知,每次收到通知都添加到列表中,点击列表可以复制通知内容。

对于本地通知,iOS 10以前和以后分两种实现方式,这里都放出来。

需要注意的是,现在在Xcode中使用远程通知功能需要在工程的Targets中的Capabilities标签里打开Push Notification权限,且需要APNS证书,不过本地通知是不需要的,可以直接测试接收通知。

iOS 10以上系统的实现

iOS 10以前使用UILocalNotification,iOS开始支持一个新的类库UNUserNotificationCenter,都给了他特定的前缀UN了,可见重视程度。

如上面第一张图所示,要发通知是需要用户同意的,也就是在第一次打开App的时候必须尝试注册通知,如果不注册,那么即使用户去设置中找也无法再通知里找到你的App然后打开。

所以我们需要在AppDelegate.m的application: didFinishLaunchingWithOptions:方法中注册通知:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    // 注册通知
    UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
    [center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert + UNAuthorizationOptionSound) completionHandler:^(BOOL granted, NSError * _Nullable error) {
            
        }];
    
    
    return YES;
}

这样就会在第一次启动App时向用户索取权限。接下来就可以决定发什么通知以及收到通知后怎么处理了。

我们可以定义一个方法来发通知:

#import 

……

/**
 iOS 10以后的本地通知
 */
- (void)addlocalNotificationForNewVersion {
    UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
    center.delegate = self;
    UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
    content.title = [NSString localizedUserNotificationStringForKey:@"Hello" arguments:nil];
    content.body = [NSString localizedUserNotificationStringForKey:[NSString stringWithFormat:@"Agent-%d",arc4random()%100] arguments:nil];
    content.sound = [UNNotificationSound defaultSound];
    
    //    UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:alertTime repeats:NO];
    UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:@"OXNotification" content:content trigger:nil];
    
    [center addNotificationRequest:request withCompletionHandler:^(NSError *_Nullable error) {
        NSLog(@"成功添加推送");
    }];
}

发通知的所有内容就在这里了,明显可见content是一个通知体,定义通知的一些内容、声音等,然后放到request中,添加到通知中心就可以了。中间注释了一行是用来重复通知的,第一个参数是重复的时间间隔,最小60s,第二个参数是是否重复。因为60s太长了不便于测试,所以不如在外部写一个定时器,重复调用这个方法就可以了。

要接收通知并处理必须要遵循 UNUserNotificationCenterDelegate 这个协议,上面代码中就设置了delegate是self,然后就可以处理接收通知:

#pragma mark - UNUserNotificationCenterDelegate
// iOS 10收到通知
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler {
    
    NSDictionary * userInfo = notification.request.content.userInfo;
    UNNotificationRequest *request = notification.request; // 收到推送的请求
    UNNotificationContent *content = request.content; // 收到推送的消息内容
    NSNumber *badge = content.badge;  // 推送消息的角标
    NSString *body = content.body;    // 推送消息体
    UNNotificationSound *sound = content.sound;  // 推送消息的声音
    NSString *subtitle = content.subtitle;  // 推送消息的副标题
    NSString *title = content.title;  // 推送消息的标题
    
    if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
        NSLog(@"iOS10 前台收到远程通知:%@", body);
        
    } else {
        // 判断为本地通知
        NSLog(@"iOS10 前台收到本地通知:{\\\\nbody:%@,\\\\ntitle:%@,\\\\nsubtitle:%@,\\\\nbadge:%@,\\\\nsound:%@,\\\\nuserInfo:%@\\\\n}",body,title,subtitle,badge,sound,userInfo);
        [self.dataArray addObject:content];
        [self.timeArray addObject:[self convertNSDateToNSString:[NSDate date]]];
        [self.tableView reloadData];
    }
    completionHandler(UNNotificationPresentationOptionBadge|UNNotificationPresentationOptionSound|UNNotificationPresentationOptionAlert); // 需要执行这个方法,选择是否提醒用户,有Badge、Sound、Alert三种类型可以设置
}

我这边的处理是添加到数组中,并且记录通知的时间,好在列表中显示,至于列表怎么显示就不写在这了,需要的同学可以直接看工程代码。

关于iOS 10的通知流程就是这些了。

iOS 10以前系统的实现

老系统的实现其实要素都差不多,只不过提供的类库不一样,一样需要在应用一开始的时候注册通知:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    // 注册通知,如果已经获得发送通知的授权则创建本地通知,否则请求授权(注意:如果不请求授权在设置中是没有对应的通知设置项的,也就是说如果从来没有发送过请求,即使通过设置也打不开消息允许设置)
    if ([[UIApplication sharedApplication] currentUserNotificationSettings].types != UIUserNotificationTypeNone) {
        [self addLocalNotificationForOldVersion];
    } else {
        [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound  categories:nil]];
    }
    
    
    return YES;
}

添加通知我们也放到一个方法中:

/**
 iOS 10以前版本添加本地通知
 */
- (void)addLocalNotificationForOldVersion {
    
    //定义本地通知对象
    UILocalNotification *notification = [[UILocalNotification alloc] init];
    //设置调用时间
    notification.timeZone = [NSTimeZone localTimeZone];
    notification.fireDate = [NSDate dateWithTimeIntervalSinceNow:2.0];//通知触发的时间,10s以后
    notification.repeatInterval = 2;//通知重复次数
    notification.repeatCalendar=[NSCalendar currentCalendar];//当前日历,使用前最好设置时区等信息以便能够自动同步时间
    
    //设置通知属性
    notification.alertBody = [NSString stringWithFormat:@"Agent-%d",arc4random()%100]; //通知主体
    notification.applicationIconBadgeNumber += 1;//应用程序图标右上角显示的消息数
    notification.alertAction = @"打开应用"; //待机界面的滑动动作提示
    notification.alertLaunchImage = @"Default";//通过点击通知打开应用时的启动图片,这里使用程序启动图片
    notification.soundName = UILocalNotificationDefaultSoundName;//收到通知时播放的声音,默认消息声音
//    notification.soundName=@"msg.caf";//通知声音(需要真机才能听到声音)
    
    //设置用户信息
    notification.userInfo = @{@"id": @1, @"user": @"cloudox"};//绑定到通知上的其他附加信息
    
    //调用通知
    [[UIApplication sharedApplication] scheduleLocalNotification:notification];
}

可以看到能够设置的东西还是蛮多的。

此外还有几个可能用得到的代理方法:

/**
 应用注册通知后

 @param application 应用
 @param notificationSettings 通知设置
 */
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
    if (notificationSettings.types != UIUserNotificationTypeNone) {
        [self addLocalNotificationForOldVersion];
    }
}

/**
 应用进入前台时调用

 @param application 应用
 */
- (void)applicationWillEnterForeground:(UIApplication *)application {
    [[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];//进入前台取消应用消息图标
}

/**
 收到通知后回调

 @param application 应用
 @param notification 通知
 */
- (void)application:(UIApplication *)application didReceiveLocalNotification:(nonnull UILocalNotification *)notification {
    NSLog(@"%@", notification.alertBody);
}

不过我用这个老方法在iOS 10的手机上测试收不到通知,不知道是不是在新系统必须要用新的库。

没什么好结的,以上。


示例工程:https://github.com/Cloudox/OXNotificationTest
查看作者首页

你可能感兴趣的:(iOS 10前后两种本地通知)