iOS10之前本地推送

  • 本地推送不需要借助服务器,即可实现推送功能。
  • 这个时候需要借助UILocalNotification类进行功能实现
  • 创建本地推送代码实现
// 创建本地推送
- (void)creatLocalPush{
    UILocalNotification *localNotifi = [[UILocalNotification alloc]init];
    // 设置触发时间
    localNotifi.fireDate = [NSDate dateWithTimeIntervalSinceNow:3];
    // 设置时区  以当前手机运行的时区为准
    localNotifi.timeZone = [NSTimeZone defaultTimeZone];
    // 设置推送 显示的内容
    localNotifi.alertTitle = @"推送标题";
    localNotifi.alertBody = @"本地推送内容";
    localNotifi.alertAction = @"alert提示框按钮文本";
    //是否显示额外的按钮,为no时alertAction消失
    localNotifi.hasAction = YES;
    // 设置 icon小红点个数
    localNotifi.applicationIconBadgeNumber = 1;
    // 设置是否重复  重复最小时间间隔为秒,但最好是分钟
    // 不设置此属性,则默认不重复
    localNotifi.repeatInterval =  NSCalendarUnitMinute;
    // 设置推送的声音
    // 通知的声音默认是iOS系统自带的声音,当然也支持自定义,但是自定义必须是固定格式的音频文件,不支持mp3,最常用的是cef/pcm/ma4/alaw格式的音频文件,并且播放时间不能长于30秒,如果长于30秒,将会被系统时间所代替,音频文件必须放在工程文件当中([NSBundle mainBundle])
    localNotifi.soundName = UILocalNotificationDefaultSoundName;

    // 设置推送的区别符
    localNotifi.userInfo = @{@"name":@"loaclPushOne"};
    // 按照前面设置的计划 执行此通知
    [[UIApplication sharedApplication] scheduleLocalNotification:localNotifi];
}
  • 取消指定本地推送代码实现
// 关闭本地推送
- (void)deleteLocalPush{
    // 获取该app上所有的本地推送
    NSArray *allLocalNotifi = [[UIApplication sharedApplication] scheduledLocalNotifications];

    // 取消特定的本地推送
    UILocalNotification *localNotifi  = nil;
    for (UILocalNotification *item in allLocalNotifi) {
        NSDictionary *userInfo = item.userInfo;
        if ([[userInfo objectForKey:@"name"] isEqualToString:@"loaclPushOne"]) {
            localNotifi = item;
            break;
        }
    }
    [[UIApplication sharedApplication] cancelLocalNotification:localNotifi];
}
  • 取消所有的本地推送
[[UIApplication sharedApplication]  cancelAllLocalNotifications];
  • 点击本地推送通知 进入APP后的回调
#pragma mark - LocalPush
// 点击本地推送通知 进入APP后的回调 在iOS10之后将会 分成两个方法回调
 - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification{
    [application cancelLocalNotification:notification];
}

iOS10之后本地推送

  • 本地通知也需要在appdelegate 中注册。

通知内容

  • 通知内容有可变和不可变之分UNNotificationContent(不可变)、UNMutableNotificationContent(可变),后续我们通过某一特定标识符更新通知,便是用可变通知了。
  • 不管是可变通知还是不可变通知,都有以下的几个属性:
// 1.附件数组,存放UNNotificationAttachment类
@property (NS_NONATOMIC_IOSONLY, copy) NSArray <UNNotificationAttachment *> *attachments ;

// 2.应用程序角标,0或者不传,意味着角标消失
@property (NS_NONATOMIC_IOSONLY, copy, nullable) NSNumber *badge;

// 3.主体内容
@property (NS_NONATOMIC_IOSONLY, copy) NSString *body ;

// 4.app通知下拉预览时候展示的图
@property (NS_NONATOMIC_IOSONLY, copy) NSString *launchImageName;

// 5.UNNotificationSound类,可以设置默认声音,或者指定名称的声音
@property (NS_NONATOMIC_IOSONLY, copy, nullable) UNNotificationSound *sound ;

// 6.推送内容的子标题
@property (NS_NONATOMIC_IOSONLY, copy) NSString *subtitle ;

// 7.通知线程的标识
@property (NS_NONATOMIC_IOSONLY, copy) NSString *threadIdentifier;

// 8.推送内容的标题
@property (NS_NONATOMIC_IOSONLY, copy) NSString *title ;

// 9.远程通知推送内容
@property (NS_NONATOMIC_IOSONLY, copy) NSDictionary *userInfo;

// 10.category标识
@property (NS_NONATOMIC_IOSONLY, copy) NSString *categoryIdentifier;

附件内容(UNNotificationAttachment)

  • 在UNNotificationContent类中,有个附件数组的属性,这就是包含UNNotificationAttachment类的数组了。
@property (NS_NONATOMIC_IOSONLY, copy) NSArray <UNNotificationAttachment *> *attachments ;

苹果的解释说,UNNotificationAttachment(附件通知)是指可以包含音频,图像或视频内容,并且可以将其内容显示出来的通知。使用本地通知时,可以在通知创建时,将附件加入即可。对于远程通知,则必须实现使用UNNotificationServiceExtension类通知服务扩展。

创建附件的方法:

+ (nullable instancetype)attachmentWithIdentifier:(NSString *)identifier URL:(NSURL *)URL options:(nullable NSDictionary *)options error:(NSError *__nullable *__nullable)error;
// URL必须是一个有效的文件路径,不然会报错
  • 在使用时,必须指定使用文件附件的内容,并且文件格式必须是支持的类型之一。

创建附件中options的属性,一共有4种选项。

  • options属性为一个类型为字典的数值。
UNNotificationAttachmentOptionsTypeHintKey
  • 一个包含描述文件的类型统一类型标识符(UTI)一个NSString。如果不提供该键,附件的文件扩展名来确定其类型,常用的类型标识符有
    kUTTypeImage、kUTTypeJPEG2000、kUTTypeTIFF、kUTTypePICT、kUTTypeGIF、kUTTypePNG、kUTTypeQuickTimeImage等。
  • 这些标识符,在UIImagePickerController对象属性中也会遇到。
  • 使用这些标识符需要导如对应的框架<MobileCoreServices/MobileCoreServices.h>
  • 使用方法示例:
NSMutableDictionary *optionsDict = [NSMutableDictionary dictionary];
    // 需要导入框架 #import<MobileCoreServices/MobileCoreServices.h>
    optionsDict[UNNotificationAttachmentOptionsTypeHintKey] = (__bridge id _Nullable)(kUTTypeImage);
UNNotificationAttachmentOptionsThumbnailHiddenKey
  • 此值为布尔值,代表是否隐藏推送消息右侧缩略图,YES代表隐藏
  • 使用方法示例:
optionsDict[UNNotificationAttachmentOptionsThumbnailHiddenKey] = @YES;
// 隐藏缩略图
UNNotificationAttachmentOptionsThumbnailClippingRectKey
  • 剪贴矩形的缩略图,将缩略图整体作为1:1,然后按照比例进行缩减,以图片左上角为原点。
  • 示例,剪切图片(中心的正方形)
optionsDict[UNNotificationAttachmentOptionsThumbnailClippingRectKey] = (__bridge id _Nullable)((CGRectCreateDictionaryRepresentation(CGRectMake(0.25, 0.25, 0.5 ,0.5))));
UNNotificationAttachmentOptionsThumbnailTimeKey
  • 主要用于附件是影片的,选择影片中的某一秒来做这个缩略图。
  • 示例,以影片第一秒来作为缩略图
optionsDict[UNNotificationAttachmentOptionsThumbnailTimeKey] = @1;

通知触发模式(UNNotificationTrigger)

  • 通知触发模式供有四种情况,四种情况均是UNNotificationTrigger 子类。

远程推送触发模式

  • @interface UNPushNotificationTrigger : UNNotificationTrigger

本地推送触发模式(按秒间隔)

  • @interface UNTimeIntervalNotificationTrigger : UNNotificationTrigger
  • 使用方法示例:
// timeInterval(时间间隔)和repeats(是否重复)
// 5秒后执行,NO:不重复
// 如果需要重复执行,则重复时间间隔需要大于60秒
UNTimeIntervalNotificationTrigger *triggerOne = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:5 repeats:NO];

本地推送触发模式(按日期进行间隔)

  • UNCalendarNotificationTrigger
  • 使用方法示例:
// 例如:周二早上 9:00 上班
NSDateComponents *components = [[NSDateComponents alloc] init];
// 注意,weekday是从周日开始从1计数,如果想设置为从周一开始则需要设置为2
components.weekday = 3;
components.hour = 9;
UNCalendarNotificationTrigger *trigger = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:components repeats:YES];

本地推送触发模式(按地理位置)

  • @interface UNLocationNotificationTrigger : UNNotificationTrigger
使用方式
  1. 导入框架#import<CoreLocation/CoreLocation.h>
  2. 初始化对象
// 不建议使用!!!!!!CLRegion *region = [[CLRegion alloc] init];
CLCircularRegion *circlarRegin = [[CLCircularRegion alloc] init];
    // 经纬度
    CLLocationDegrees latitudeDegrees = 123.00; // 维度
    CLLocationDegrees longitudeDegrees = 123.00; // 经度

    [circlarRegin containsCoordinate:CLLocationCoordinate2DMake(latitudeDegrees, longitudeDegrees)];
    UNLocationNotificationTrigger *trigger = [UNLocationNotificationTrigger triggerWithRegion:circlarRegin repeats:NO];

这里建议使用CLCircularRegion这个继承自CLRegion的类,因为我看到苹果已经飞起了CLRegion里面是否包含这一点的方法,并且推荐我们使用CLCircularRegion这个类型

创建本地通知示例

#pragma mark - 创建本地推送 ios10之后
- (void)creatLocalPushIOS10{
    // 注意:创建本地通知也需要在appdelegate中心进行注册
    // 1.创建通知内容
    UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
    content.title = @"本地通知标题";
    content.subtitle = @"本地通知副标题";
    content.body = @"本地通知内容";
    content.badge = @1;
    NSError *error = nil;
    NSString *path = [[NSBundle mainBundle] pathForResource:@"imageName" ofType:@"png"];
    // 2.设置通知附件内容
    NSMutableDictionary *optionsDict = [NSMutableDictionary dictionary];
    // 一个包含描述文件的类型统一类型标识符(UTI)一个NSString。如果不提供该键,附件的文件扩展名来确定其类型,常用的类型标识符有 kUTTypeImage,kUTTypeJPEG2000,kUTTypeTIFF,kUTTypePICT,kUTTypeGIF ,kUTTypePNG,kUTTypeQuickTimeImage等。

    // 需要导入框架 #import<MobileCoreServices/MobileCoreServices.h>
              optionsDict[UNNotificationAttachmentOptionsTypeHintKey] = (__bridge id _Nullable)(kUTTypeImage);
    // 是否隐藏缩略图
    optionsDict[UNNotificationAttachmentOptionsThumbnailHiddenKey] = @YES;
    // 剪切缩略图
    optionsDict[UNNotificationAttachmentOptionsThumbnailClippingRectKey] = (__bridge id _Nullable)((CGRectCreateDictionaryRepresentation(CGRectMake(0.25, 0.25, 0.5 ,0.5))));
    // 如果附件是影片,则以第几秒作为缩略图
optionsDict[UNNotificationAttachmentOptionsThumbnailTimeKey] = @1;
    // optionsDict如果不需要,可以不设置,直接传nil即可
    UNNotificationAttachment *att = [UNNotificationAttachment attachmentWithIdentifier:@"identifier" URL:[NSURL fileURLWithPath:path] options:optionsDict error:&error];
    if (error) {
        NSLog(@"attachment error %@", error);
    }
    content.attachments = @[att];
    content.launchImageName = @"imageName@2x";
    // 2.设置声音
    UNNotificationSound *sound = [UNNotificationSound defaultSound];
    content.sound = sound;
    // 3.触发模式 多久触发,是否重复
     // 3.1 按秒
    UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:5 repeats:NO];
     // 3.2 按日期
//    // 周二早上 9:00 上班
//    NSDateComponents *components = [[NSDateComponents alloc] init];
//    // 注意,weekday是从周日开始的计数的
//    components.weekday = 3;
//    components.hour = 9;
//    UNCalendarNotificationTrigger *trigger = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:components repeats:YES];
    // 3.3 按地理位置
    // 一到某个经纬度就通知,判断包含某一点么
    // 不建议使用!!!!!!CLRegion *region = [[CLRegion alloc] init];

//   CLCircularRegion *circlarRegin = [[CLCircularRegion alloc] init];
    // 经纬度
//    CLLocationDegrees latitudeDegrees = 123.00; // 维度
//    CLLocationDegrees longitudeDegrees = 123.00; // 经度

//    [circlarRegin containsCoordinate:CLLocationCoordinate2DMake(latitudeDegrees, longitudeDegrees)];
//    UNLocationNotificationTrigger *trigger = [UNLocationNotificationTrigger triggerWithRegion:circlarRegin repeats:NO];

    // 4.设置UNNotificationRequest
    NSString *requestIdentifer = @"TestRequest";
    UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:requestIdentifer content:content trigger:trigger];

    //5.把通知加到UNUserNotificationCenter, 到指定触发点会被触发
    [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
    }];

}

推送效果图示:

iOS本地通知 oc_iOS本地通知 oc

推送回调

  • 远程推送与本地推送均是这两个回调
#pragma mark - UNUserNotificationCenterDelegate 
// iOS10 推送回调
- (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 收到远程通知");
    }else{
        NSLog(@"ios10 收到本地通知%@%@%@%@%@",title,subTitle,body,badge,userInfo);
    }
    completionHandler(UNNotificationPresentationOptionBadge |
                      UNNotificationPresentationOptionSound |
                      UNNotificationPresentationOptionAlert );
    // 需要执行此方法,选择是否提醒用户,有以上三种那个类型可选

}
// 通知的点击事件
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)())completionHandler{
    NSDictionary *userInfo = response.notification.request.content.userInfo;
    UNNotificationRequest *request = response.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; // 推送收到的标题
    NSLog(@">>>通知的点击事件");
    if ([request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
        NSLog(@"iOS10 收到远程通知");
    }else{
        NSLog(@"ios10 收到本地通知%@%@%@%@%@",title,subTitle,body,badge,userInfo);
    }
    completionHandler(); //系统要求执行此方法

}

代码地址:https://github.com/FlyingKuiKui/PushTestApp.git