做远程推送,首先在苹果的开发者中心配置两个证书,下载到本地,在钥匙串中点击对应证书,选择导出证书即可得到激光所需要的p12文件,这个过程中会用密码填写,需要记住。
这里主要介绍本地推送,本地进行推送重点在于构建出firedate和间timerinter,来达到某个时间点的推送。iOS系统的升级系统的推送系统也进行了比较大的更新,尤其在iOS10以及以后推出了一套新的API来管理推送。还有就是对于iOS8的系统,必须注册并用户点击了同意才能进行推送,当然都需要在info里面添加需要进行推送的字段。
iOS8:注册推送通过UIUserNotificationSettings这个对象来设置推送类型,通过UIApplication 注册通知。
UIUserNotificationSettings *localNot = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeSound | UIUserNotificationTypeBadge | UIUserNotificationTypeAlert categories:nil];
[application registerUserNotificationSettings:localNot];
iOS10:通过UNUserNotificationCenter这个对象来获取授权,并且也把查询用户授权的接口也以及给出
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
[center requestAuthorizationWithOptions:UNAuthorizationOptionAlert|UNAuthorizationOptionSound|UNAuthorizationOptionBadge completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (!error&& granted) {
NSLog(@"用户点击允许");
} else {
NSLog(@"注册失败");
}
}];
[center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
if (settings.authorizationStatus == UNAuthorizationStatusDenied) {
//
NSLog(@"未作出选择");
} else if (settings.authorizationStatus == UNAuthorizationStatusNotDetermined) {
//
NSLog(@"未授权");
} else {
NSLog(@"已经授权");
}
}];
远程推送
ios_8_to_ios 10
[[UIApplication sharedApplication] registerForRemoteNotifications];
iOS_10_later
[[UIApplication sharedApplication] registerForRemoteNotifications];
iOS_8_ before
[application registerForRemoteNotificationTypes: UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound];
发送通知:为了兼容iOS10以及大于:发送本地通知也有两套不同的API。
iOS10er:发送本地通知主要依赖于application这个对象,首先构造出UILocalNotification这个发送本地通知的对象,再通过application这个对象发送UILocalNotification,UILocalNotification的firedate和@property(nonatomic) NSCalendarUnit repeatInterval; 决定了在那个时间发送通知和重复规律,不过需要注意的是,repeaterval是一个枚举类型:
NSCalendarUnitEra = kCFCalendarUnitEra,
NSCalendarUnitYear = kCFCalendarUnitYear,
NSCalendarUnitMonth = kCFCalendarUnitMonth,
NSCalendarUnitDay = kCFCalendarUnitDay,
NSCalendarUnitHour = kCFCalendarUnitHour,
NSCalendarUnitMinute = kCFCalendarUnitMinute,
NSCalendarUnitSecond = kCFCalendarUnitSecond,
NSCalendarUnitWeekday = kCFCalendarUnitWeekday,
NSCalendarUnitWeekdayOrdinal = kCFCalendarUnitWeekdayOrdinal,
我在开发中需要在某一天按照周重复来提醒用户,选择的是NSCalendarUnitWeekdayOrdinal(不知道为什么不是选择NSCalendarUnitWeekday这个枚举值)。userinfo这个字典属性:可以用来放这个通知的id(自己生成),在取消通知的时候根据该id值判断是否为需求取消的。
iOS10later:iOS发送通知则简单很多,通过UNNotificationTrigger的子类UNTimeIntervalNotificationTrigger;UNCalendarNotificationTrigger;UNLocationNotificationTrigger三个类,根据需求来构造出本地通知。
UNTimeIntervalNotificationTrigger:+ (instancetype)triggerWithTimeInterval:(NSTimeInterval)timeInterval repeats:(BOOL)repeats;
这个方法构造,不过只有timeintercal,而没有firedate,猜想应该是当前时间(还没有验证);我在开发中用到的是UNCalendarNotificationTrigger:它需要一个NSDateComponents对象,来指定起飞时间,这个可以借助NSCalendar,这个对象根据发送通知的时间来构造出NSDateComponents:
static dispatch_once_t onceToken;
static NSCalendar *calender;
dispatch_once(&onceToken, ^{
calender = [NSCalendar currentCalendar];
});
NSDateComponents *compen = [calender components:NSCalendarUnitWeekday|NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitMonth fromDate:alertDate];
UNCalendarNotificationTrigger *trigger = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:compen repeats:YES];//repeats决定是否重复
到这里是否有疑问间隔如何设置,其实也是借助datecompent这个对象,比如你想要设置每天八点,只需要trigger.dateComponents.houre = 8;就可以达到天重复,对于周重复,设置weekday这个属性即可(这也是对于iOS10以后通知间隔不是选择NSCalendarUnitWeekday疑惑所在,注意NSDateComponents是一个深拷贝对象,需要trigger.dateComponents.weekday = x;)。很重要一点对于iOS10可以查看nextfiredate来检查是否正确,对iOS10er可以输出locationnotifation这个对象,也可以查看下个触发点。
UNMutableNotificationContent:决定了通知如何显示:到这里我们就可以构造出一个请求对象了:
UNNotificationRequest [UNNotificationRequest requestWithIdentifier:remindArray[i] content:content trigger:trigger];//得到request就可以拿UNUserNotificationCenter这个对象来发送了
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
if (!error) {
NSLog(@"week:%ld hour:%ld minute:%ld remindid:%@",(long)trigger.dateComponents.weekday, (long)trigger.dateComponents.hour,(long)trigger.dateComponents.minute,remindArray[i]);
NSLog(@"通知已经成功添加");
}
}];
取消通知:iOS10later:
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center removePendingNotificationRequestsWithIdentifiers:identArray];
iOS10er:
NSArray *array = [[UIApplication sharedApplication] scheduledLocalNotifications];
for (UILocalNotification *local in array) {
NSString *notiString = local.userInfo[kidentifier];
BOOL find = NO;
for (NSString *identfil in identArray) {
if ([identfil isEqualToString:notiString]) {
find = YES;
break;
} else
continue;
}
if (find) {
[findArray addObject:local];
}
}
for (UILocalNotification *local in findArray) {
[[UIApplication sharedApplication] cancelLocalNotification:local];
NSLog(@"取消本地通知...%@",local.userInfo[kidentifier]);
}
在收到通知不同系统版本处理
<iOS10:
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
NSLog(@"接收到本地通知");
// 通过UI控件来测试.当App彻底退出时, 用户点击通知, 打开APP , 会不会调用这个方法
// UISwitch *sw = [[UISwitch alloc] init];
// [self.window.rootViewController.view addSubview:sw];
// 查看当前的状态出于(前台: 0)/(后台: 2)/(从后台进入前台: 1)
NSLog(@"applicationState.rawValue: %zd", application.applicationState);
// 执行响应操作
// 如果当前App在前台,执行操作
if (application.applicationState == UIApplicationStateActive) {
UIAlertView *alerview = [[UIAlertView alloc] initWithTitle:notification.alertTitle message:notification.alertBody delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
[alerview show];
// [MBProgressHUD showSuccess:notification.alertBody];
NSLog(@"执行前台对应的操作");
} else if (application.applicationState == UIApplicationStateInactive) {
// 后台进入前台
NSLog(@"执行后台进入前台对应的操作");
//NSLog(@"%@", notification.userInfo);
} else {
// 当前App在后台
NSLog(@"执行后台对应的操作");
}
}
>=iOS10:iOS10以后通知管理更加方便,不管远程还是本地都通过走两个方法,一个是在前台收到通知,以及在后台收到通知,方法如下
//前台接收通知时
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
UNNotificationRequest *requst = notification.request;
UNNotificationContent *content = requst.content;
NSDictionary *userInfo = content.userInfo;
if ([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
NSLog(@"iOS 10 收到远端通知");
} else {
NSLog(@"iOS 收到本地通知");
}
//执行这个方法,处于前台的app才可以显示通知,类型可以选择
completionHandler(UIUserNotificationTypeSound | UIUserNotificationTypeBadge | UIUserNotificationTypeAlert);
}
-(void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler {
completionHandler();
}