iOS 闹钟的实现

概述

iOS的机制是一旦程序处于后台,那么程序就处于暂停状态,这也是iOS系统后台开很多应用依旧流畅的原因,因为这个机制,所以类似闹钟这样的应用就不能用定时器实现
那么我们要怎样实现定时提醒的功能呢

iOS的通知是系统级的 ,也就是说就算我们的软件关闭了,他依然能通知我们,但是他只能做到定时通知,所以没办法实现定时任务,所以基本上iOS上实现(不能全自动)定时任务的流程都是

注册通知 –> 添加通知 –> 通知栏显示通知 –> 点击通知进入软件 –> 处理通知

下面就用实际代码实现这个功能

示例

注册通知

只有APP注册了通知,那么添加的本地通知才能被接受到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//注册通知
func registerNofitication(){
if #available(iOS 8.0, *) {
let types:UIUserNotificationType = [UIUserNotificationType.Alert, UIUserNotificationType.Badge,UIUserNotificationType.Sound];
let acceptAction = UIMutableUserNotificationAction()
acceptAction.identifier = "ACCEPT_IDENTIFIER";
acceptAction.title = "Accept";

acceptAction.activationMode = UIUserNotificationActivationMode.Foreground;
acceptAction.destructive = false;
acceptAction.authenticationRequired = false;

//Categories
let inviteCategory = UIMutableUserNotificationCategory();

inviteCategory.identifier = "INVITE_CATEGORY";

inviteCategory.setActions([acceptAction], forContext: UIUserNotificationActionContext.Default);
inviteCategory.setActions([acceptAction], forContext: UIUserNotificationActionContext.Minimal);

let categories = NSSet(object: inviteCategory);

let mySettings = UIUserNotificationSettings(forTypes: types, categories: categories as? Set<UIUserNotificationCategory>);
UIApplication.sharedApplication().registerUserNotificationSettings(mySettings);
UIApplication.sharedApplication().registerForRemoteNotifications();
} else {
UIApplication.sharedApplication().registerForRemoteNotificationTypes([UIRemoteNotificationType.Alert,UIRemoteNotificationType.Badge,UIRemoteNotificationType.Sound]);
};
}

添加本地通知

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
添加通知

- parameter date:本地通知的时间
- parameter attendanceType:签到或签退
*/
func addNotifation(date:NSDate,attendanceType:String){
let notification = UILocalNotification();
notification.fireDate = date;
notification.repeatInterval = NSCalendarUnit.Day;
notification.timeZone = NSTimeZone.defaultTimeZone();
//notification.applicationIconBadgeNumber=1; //应用的红色数字
notification.soundName = UILocalNotificationDefaultSoundName;
notification.alertBody = "考勤君友情提示:不签到要扣工资的哟!";//提示信息
notification.alertAction = "打开"; //提示框按钮
var userInfo:[String:String] = [:];
userInfo["type"] = "考勤";
userInfo["attendanceType"] = attendanceType;
notification.userInfo = userInfo;

//添加通知
UIApplication.sharedApplication().scheduleLocalNotification(notification);
}

代码中通知的重复周期为NSCalendarUnit.Day,所以每天都会通知,要想一天通知4次的话,只能注册四个通知,并设置重复周期为NSCalendarUnit.Day

删除原有的通知

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
删除原有的考勤通知
*/
func delLocalNotification(){
let application = UIApplication.sharedApplication();
let localNotifications = application.scheduledLocalNotifications;

guard localNotifications != nil else{
return;
}

guard localNotifications!.count>0 else {
return;
}

for localNotification in localNotifications!{

guard let userInfo = localNotification.userInfo else{
continue;
}

guard let type = userInfo["type"] else {
continue;
}

if((type as! String) == "考勤"){
application.cancelLocalNotification(localNotification);
}

}
}

清空本应用所有消息

1
2
3
4
5
6
7
8
/**
清空所有本应用的消息(不再通知)
*/
func clearAllNotifation(){
let application = UIApplication.sharedApplication();
application.applicationIconBadgeNumber = 0;
application.cancelAllLocalNotifications();
}

清空本应用通知栏的所有消息

1
2
3
4
5
6
7
/**
清空所有本应用的通知栏消息(会继续通知)
*/
func clearAllNotifation(){
let application = UIApplication.sharedApplication();
application.applicationIconBadgeNumber = 0;
}

接受本地推送的代理方法

该方法会在两种情况下运行

  • app处于激活状态 接受本地通知时调用
  • app处于关闭或未激活状态,接受本地通知时不调用,点击消息后进入app后调用

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
func application(application: UIApplication, didReceiveLocalNotification notification: UILocalNotification) {
print("接受本地推送")

guard let userInfo = notification.userInfo else{
return;
}

guard let type = userInfo["type"] else{
return;
}

guard let attendanceType = userInfo["attendanceType"] else{
return;
}

guard (type as! String) == "考勤" else {
return;
}

if((attendanceType as! String) == "签到"){
//签到的方法
}else if((attendanceType as! String) == "签退"){
//签退的方法
}
}