大家都知道Push Notification,这个东西需要联网才可以用。iOS4起,苹果引入了一种可以在设备内部引发的notification。不需要复杂的服务器编程,或其他复杂的配置。这个技术就是Local Notification。

Local notificaton可以在用户设定里定时触发。甚至,你可以设定重发。下面,我们就来研究下Local Notification,看看如何设定,查看和处理Local Notification。

1. 创建项目

总体来说是这么个效果:

一共分三层,最上面一层是DatePicker。用于选择出发Local Notification的时间。第二层是一个TextField,用于设定Notification的title。最后是设定过的Notification都放在一个TableView里。看看都有什么:

    UIDatePicker *datePicker = [[UIDatePicker alloc] initWithFrame:CGRectMake(0, 44, 320, 160)];
[self.view addSubview:datePicker]; UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 227, 150, 40)];
[self.view addSubview:textField];
textField.borderStyle = UITextBorderStyleRoundedRect;
textField.placeholder = @"Input Text";
self.textField = textField; UIButton *saveButton = [[UIButton alloc] initWithFrame:CGRectMake(155, 227, 160, 40)];
[self.view addSubview:saveButton];
saveButton.backgroundColor = [UIColor orangeColor];
[saveButton setTitle:@" SAVE " forState:UIControlStateNormal];
[saveButton addTarget:self action:@selector(saveAction:) forControlEvents:UIControlEventTouchUpInside]; CGFloat height = [UIScreen mainScreen].bounds.size.height - 242;
UITableView *notiTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 268, 320, height)];
[self.view addSubview:notiTableView];
notiTableView.delegate = self;
notiTableView.dataSource = self;

与UI元素对应的,我们这里有三层,四个界面元素。同事还有Button的一个action。同事需要注意的是,我们需要在Controller里实现UITableViewDelegate和UITableViewDataSource这两个protocol。要是用UITableView这两个protocol必须实现。

其他还要做一些必要的操作。比如创建一个空的设定notification的方法,等。

#pragma mark - Private methods

- (void)saveAction:(id)sender{
DLog(@"");
[self.textField resignFirstResponder];
} #pragma mark - UITableViewDelegate & datasource - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return ;
} - (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
} return cell;
}

在saveAction方法中,设定notification时退出textfield的编辑状态并隐藏键盘。所以,需要调用resignFirestResponder方法,[self.textField resignFirstResponder]

后面的UITableView相关的protocol中,暂时指定返回的行数为1,并在返回Cell的方法中返回没有设定任何内容的行。这样,代码就可以正常运行。否则,会因为没有实现必要的protocol方法而crash。

这个时候,在运行app之后就会出现上面给出的效果图。(注意:这里用的是真机运行的app)

2. 设定notification

这里是全教程的核心所在了。折腾完全文也都是基于这里所讲的内容。

首先,在DatePicker里设定好时间。之后在设定notification的内容。最后把指定推送在指定的时间引发。

- (void)saveAction:(id)sender{
DLog(@"");
[self.textField resignFirstResponder]; NSDate *pickerDate = [self.datePicker date]; UILocalNotification *localNotification = [[UILocalNotification alloc] init];
if (localNotification) {
localNotification.fireDate = pickerDate;//fireDate;
localNotification.timeZone = [NSTimeZone defaultTimeZone];
localNotification.alertBody = self.textField.text;
localNotification.alertAction = @"View";
localNotification.soundName = UILocalNotificationDefaultSoundName;
localNotification.applicationIconBadgeNumber = 1;
localNotification.userInfo = @{@"userId": @"best user", @"userName": @"Jack"};
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification]; [self.notificationTableView reloadData];
}
}

就如前文所述,使用NSDate *pickerDate = [self.datePicker date]; 获取到DatePicker中设定的日期,之后在Local notification对象的fireDate属性里赋值。localNotification.alertBody = self.textField.text设定提示的文本。使用localNotification.userInfo = @{@"userId": @"best user", @"userName": @"Jack"}设定用户信息,就是你觉得有用的信息以字典的方式存放在notification对象中,在其他的时候可以获取这个字典。最后,最关键的就是使用[[UIApplication sharedApplication] scheduleLocalNotification:localNotification]设定notification在指定的时间触发。

到这里,就可以指定一个Local notification在给定的时间触发了。但是还有一种场景,在用户做了某个操作的时候,notification立刻触发。这时,再用schecule的方法就会很奇怪,schedule一秒可能赶不上,schedule的秒多了可能错过正确的提示时机。所以API里提供了另一个方法presentNow,提示立刻触发。正确的立刻触发的方法是:[[UIApplication sharedApplication] presentLocalNotificationNow:localNotification]。其他初始化和设定相关属性的方法都没有任何的变化。

3. 把设定过的notification都现实在TableView里

之前使用了一些dummy的方法,只是为了能让app正常的运行。这里补全所有必要的代码。

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [[UIApplication sharedApplication] scheduledLocalNotifications].count;
} - (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
} NSArray *notifications = [[UIApplication sharedApplication] scheduledLocalNotifications];
UILocalNotification *n = notifications[indexPath.row]; cell.textLabel.text = n.alertBody;
cell.detailTextLabel.text = [n.fireDate description]; return cell;
}

[[UIApplication sharedApplication] scheduledLocalNotifications]包含了全部的schedule过了的notification数组,count属性就是数量。在- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath中从notification数组中取出对应元素,显示在UITableView的Cell中,分别是:cell.textLabel.text = n.alertBody, cell.detailTextLabel.text = [n.fireDate description]。

最后

似乎是一切都完美了。notification也有了,可以通过界面的DatePicker指定时间,可以立即触发,还可以指定提示的内容。而且,还会在“铛”的一声,然后在app的图标上显示一个badge number出来。但是,当你点击了提示之后,进入到app里再出来你会发现。。。。。。badge number还是华丽丽的在那里木有消失。是的本来应该点开了notification之后就消失的,这是为什么呢。处理badge number的代码也需要我们手动的写出来。最后我们来处理这一部分的功能。

这里需要注意到两种情况:1. 设定好了notification的出发时间以后,app退出了。这个退出是说双击home键以后,上滑了这个app,终止了app进程。2. app还在运行着,也许是在触发notification的时候app还在运行中,或者app的进程还在运行中。

第一种情况:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; BVRootViewController *rootViewController = [[BVRootViewController alloc] init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:rootViewController];
self.window.rootViewController = nav; self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible]; application.applicationIconBadgeNumber = 0; UILocalNotification *n = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if (n) {
DLog(@"Received notification %@", n);
} return YES;
}

第二种情况:

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification{
application.applicationIconBadgeNumber = 0;
DLog(@"Received notification %@", notification);
}

哦了!

Local Notification的更多相关文章

  1. ios push local notification

    UILocalNotification* localNotification = [[UILocalNotification alloc]init]; localNotification.alertB ...

  2. iOS 远程通知(Remote Notification)和本地通知(Local Notification)

    ios通知分为远程通知和本地通知,远程通知需要连接网络,本地通知是不需要的,不管用户是打开应用还是关闭应用,我们的通知都会发出,并被客户端收到 我们使用远程通知主要是随时更新最新的数据给用户,使用本地 ...

  3. cordova local notification plugin

    cordova plugin add org.apache.cordova.device cordova plugin add https://github.com/katzer/cordova-pl ...

  4. iOS 10.0之前和之后的Local Notification有神马不同

    在iOS 10.0之前apple还没有将通知功能单独拿出来自成一系.而从10.0开始原来的本地通知仍然可用,只是被标记为过时.于是乎我们可以使用10.0全新的通知功能.别急-让我们慢慢来,先从iOS ...

  5. [Xamarin] 關於發出Notification 的大小事 (转帖)

    關於Anroid 的使用者來說,Notification 是一個非常會看到且用到的功能 他可以提醒使用者甚麼東西需要待處理,像是郵件或是會議的提醒等.. 甚至有些APP ,直接使用Notificati ...

  6. ios notification

    apps can use local or push notifications to let people know when interesting things happen, such as: ...

  7. [转载]iOS 10 UserNotifications 框架解析

    活久见的重构 - iOS 10 UserNotifications 框架解析 TL;DR iOS 10 中以前杂乱的和通知相关的 API 都被统一了,现在开发者可以使用独立的 UserNotifica ...

  8. ios 消息通知

    苹果的通知分为本地通知和远程通知,这里主要说的是远程通知 历史介绍 iOS 3 - 引入推送通知UIApplication 的 registerForRemoteNotificationTypes 与 ...

  9. iOS 多任务

    本文转自猫神的博客:https://onevcat.com/2013/08/ios7-background-multitask/ 写的没的说,分享给大家,一起学习! iOS7以前的Multitaski ...

随机推荐

  1. UVA-11292Dragon of Loowater

    /* The Dragon of Loowater Once upon a time, in the Kingdom of Loowater, a minor nuisance turned into ...

  2. ISIS与OSPF的区别与联系

    共同之处: 1 都是链路状态路由协议,都要求区域内的路由器交换链路状态信息,链路状态信息被收集到链路状态数据库中 2 都是用了一种实现路由选择信息交换相似机制 3 都在广播网络中选择指定路由器来控制扩 ...

  3. 各自平台token获取解析及用户信息的获取

    1.auth根据手机号码获取auth平台session_token记统一认证的user_id与pass_id [dwliuchao1@GD-QHD-CNG152TFKX-12.55 logs]$ cd ...

  4. GPRS 通信

    最近使用SIM900A GSM/GPRS模块,做一些简单物联网信息投递. 1.选取何种流量卡 一般来讲,需要带身份证去运营商办理新的电话卡.对于小流量用户,实际上就是办一个最低月租即可,因为套餐会赠送 ...

  5. IOS 后台之长时间任务 beginBackgroundTaskWithExpirationHandler 申请后台十分钟 600秒

    10分钟 beginBackgroundTaskWithExpirationHandler,beginBackgroundTaskWithName endBackgroundTask 定义变量 UIB ...

  6. spring源码解析之AOP原理

    一.准备工作 在这里我先简单记录下如何实现一个aop: AOP:[动态代理] 指在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式: 1.导入aop模块:Spring AOP:(s ...

  7. 使用Eclipse搭建JavaWeb开发环境的几个基本问题

    Eclipse搭建JavaWeb开发环境 eclipse是一个用于java程序开发的ide软件,tomcat是一个运行javaweb应用的服务器软件,使用eclipse开发javaweb应用的时,首要 ...

  8. Elasticsearch 全字段搜索_all,query_string查询,不进行分词

    最近在使用ELasitcsearch的时候,需要用到关键字搜索,因为是全字段搜索,就需要使用_all字段的query_string进行搜索. 但是在使用的时候,遇到问题了.我们的业务并不需要分词,我在 ...

  9. Java服务器工程师任职资格

    Java服务器端开发工程师 1.Java服务器端3年以上开发经验 2.至少一个完整游戏项目经验 3.熟练掌握OOA.OOD.OOP 4.掌握常见网游协议开发方法 5.对TCP/IP有深入了解 6.对消 ...

  10. if __name__ == '__main__'的作用和原理

    最简单的理解就是这样: __name__ 是当前模块名,当模块被直接运行时,模块名为 __main__. 所以 if __name__ == '__main__' 这句话的意思就是当前模块被直接运行时 ...