在上集中,我们已经构建了一个简单的待办列表应用(to-do list app),这个应用可以在待办项过期时通过本地通知提醒用户。现在,我们要在之前的基础上添加以下功能:应用图标角标上显示过期待办项的数量、通知动作的支持和在不开启应用的情况下编辑和完成待办项。

你可以在这里下载上一集的源代码。

为应用图标添加角标(Badge)

值得注意的是,我们不通过本地通知也可以为应用图标添加角标。AppDelegate 中的 applicationWillResignActive: 方法是可以实现这个功能的。在用户返回主屏幕的时候,看到应用图标时候,会触发这个方法。

func applicationWillResignActive(application: UIApplication) {
var todoItems: [TodoItem] = TodoList.sharedInstance.allItems()
var overdueItems = todoItems.filter({ (todoItem) -> Bool in
return todoItem.deadline.compare(NSDate()) != .OrderedDescending
})
UIApplication.sharedApplication().applicationIconBadgeNumber = overdueItems.count
}

虽然可行,但是并不能在待办项过期时自动更新角标的值。因为我们不能简单的在通知触发的时候增加角标的值,因此,我们可以为本地通知预设一个“applicationIconBadgeNumber”的属性值。接下来,我们在 TodoList 中写一个为每个通知设置相关角标值的方法。

func setBadgeNumbers() {
var notifications = UIApplication.sharedApplication().scheduledLocalNotifications as! [UILocalNotification]
var todoItems: [TodoItem] = self.allItems()
for notification in notifications {
var overdueItems = todoItems.filter({ (todoItem) -> Bool in
return (todoItem.deadline.compare(notification.fireDate!) != .OrderedDescending)
})
UIApplication.sharedApplication().cancelLocalNotification(notification)
notification.applicationIconBadgeNumber = overdueItems.count
UIApplication.sharedApplication().scheduleLocalNotification(notification)
}
}

虽然没有办法去更新已经计划好时间的通知,但是可以通过删除当前通知然后重新设置的方式来达到同样的效果。

applicationIconBadgeNumber这个属性可以接受的最大值是 2,147,483,647(NSIntegerMax),超过 5 位数的数字就会在图标上被截断,如图所示。而且,设置为零或负数是不会产生效果的。

我们只是需要在待办列表发生变化的时候调用这个方法。将下面这段代码添加到 TodoList 中的addItem:removeItem:两个方法之后。

self.setBadgeNumbers()

这样,当一个通知被触发的时候,角标的值会被自动更新。

如何让通知反复触发

UILocalNotificaiton实例有个属性,叫repeatInterval,可以让通知以一个固定的时长反复触发。这种方法可以很好的避免通知数量 64 的这个上限,而且一个重复的通知只会被计算一次。

不幸的是,在我们的应用中,只能在repeatIntervalapplicationIconBadgeNumber中选择一个。角标值会在每次通知被触发的时候更新。较旧的通知可能会被新的通知终结,而且恰好新的通知是重复的通知(一个重复的通知只会被计算一次),即导致角标的值会比预计的小。我们可以设置两个通知,一个是重复的通知会显示提醒和播放提示音,另一个是非重复的通知会更新角标值,会发现测试的结果角标值只有预想的一半。

重复通知的最大局限是重复的间隔(repeatInterval)不接受自定义值。你必须提供一个NSCalendarUnit值,例如HourCalendarUnitDayCalendarUnit。假如,如果你希望设置的通知每 30 分钟触发一次,那么可以通过设置两个通知(两者之间间隔 30 分钟,并都以一小时重复触发)来解决。当然了,如果你希望是每 31 分钟触发一次,那就没办法了。

后台执行通知动作

iOS 8 引进了一个很有用的新特性:通知动作(notification actions),它可以让通知由用户来触发,甚至用户没有打开应用都可以触发。让我们来实现这个功能吧:从通知横幅上直接完成或等会提醒待办项。

AppDelegate文件里可以这样写:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let completeAction = UIMutableUserNotificationAction()
completeAction.identifier = "COMPLETE_TODO"
completeAction.title = "Complete"
completeAction.activationMode = .Background
completeAction.authenticationRequired = false
completeAction.destructive = true
let remindAction = UIMutableUserNotificationAction()
remindAction.identifier = "REMIND"
remindAction.title = "Remind in 30 minutes"
remindAction.activationMode = .Background
remindAction.destructive = fal
let todoCategory = UIMutableUserNotificationCategory()
todoCategory.identifier = "TODO_CATEGORY"
todoCategory.setActions([remindAction, completeAction], forContext: .Default)
todoCategory.setActions([completeAction, remindAction], forContext: .Minimal)
application.registerUserNotificationSettings(UIUserNotificationSettings(forTypes: .Alert | .Badge | .Sou categories: NSSet(array: [todoCategory])))
return true
}

值得注意的是,上面的代码中我们调用了todoCategory.setActions()两次,分别设置了动作上下文(action contexts)。如果通知是以横幅(banner)的形式显示,那么通知动作会以迷你形式(minimal context)显示出来。如果通知是以(默认的)提示(alert) 形式显示,通知动作会显示至少 4 个操作。如下图。

我们传递到setActions:方法里的通知动作的顺序会一一对应的呈现在 UI 里,但是很奇怪的是,迷你形式里通知动作的顺序是以从右向左排列的方式显示的。

下面的代码是为了确保通知的category是为 TodoList 的addItem:方法设置的。

notification.category = "TODO_CATEGORY"

到此,我们已经可以用removeItem:方法来实现完成待办项,现在我们需要在 TodoList 里实现过会提醒的功能。

func scheduleReminderforItem(item: TodoItem) {
var notification = UILocalNotification()
notification.alertBody = "Reminder: Todo Item \"\(item.title)\" Is Overdue"
notification.alertAction = "open"
notification.fireDate = NSDate().dateByAddingTimeInterval(30 * 60)
notification.soundName = UILocalNotificationDefaultSoundName
notification.userInfo = ["title": item.title, "UUID": item.UUID]
notification.category = "TODO_CATEGOR
UIApplication.sharedApplication().scheduleLocalNotification(notification)
}

值得注意的是,我们并没有修改待办项的到期日期(或者试着取消原来的通知,虽然已经被自动删除)。现在,回到AppDelegate里,实现actions:里的处理。

func application(application: UIApplication, handleActionWithIdentifier identifier: String?, forLocalNotification notification: UILocalNotification, completionHandler: () -> Void) {
var item = TodoItem(deadline: notification.fireDate!, title: notification.userInfo!["title"] as String, UU notification.userInfo!["UUID"] as String!)
switch (identifier!) {
case "COMPLETE_TODO":
TodoList.sharedInstance.removeItem(item)
case "REMIND":
TodoList.sharedInstance.scheduleReminderforItem(item)
default:
println("Error: unexpected notification action identifier!")
}
completionHandler()
}

终于可以试着运行这个应用了(为了测试方便,建议将dateByAddingTimeInterval:设置一个较小的值)。

我们讨论了所有的非地理上(注:上一集讲到的用户进入和离开某个地理区域时,可以触发本地通知的功能)的 UILocalNotification 功能,现在已经有一个功能较全的待办项应用了,所以本系列教程到此结束。你可以在这里下载工程的源代码。

如何在 iOS 8 中使用 Swift 实现本地通知(下)的更多相关文章

  1. 如何在 iOS 8 中使用 Swift 实现本地通知(上)

    当你的应用在后台运行时,可以简单地使用本地通知把信息呈现给用户.它可以允许你显示 提醒.播放提示音和数字角标(badge).本地通知可以被以下的事件触发:计划好的时间点或者用户进入和离开某个地理区域. ...

  2. 如何在C语言中调用Swift函数

    在Apple官方的<Using Swift with Cocoa and Objectgive-C>一书中详细地介绍了如何在Objective-C中使用Swift的类以及如何在Swift中 ...

  3. 如何在IOS开发中在自己的framework中添加.bunble文件

    今天就跟大家介绍一下有关,如何在IOS开发中在自己的framework中添加.bunble文件,该文章我已经在IOS教程网(http://ios.662p.com)发布过来,个人觉得还是对大家有帮助的 ...

  4. 转 如何在IOS设备中去掉屏幕上的status bar

    引入如何在IOS设备中去掉屏幕上的status bar,即:不显示设备上方的[网络.时间.电池??]条?操作方法一:在-info.list项目文件中,加上“Status bar is initiall ...

  5. 如何在iOS设备中配置S/MIME邮件签名证书

    本篇将介绍如何在iOS设备(如iPhone或iPad)上导入.配置并使用S/MIME邮件证书. 前置条件: iOS设备上已完成邮箱账号配置: 您的S/MIME邮件证书PFX/P12文件已导出备用. 步 ...

  6. <转>如何在iOS 7中设置barTintColor实现类似网易和 Facebook 的 navigationBar 效果

    转自:i‘m Allen的博客 先给代码:https://github.com/allenhsu/CRNavigationController 1. 问题的表现 相信很多人在 iOS 7 的适配过程中 ...

  7. iOS OC中桥接swift第三方库

    swift中有一些比较好的框架,比如绘图框架charts,最近项目中刚好用到,通过Pod的方式直接导入,xcode会自动生成charts-swift.h的文件,然后在需要导入的地方import < ...

  8. ios开发——实用技术OC-Swift篇&本地通知与远程通知详解

    本地通知与远程通知详解 一:本地通知   Local Notification的作用 Local Notification(本地通知) :是根据本机状态做出的通知行为,因此,凡是仅需依赖本机状态即可判 ...

  9. iOS监听模式系列之本地通知Notification

    本地通知 本地通知是由本地应用触发的,它是基于时间行为的一种通知形式,例如闹钟定时.待办事项提醒,又或者一个应用在一段时候后不使用通常会提示用户使用此应用等都是本地通知.创建一个本地通知通常分为以下几 ...

随机推荐

  1. win7 提示"Windows 无法连接到System Event Notification Service服务......"的解决办法

    登录win7系统,突然出现如图1的提示,无线网络中断,不能上网,多次插拔无线网卡问题依然. 图1 解决过程如下: 1.检查网卡硬件状况,在设备管理器中查看网卡现象正常,排除网卡硬件故障. 2.查看服务 ...

  2. C++中的基类与派生类

    派生类的继承方式总结: 继承方式 说明 public 基类的public和protected的成员被派生类继承后,保持原来的状态 private 基类的public和protected的成员被派生类继 ...

  3. 10个常见的IE bug和解决方法

    1.IE6 幽灵文本(Ghost Text bug) 在我写本文之前,我遇到了这个bug.它相当的古怪和滑稽.一块不知哪来的重复的文本,被IE6显示在靠近原文本的下面.(译注:也可以参看 Explor ...

  4. ShellExecute的各种用法

    一.利用系统默认的邮件收发器发送电子邮件 Uses ..., ShellAPI; Var lpHwnd: HWND; lpOperation, lpFile, lpParameters, lpDire ...

  5. Camel In Action 阅读笔记 第一部分概述 + 第一章概述 认识Camel

    第一部分: 最开始的一小步 Apache Camel 是一个开源集成框架,其目的是让系统集成变得更加简便,在本书的第一章中,我们会为您介绍它并向您展示它是如何在大型企业应用中做好集成工作.您也会了解到 ...

  6. dom 封装表单控件

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  7. 使用Java程序调用MatLab

    Java代码实现的计算难免会显得不够高效.而利用MATLAB写好相应的计算函数,然后打包成jar包供Java调用,在某些情况下会更加方便.或者有些时候会涉及到使用Java调用MatLab展现一些二维三 ...

  8. MySQL 5.5 服务器变量详解一(转)

    add by zhj:在MySQL5.6中对一些参数有增删改,详见http://dev.mysql.com/doc/refman/5.6/en/server-system-variables.html ...

  9. 关于MAC下的QQ聊天中看不到对方所发的图片解决

    使用QQ聊天我们会经常碰到一件让人烦心的事情,那就是别人发的截图自己看不大,是一张裂图(腾讯默认的那张图片).通常有几种情况可以造成这种结果: 第一种原因,网络延迟原因,你的网络不好或者对方的网络不好 ...

  10. HDU 4617 Weapon (简单三维计算几何,异面直线距离)

    Weapon Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Subm ...