AC — Swift和IOS —用户通知

在iOS 10中新加入UserNotifications框架,称为iOS SDK发展到现在的最大规模的一次重组。新版本里通知的相关功能被提取到了单独的框架,通知也不再区分类型,而有了更统一的行为。

权限申请

通知权限

  • 加入UserNotifications框架
  导入用户通知 
  • 向用户申请通知权限
  func application(_ application:UIApplication,didFinishLaunchingWithOptions launchOptions:[UIApplicationLaunchOptionsKey:Any]?)->布尔{ 
  //应用程序启动后进行自定义的替代点。 
  // 1.我们利用UNUserNotificationCenter.current()获得UNUserNotificationCenter物件,然后再调用它的requestAuthorization(options:completionHandler :),征求使用者同意App发送通知。 
// 2. options:设定我们希望使用者同意的通知样式。
  UNUserNotificationCenter.current()。requestAuthorization(选项:[。alert,.sound,.badge],completionHandler:{(已授予:Bool,错误:Error?)->无效 
如果授予== true {
print(“使用者同意了!”)
}其他{
print(“使用者不同意...”)
}
})
 返回真 
  } 
  • 要注意的是,询问消息只会出现一次,一旦用户拒绝了这个请求,当我们下次启动App时,再也看不到它。想要应用有机会接收到通知的话,用户必须从设定App进入App的通知设定页面,打开Allow Notifications的开关。

远程通知

一旦用户同意后,就可以在应用中发送本地通知了。不过要通过服务器发送远程通知的话,还需要多一个获取用户token的操作。server再使用这个token将用向Apple Push Notification的server提交请求,然后APNs通过令牌识别设备和应用,将通知推给用户。

  • 使用UIApplication的registerForRemoteNotification来注册远程通知; 在application(_:didRegisterForRemoteNotificationsWithDeviceToken)中获取用户令牌。
 // application(_: didFinishLaunchingWithOptions )中,註冊遠程通知 application.registerForRemoteNotifications() 
  func application(_ application:UIApplication,didRegisterForRemoteNotificationsWithDeviceToken deviceToken:Data){ 
// deviceToken是一个Data类型,为了方便使用和传递,一般会选择将其转换为一个字符串。
  print(“ DeviceToken:\(deviceToken)”) 
 让apnsToken = String(格式:“%@”,deviceToken为CVarArg)作为String 
  print(“ ApnsToken:\(apnsToken)”) 
 让tokenString = apnsToken.trimmingCharacters(in:CharacterSet(charactersIn:“ ”))。replacingOccurrences(of:“”,with:“”) 
  print(“ TokenString:\(tokenString)”) 
  } 

发送通知

  @IBAction func createNotification(_ sender:AnyObject){ 

//创建通知内容
让内容= UNMutableNotificationContent()
content.title =“体验过了,才是你的。”
content.subtitle =“米花儿”
“ content.body =”不要追问为什么,就笨拙地走入未知。感受眼前的怦然与颤抖,看见左边的碎裂和跳动。不管好的坏的,只有体验过了,才是你的。
content.badge = 1
content.sound = UNNotificationSound.default()

//创建通知触发
让触发器= UNTimeIntervalNotificationTrigger(timeInterval:10,重复:false)

//创建一个通知请求
让请求= UNNotificationRequest(标识符:“ notification1”,内容:内容,触发器:触发器)

//将请求加入到通知中心
UNUserNotificationCenter.current()。add(request,withCompletionHandler:nil)
}
  • 总共有的总体方法可以触发通知,可进一步研究:
  1. UNTimeIntervalNotificationTrigger:几秒钟后触发。
  2. UNCalendarlNotificationTrigger:指定某个时刻触发。
  3. UNLocationNotificationTrigger:用户位于某个位置时触发。
  4. UNPushNotificationTrigger:从遥远的后台传送到用户手机的通知。

取消通知

取消要求的方法

  • Pending是使用者还没收到的未来通知,已传送则是已经收到,但仍显示在通知页面,尚未点开观看的通知。
 打开函数removePendingNotificationRequests(withIdentifiers标识符:[String]) 
 打开函数removeAllPendingNotificationRequests() 
 打开函数removeDeliveredNotifications(withIdentifiers标识符:[String]) 
 打开函数removeAllDeliveredNotifications() 

在通知加入图片,音乐,影片

开发者现在可以在通知中嵌入图片/视频,大大丰富了通知内容的替代和趣味性。

为本地通知添加多媒体内容十分简单,只需要通过本地磁碟上的档案路径url创建一个UNNotificationAttachment对象,然后将对象赋值给给内容的附件属性就行了。

   imageURL = Bundle.main.url(forResource:“ pic”,withExtension:“ jpg”) 
 让附件=尝试!  UNNotificationAttachment(标识符:“ imageAttachment”,网址:imageURL !,选项:nil) 
  //附件属性:可包含多个UNNotificationAttachment物件的数组 
content.attachments = [附件]
  • UNNotificationAttachment物件的内容可以是图片,音乐或影片,只要传给它档案的路径url。 ,因为无法取得里头图片的url。

在前景显示通知

通知的设计是为了让使用者在操作其他App或是发呆做着白日梦时,贴心提醒使用者。因此当App在前景时,通常是不会显示通知讯息的。不过有些时候就算App在前景,还是有显示通知的需求。如果希望在App应用内也能显示通知的话,需要额外的工作处理。

遵从UNUserNotificationCenterDelegate协议

  1. 利用extension扩展AppDelegate,让它遵从UNUserNotificationCenterDelegate协定。
  2. 定义userNotificationCenter(_:willPresent:withCompletionHandler)。
  func userNotificationCenter(_中心:UNUserNotificationCenter,willPresent通知:UNNotification,withCompletionHandlercompleteHandler:@转义(UNNotificationPresentationOptions)->无效) 
  completeHandler([。alert,.badge,.sound]) 
  //如果不想显示某个通知,可以直接用空options调用completeHandler: 
// completeHandler([])
}

将AppDelegate物件创建UNUserNotificationCenter物件的代理人

在application(_:didFinishLaunchingWithOptions)里:

  UNUserNotificationCenter.current()。delegate = 自我 

在通知里包含客制化资讯

可以通过其中包含定义属性的信息来实现。它的类型别是Dictionary,因此我们可在其中搭配自订的key,包含任何我们想携带的客制化资讯。

  content.userInfo = [“链接”:“ https://www.facebook.com/himinihana/photos/a.104501733005072.5463.100117360110176/981809495274287”] 

判断用户点击通知,解析通知内容

UNUserNotificationCenterDelegate宣告的userNotificationCenter(_:didReceive:withCompletionHndler)会在用户与通知进行交互时被触发,不管App在前景还是背景下,再点击。

因此我们在UNUserNotificationCenter物件的代理人类别AppDelegate里定义此功能,来客制化使用者点击通知后做的事情。

  func userNotificationCenter(_ center:UNUserNotificationCenter,didReceive响应:UNNotificationResponse,withCompletionHandlercompleteHandler:@escaping()-> Void){ 
  // UNNotificationResponse是一个几乎包括了通知的所有信息的物件 
让内容= response.notification.request.content
  print(“标题\(content.title)”) 
  print(“ userInfo \(content.userInfo)”) 
  //警告:UNUserNotificationCenter委托收到了对-userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:的调用,但从未调用完成处理程序。 
//系统要求执行的方法
completeHandler()
}

可行的通知的发送和处理

例如可以在通知里加上按钮,来跟用户互动。方式为将动作放入一个类别中,把此类别进行注册动作,最后在发送通知时,将通知的类别设置为要使用的类别来达到。

  1. 在application(_:didFinishLaunchingWithOptions)里:生成对应到通知按钮的UNNotificationAction对象。
  2. 同时指定一个标识符,我们将在实际发送通知时用此标识符进行设置,如此系统就可知该通知对应类别类别了。
  3. 创建通知时,设置内容的类别标识符等于先前指定的UNNotificationCategory对象的标识符一样,如此一来App收到通知时,才知道要显示哪组按钮。
  4. 和UN的InputNotificationAction触发的响应,直接将与中普通的通知一样,actionable通知也会进到didReceive的委托方法,在这里通过请求它转换为一个UNTextInputNotificationResponse,就可以拿到其中的使用者输入了。
  //加入客制化的按钮,设置自订的通知类别 
let likeAction = UNNotificationAction(标识符:“喜欢”,标题:“好感动”,选项:[。foreground])
  let dislikeAction = UNNotificationAction(标识符:“不喜欢”,标题:“没感觉”,选项:[。destructive]) 
  let inputAction = UNTextInputNotificationAction(标识符:“输入”,标题:“请写下”,选项:[。foreground],textInputButtonTitle:“发送”,textInputPlaceholder:“您想说什么...”) 
 让类别= UNNotificationCategory(标识符:“ luckyMessage”,动作:[likeAction,dislikeAction,inputAction],intentIdentifiers:[],选项:[。customDismissAction]) 
UNUserNotificationCenter.current()。setNotificationCategories([类别])
  @IBAction func createNotification(_ sender:AnyObject){ 
// 先前略...
 content.categoryIdentifier = "saySomethingCategory" 
 func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { 

让categoryIdentifier = response.notification.request.content.categoryIdentifier

如果categoryIdentifier ==“ luckyMessage” {
handleSaySomthing(响应:响应)
}
  completionHandler() 
}
  //仅点击或清除。  (除非您将.customDismissAction设置为category选项,否则当用户清除通知时,您将不会收到此回调。) 
 私有函数handleSaySomthing(响应:UNNotificationResponse){ 
让文字:字符串

让actionType = response.actionIdentifier

切换actionType {
情况“输入”:
text =(响应为!UNTextInputNotificationResponse).userText
情况“喜欢”:
文字=“谢谢”
案例“不喜欢”:
文字=“再见”
默认:
文字=“”
}

print(“ text:\(text)”)
}

参考阅读1:[结合iOS 10的用户通知:传送米花儿的幸福打气通知]

参考阅读2:[活久见的重构— iOS 10 UserNotifications框架解析]

参考阅读3:[iOS 10消息推送(UserNotifications)秘籍总结(一)]