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

本地通知与远程通知详解

一:本地通知
 
Local Notification的作用
Local Notification(本地通知) :是根据本机状态做出的通知行为,因此,凡是仅需依赖本机状态即可判断需要发出通知的行为都可以或者说应该使用Local Notification来处理。比方说:iBeacon中进入了某个Beacon region,或者说自定义的一些定时提醒等。
构建Local Notification
在iOS中,构建LocalNotification非常简单,只需要掌握好NSLocalNotification这个类就够用了,基本步骤如下:
1. 创建并初始化 UILocalNotification对象
2. 配置该对象的属性:
  • * 触发时间(fireDate,timeZone,repeatInterval,repeatCalendar),如果你想根据时间来触发。
  • * 通知行为(alertAction,hasAction),定义查看通知的操作名。
  • * 触发通知时的启动画面(alertLaunchImage)
  • * 通知的正文内容(alertBody),
  • * 通知的背景声(soundName)
  • * 通知消息数的展示(applicationIconBadgeNumber),就是强迫症们最讨厌的App图标上左上角的那个小数字
  • * 其它(userInfo),可以给通知绑定一些处理通知时需要的额外信息。
3.展示通知,展示通知有两个方式:
  • * - (void)scheduleLocalNotification:(UILocalNotification *)notification:根据触发时间的配置展示通知消息,
  • * - (void)presentLocalNotificationNow:(UILocalNotification *)notification:立即发送通知到本机
栗子:
 1 - (void)showNotificationWithAction:(NSString *)action andContent:(NSString *)content
 2 {
 3   UILocalNotification *notification = [[UILocalNotification alloc] init];
 4   notification.alertBody = content;
 5   notification.alertAction = action;
 6   notification.soundName = UILocalNotificationDefaultSoundName;
 7   [[UIApplication sharedApplication] presentLocalNotificationNow:notification];
 8 }
 9 
10 - (void)scheduleNotificationWithItem:(ToDoItem *)item interval:(int)minutesBefore {
11   NSCalendar *calendar = [NSCalendar autoupdatingCurrentCalendar];
12   NSDateComponents *dateComps = [[NSDateComponents alloc] init];
13   [dateComps setDay:item.day];
14   [dateComps setMonth:item.month];
15   [dateComps setYear:item.year];
16   [dateComps setHour:item.hour];
17   [dateComps setMinute:item.minute];
18   NSDate *itemDate = [calendar dateFromComponents:dateComps];
19  
20   UILocalNotification *localNotif = [[UILocalNotification alloc] init];
21   if (localNotif == nil)
22     return;
23   localNotif.fireDate = [itemDate dateByAddingTimeIntervalInterval:-(minutesBefore*60)];
24   localNotif.timeZone = [NSTimeZone defaultTimeZone];
25  
26   localNotif.alertBody = [NSString stringWithFormat:NSLocalizedString(@"%@ in %i minutes.", nil),
27      item.eventName, minutesBefore];
28   localNotif.alertAction = NSLocalizedString(@"View Details", nil);
29  
30   localNotif.soundName = UILocalNotificationDefaultSoundName;
31   localNotif.applicationIconBadgeNumber = 1;
32  
33   NSDictionary *infoDict = [NSDictionary dictionaryWithObject:item.eventName forKey:ToDoItemKey];
34   localNotif.userInfo = infoDict;
35  
36   [[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
37 }

 

处理Local Notification
在处理本地通知时,我们需要考虑三种情况:
1. App没有启动,
这种情况下,当点击通知时,会启动App,而在App中,开发人员可以通过实现*AppDelegate中的方法:- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions,然后从lauchOptions中获取App启动的原因,若是因为本地通知,则可以App启动时对App做对应的操作, 比方说跳转到某个画面等等。栗子:
 1 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
 2 {
 3   NSLog(@"Start App....");
 4   ....
 5   UILocalNotification *localNotification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
 6   if ([self isWelcomeNotification:localNotification]) {
 7     NSLog(@"start with welcome notification");
 8     [self.mainViewController showOfficeIntroduction];
 9   }
10   return YES;
11 }

 

2. App运行在后台
3. App运行在前台
上面的2种情况的处理基本一致, 不同点只有当运行再后台的时候,会有弹窗提示用户另外一个App有通知,对于本地通知单的处理都是通过*AppDelegate的方法:- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification来处理的。 栗子:
1 - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
2 {
3     if ([self isWelcomeNotification:notification]) {
4        [self.mainViewController showOfficeIntroduction]; 
5     }if ([self isCustomerDataNotification:notification]) {
6         [self.mainViewController showCustomerDataIntroduction];
7     }
8 }

 

Swift
 
 1  if ( UIApplication . instancesRespondToSelector ( Selector ( "registerUserNotificationSettings:" ))) {
 2 
 3 application. registerUserNotificationSettings ( UIUserNotificationSettings (forTypes:  UIUserNotificationType .Sound |  UIUserNotificationType .Alert |  UIUserNotificationType .Badge, categories:  nil ))
 4 
 5 } else {
 6 
 7 application. registerForRemoteNotificationTypes (.Alert | .Sound | .Badge)
 8 
 9 }
10 
11 然后,在Appdelegate.swift 写相关远程推送、本地通知等代码
12 
13 // 收到本地通知
14 
15 func application(application: UIApplication , didReceiveLocalNotification notification: UILocalNotification ) {
16 
17 var alertView = UIAlertView (title: " 系统本地通知 " , message: notification. alertBody , delegate: nil , cancelButtonTitle: " 返回 " )
18 
19 alertView. show ()
20 
21 }

本地通知方法:

  1  ****************************** 本地通知方法 ********** ***** ***************  
  2 
  3 //
  4 
  5 //  TimeViewController.swift
  6 
  7 //  UIControlDemo
  8 
  9 //
 10 
 11 //  Created by  on 14/12/10.
 12 
 13 //  Copyright (c) 2014 年 马大哈 . All rights reserved.
 14 
 15 //
 16 
 17 import UIKit
 18 
 19 class TimeViewController: BaseViewController {
 20 
 21 var wordTextField: UITextField ? // 文字
 22 
 23 var dateTextField: UITextField ? // 时间
 24 
 25 var datePicker: UIDatePicker ?
 26 
 27 override func viewDidLoad() {
 28 
 29 super . viewDidLoad ()
 30 
 31          self . title = " 时间 / 日期 / 本地通知 "         
 32 
 33 let leftBarButton: UIBarButtonItem = UIBarButtonItem (barButtonSystemItem: . Trash , target: self , action: "locaNotifcationDeleteAll" )
 34 
 35 self . navigationItem . rightBarButtonItem = leftBarButton;
 36 
 37 wordTextField = UITextField (frame: CGRectMake ( 50 , 80 , 200 , 40 ))
 38 
 39 wordTextField ?. backgroundColor = . clearColor ()
 40 
 41 wordTextField !. tag = 100
 42 
 43 wordTextField ?. borderStyle = UITextBorderStyle . RoundedRect
 44 
 45 wordTextField ?. keyboardType = UIKeyboardType . Default
 46 
 47 wordTextField ?. returnKeyType = UIReturnKeyType . Done
 48 
 49 wordTextField ?. contentVerticalAlignment = UIControlContentVerticalAlignment . Center
 50 
 51 wordTextField ?. clearButtonMode = UITextFieldViewMode . WhileEditing
 52 
 53 wordTextField ?. secureTextEntry = false
 54 
 55 wordTextField ?. textColor = . blackColor ()
 56 
 57 wordTextField ?. textAlignment = . Left
 58 
 59 wordTextField ?. placeholder = " 键盘 "
 60 
 61 wordTextField ?. font = UIFont . systemFontOfSize ( 15 )
 62 
 63 self . view . addSubview ( wordTextField !)
 64 
 65 dateTextField = UITextField (frame: CGRectMake ( 50 , 140 , 200 , 40 ))
 66 
 67 dateTextField ?. backgroundColor = . clearColor ()
 68 
 69 dateTextField !. tag = 101
 70 
 71 dateTextField ?. borderStyle = UITextBorderStyle . RoundedRect
 72 
 73 dateTextField ?. keyboardType = UIKeyboardType . Default
 74 
 75 dateTextField ?. returnKeyType = UIReturnKeyType . Done
 76 
 77 dateTextField ?. contentVerticalAlignment = UIControlContentVerticalAlignment . Center
 78 
 79 dateTextField ?. textColor = . blackColor ()
 80 
 81 dateTextField ?. textAlignment = . Left
 82 
 83 dateTextField ?. placeholder = " 日期 picker"
 84 
 85 dateTextField ?. font = UIFont . systemFontOfSize ( 15 )
 86 
 87 self . view . addSubview ( dateTextField !)
 88 
 89  
 90 
 91 datePicker = UIDatePicker ()
 92 
 93 datePicker ?. datePickerMode = . DateAndTime
 94 
 95 datePicker ?. timeZone = NSTimeZone . systemTimeZone ()
 96 
 97 datePicker ?. addTarget ( self , action: "datePickerSelected:" , forControlEvents: UIControlEvents .ValueChanged)
 98 
 99 dateTextField !. inputView = datePicker
100 
101         
102 
103 var button = UIButton . buttonWithType ( UIButtonType . Custom ) as UIButton
104 
105 button. frame = CGRectMake ( 200 , 200 , 50 , 30 )
106 
107 button. backgroundColor = UIColor . redColor ()
108 
109 button. setTitleColor ( UIColor . blackColor (), forState:.Normal)
110 
111 button. setTitle ( " 保存 " , forState: UIControlState .Normal)
112 
113 button. titleLabel !. font = UIFont . boldSystemFontOfSize ( CGFloat ( 20 ))
114 
115 button. showsTouchWhenHighlighted = true
116 
117 button. addTarget ( self , action: "saveLocalNotificationButton" , forControlEvents: UIControlEvents .TouchUpInside)
118 
119 self . view . addSubview (button)
120 
121 }
122 
123 // 保存按钮方法
124 
125 func saveLocalNotificationButton(){
126 
127 var contentDic = [ "KEY" : "VALUE" ]
128 
129 locaNotifcationSchedule (chedulDate: datePicker !. date , alertBody: " 通知看到 : /( wordTextField !. text ) " , content: contentDic)
130 
131 var alertView = UIAlertView (title: " 保存成功 " , message: nil , delegate: nil , cancelButtonTitle: " 返回 " )
132 
133 alertView. show ()
134 
135 wordTextField ?. resignFirstResponder ()
136 
137 dateTextField ?. resignFirstResponder ()
138 
139 }
140 
141     
142 
143 // 注册本地通知
144 
145 func locaNotifcationSchedule(#chedulDate: NSDate ,alertBody: String ,content: NSDictionary ) {
146 
147 var localNotif = UILocalNotification ()
148 
149 localNotif. fireDate = chedulDate
150 
151 localNotif. timeZone = NSTimeZone . defaultTimeZone ()
152 
153 //        localNotif.repeatInterval = repeatInterval 0 代表不重复
154 
155 localNotif. soundName =  "iPhone.caf" // 此属性可以不写(默认系统声音 UILocalNotificationDefaultSoundName )
156 
157 //        localNotif.hasAction = true;
158 
159 //        localNotif.alertAction = " 查看 ";
160 
161 localNotif. alertBody = alertBody
162 
163 localNotif. userInfo   = content
164 
165 UIApplication . sharedApplication (). scheduleLocalNotification (localNotif)  
166 
167 }
168 
169 // 删除所有注册的本地通知
170 
171 func locaNotifcationDeleteAll() {
172 
173 let application = UIApplication . sharedApplication ()
174 
175 application. cancelAllLocalNotifications ()
176 
177 var alertView = UIAlertView (title: " 所有本地通知都已移除 " , message: nil , delegate: nil , cancelButtonTitle: " 返回 " )
178 
179 alertView. show ()
180 
181 }
182 
183 // 动态改变 textfield 内容
184 
185 func datePickerSelected(datePicker: UIDatePicker ){
186 
187 let dateString = timeDateFormatter (). stringFromDate (datePicker. date )
188 
189 dateTextField !. text = dateString
190 
191 }
192 
193 override func touchesEnded(touches: NSSet , withEvent event: UIEvent ) {
194 
195 wordTextField ?. resignFirstResponder ()
196 
197 dateTextField ?. resignFirstResponder ()
198 
199 }
200 
201 override func didReceiveMemoryWarning() {
202 
203 super . didReceiveMemoryWarning ()
204 
205 }
206 
207 }

 

 
 
二:远程通知
 

首先是申请证书的网址

https://developer.apple.com/ios/manage/overview/index.action

登录成功以后,进入iOS 配置管理的 主页面.

ios开发——实用技术OC-Swift篇&本地通知与远程通知详解_第1张图片

第一步操作是去创建一个新的App IDs创建成功后,会需要提供安全证书来激动推送服务,如下图:


ios开发——实用技术OC-Swift篇&本地通知与远程通知详解_第2张图片



ios开发——实用技术OC-Swift篇&本地通知与远程通知详解_第3张图片

ios开发——实用技术OC-Swift篇&本地通知与远程通知详解_第4张图片

 

选择存储到磁盘以后,生成一个文件名称为(简称CSR): CertificateSigningRequest.certSigningRequest

回到Apple页面 将这个提交并提示激动成功.

激活成功后的App  IDs 提供下载开发版或是发布版的主动推送证书(aps_development.cer),如果需要做服务器方面的主动推送的话,就必须要下载这个文件来使用推送服务了.

第二步要为App提供接受推送许可的证书,点击Provisioning进行设置,添加一个新的许可,选择刚刚新创建的App IDs. 再选择可以调试的iPhone 设备.

最后,同样是下载下来: YsyPushMessageDemo.mobileprovision双击该证书,让其加载一次.

接下来,进入iOS工程,选择使用该证书来调试.

 

ios开发——实用技术OC-Swift篇&本地通知与远程通知详解_第5张图片

 

红圈中,全部设置刚刚加载的许可证书.

 

那么到这里,关于证书类的准备工作,已经全部准备就绪.

在这里再此强调一次,每个文件的具体作用

1: CertificateSigningRequest.certSigningRequest : 为生成App IDs 而用

2: aps_development.cer 为开发主动推送服务而用到的证书

3: YsyPushMessageDemo.mobileprovision 为App 接受推送通知的许可服务

 

主动推送的Push 代码及使用,请参考一开始介绍的第一篇博客

这里只附上下载地址: https://github.com/stefanhafeneger/PushMeBaby

 

接下来,说说收到推送通知代码方面.

1:申请本App需要接受来自服务商提供推送消息,

 

  1 [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)]; 

2:申请发出后,如果成功,委托会自动返回一个设备令牌(toKen),如果失败,将会进入另外一个失败的委托

 

 

 1     //远程通知注册成功委托  
 2     - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken  
 3     {  
 4         NSLog(@"%@",deviceToken);  
 5         self.viewController.toKenValueTextView.text = [NSString stringWithFormat:@"%@",deviceToken];  
 6         self.viewController.pushStatusLabel.text = @"已经注册.";  
 7     }  
 8     //远程通知注册失败委托  
 9     -(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error  
10     {  
11         self.viewController.toKenValueTextView.text = [error description];  
12     }  

 


3:将设备令牌码提供给服务商,以供推送到具体的手机上面. 如果远程推送消息来了,用户点击了推送消息,或者应用已经处于打开状态,系统都会自动调用以下委托:

 

 

1      //点击某条远程通知时调用的委托 如果界面处于打开状态,那么此委托会直接响应  
2     -(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo  
3     {  
4         NSLog(@"远程通知");  
5         [self PMD_uesPushMessage:userInfo];  
6     }  

 


4: 第三点里面的介绍的情况是应用程序已经处于运行状态,上面的委托才会被执行,如果应用程序处于未启用状态,此时又需要响应消息,那么需要以下委托处理.

 

 

1  - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions  
2 {  
3     //这里处理应用程序如果没有启动,但是是通过通知消息打开的,此时可以获取到消息.  
4     if (launchOptions != nil) {  
5         NSDictionary *userInfo = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];  
6         [self PMD_uesPushMessage:userInfo];  
7     }  
8     return YES;  
9 } 

 

5:清空通知中心已有的推送消息,只需要将指定App 的 Badge 设置为 0即可

 

  1 [[UIApplication sharedApplication ] setApplicationIconBadgeNumber:0];  

 

6:主动推送的字符串必须符合如下Json数组的格式,才能正确推送到手机当中.

 

 

   

 1 @"{
 2 
 3        //自定义参数
 4 
 5        "userinfo":
 6 
 7               {
 8 
 9                  "name":"remote notice"
10 
11               },
12 
13        //标准写法
14 
15        "aps":
16 
17               {
18 
19                  "alert":
20 
21                            {
22 
23                               "action-loc-key":"Open",//支持多语言
24 
25                               "body":"messgae content"//消息正文
26 
27                            },
28 
29                  "badge":1,//为App 的icon  标记 具体数值
30 
31                  "sound":"default" //播放的音频文件,default 表示系统默认的选择列铃声
32 
33              } 
34 
35      }";

 

 

 

 

到这里就差不多结束了.

 

php服务器推送消息

 

 

 1      <?php  
 2       
 3     $deviceToken = '38c866dd bb323b39 ffa73487 5e157ee5 a85e0b7ce90d56e9 fe145bcc 6c2c594b'; // masked for security reason  
 4     // Passphrase for the private key (ck.pem file)  
 5     // $pass = '';  
 6     // Get the parameters from http get or from command line  
 7     $message = $_GET['message'] or $message = $argv[1] or $message = 'Message received from javacom';  
 8     $badge = (int)$_GET['badge'] or $badge = (int)$argv[2];  
 9     $sound = $_GET['sound'] or $sound = $argv[3];  
10     // Construct the notification payload  
11     $body = array();  
12     $body['aps'] = array('alert' => $message);  
13     if ($badge)  
14     $body['aps']['badge'] = $badge;  
15     if ($sound)  
16     $body['aps']['sound'] = $sound;  
17       
18       
19     $ctx = stream_context_create();  
20     stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');  
21     // assume the private key passphase was removed.  
22     // stream_context_set_option($ctx, 'ssl', 'passphrase', $pass);  
23     $fp = stream_socket_client('ssl://gateway.sandbox.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx);  
24     if (!$fp) {  
25     print "Failed to connect $err $errstrn";  
26     return;  
27     }  
28     else {  
29     print "Connection OKn";  
30     }  
31     $payload = json_encode($body);  
32     $msg = chr(0) . pack("n",32) . pack('H*', str_replace(' ', '', $deviceToken)) . pack("n",strlen($payload)) . $payload;  
33     print "sending message :" . $payload . "n";  
34     fwrite($fp, $msg);  
35     fclose($fp);  
36     ?>

 

 
Swift
 
 
 1      // 远程推送通知 注册成功
 2 
 3 func application(application: UIApplication , didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData ) {
 4 
 5 println (deviceToken. description )
 6 
 7 }
 8 
 9 // 远程推送通知 注册失败
10 
11 func application(application: UIApplication , didFailToRegisterForRemoteNotificationsWithError error: NSError ) {
12 
13 if error. code == 3010 {
14 
15 println ( "Push notifications are not supported in the iOS Simulator." )
16 
17 } else {
18 
19 println ( "application:didFailToRegisterForRemoteNotificationsWithError: /(error) " )
20 
21 }
22 
23 }
24 
25   // 8.0 之前   收到远程推送通知
26 
27 func application(application: UIApplication , didReceiveRemoteNotification userInfo: [ NSObject : AnyObject ]) {
28 
29 let notif    = userInfo as NSDictionary
30 
31 let apsDic   = notif. objectForKey ( "aps" ) as NSDictionary
32 
33 let alertDic = apsDic. objectForKey ( "alert" ) as String
34 
35 var alertView = UIAlertView (title: " 系统本地通知 " , message: alertDic, delegate: nil , cancelButtonTitle: " 返回 " )
36 
37 alertView. show ()
38 
39 }
40 
41 // 8.0 之后 收到远程推送通知
42 
43 func application(application: UIApplication , didReceiveRemoteNotification userInfo: [ NSObject : AnyObject ], fetchCompletionHandler completionHandler: ( UIBackgroundFetchResult ) -> Void ) {
44 
45 let notif    = userInfo as NSDictionary
46 
47 let apsDic   = notif. objectForKey ( "aps" ) as NSDictionary
48 
49 let alertDic = apsDic. objectForKey ( "alert" ) as String
50 
51 var alertView = UIAlertView (title: " 远程推送通知 " , message: alertDic, delegate: nil , cancelButtonTitle: " 返回 " )
52 
53 alertView. show ()
54 
55 }
56 
57 // 注册通知 alert 、 sound 、 badge ( 8.0 之后,必须要添加下面这段代码,否则注册失败)
58 
59 func application(application: UIApplication , didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings ) {
60 
61 application. registerForRemoteNotifications ()
62 
63 }

 

 
 












 
 
 
 

你可能感兴趣的:(swift)