本地通知与远程通知详解

一:本地通知
 
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:立即发送通知到本机

栗子:

 - (void)showNotificationWithAction:(NSString *)action andContent:(NSString *)content
 {
   UILocalNotification *notification = [[UILocalNotification alloc] init];
   notification.alertBody = content;
   notification.alertAction = action;
   notification.soundName = UILocalNotificationDefaultSoundName;
   [[UIApplication sharedApplication] presentLocalNotificationNow:notification];
 }

 - (void)scheduleNotificationWithItem:(ToDoItem *)item interval:(int)minutesBefore {
   NSCalendar *calendar = [NSCalendar autoupdatingCurrentCalendar];
   NSDateComponents *dateComps = [[NSDateComponents alloc] init];
   [dateComps setDay:item.day];
   [dateComps setMonth:item.month];
   [dateComps setYear:item.year];
   [dateComps setHour:item.hour];
   [dateComps setMinute:item.minute];
   NSDate *itemDate = [calendar dateFromComponents:dateComps];

   UILocalNotification *localNotif = [[UILocalNotification alloc] init];
   if (localNotif == nil)
     return;
   localNotif.fireDate = [itemDate dateByAddingTimeIntervalInterval:-(minutesBefore*)];
   localNotif.timeZone = [NSTimeZone defaultTimeZone];

   localNotif.alertBody = [NSString stringWithFormat:NSLocalizedString(@"%@ in %i minutes.", nil),
      item.eventName, minutesBefore];
   localNotif.alertAction = NSLocalizedString(@"View Details", nil);

   localNotif.soundName = UILocalNotificationDefaultSoundName;
   localNotif.applicationIconBadgeNumber = ;

   NSDictionary *infoDict = [NSDictionary dictionaryWithObject:item.eventName forKey:ToDoItemKey];
   localNotif.userInfo = infoDict;

   [[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
 }

处理Local Notification
在处理本地通知时,我们需要考虑三种情况:
1. App没有启动,
这种情况下,当点击通知时,会启动App,而在App中,开发人员可以通过实现*AppDelegate中的方法:-
(BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary
*)launchOptions,然后从lauchOptions中获取App启动的原因,若是因为本地通知,则可以App启动时对App做对应的操作,
比方说跳转到某个画面等等。栗子:

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
 {
   NSLog(@"Start App....");
   ....
   UILocalNotification *localNotification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
   if ([self isWelcomeNotification:localNotification]) {
     NSLog(@"start with welcome notification");
     [self.mainViewController showOfficeIntroduction];
   }
   return YES;
 }

2. App运行在后台

3. App运行在前台
上面的2种情况的处理基本一致,
不同点只有当运行再后台的时候,会有弹窗提示用户另外一个App有通知,对于本地通知单的处理都是通过*AppDelegate的方法:-
(void)application:(UIApplication *)application
didReceiveLocalNotification:(UILocalNotification *)notification来处理的。 栗子:

 - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
 {
     if ([self isWelcomeNotification:notification]) {
        [self.mainViewController showOfficeIntroduction];
     }if ([self isCustomerDataNotification:notification]) {
         [self.mainViewController showCustomerDataIntroduction];
     }
 }
Swift

  if ( UIApplication . instancesRespondToSelector ( Selector ( "registerUserNotificationSettings:" ))) {

 application. registerUserNotificationSettings ( UIUserNotificationSettings (forTypes:  UIUserNotificationType .Sound |  UIUserNotificationType .Alert |  UIUserNotificationType .Badge, categories:  nil ))

 } else {

 application. registerForRemoteNotificationTypes (.Alert | .Sound | .Badge)

 }

 然后,在Appdelegate.swift 写相关远程推送、本地通知等代码

 // 收到本地通知

 func application(application: UIApplication , didReceiveLocalNotification notification: UILocalNotification ) {

 var alertView = UIAlertView (title: " 系统本地通知 " , message: notification. alertBody , delegate: nil , cancelButtonTitle: " 返回 " )

 alertView. show ()

 }

本地通知方法:

  ****************************** 本地通知方法 ********** ***** ***************  

 //

 //  TimeViewController.swift

 //  UIControlDemo

 //

 //  Created by  on 14/12/10.

 //  Copyright (c) 2014 年 马大哈 . All rights reserved.

 //

 import UIKit

 class TimeViewController: BaseViewController {

 var wordTextField: UITextField ? // 文字

 var dateTextField: UITextField ? // 时间

 var datePicker: UIDatePicker ?

 override func viewDidLoad() {

 super . viewDidLoad ()

          self . title = " 时间 / 日期 / 本地通知 "         

 let leftBarButton: UIBarButtonItem = UIBarButtonItem (barButtonSystemItem: . Trash , target: self , action: "locaNotifcationDeleteAll" )

 self . navigationItem . rightBarButtonItem = leftBarButton;

 wordTextField = UITextField (frame: CGRectMake (  ,  ,  ,  ))

 wordTextField ?. backgroundColor = . clearColor ()

 wordTextField !. tag = 

 wordTextField ?. borderStyle = UITextBorderStyle . RoundedRect

 wordTextField ?. keyboardType = UIKeyboardType . Default

 wordTextField ?. returnKeyType = UIReturnKeyType . Done

 wordTextField ?. contentVerticalAlignment = UIControlContentVerticalAlignment . Center

 wordTextField ?. clearButtonMode = UITextFieldViewMode . WhileEditing

 wordTextField ?. secureTextEntry = false

 wordTextField ?. textColor = . blackColor ()

 wordTextField ?. textAlignment = . Left

 wordTextField ?. placeholder = " 键盘 "

 wordTextField ?. font = UIFont . systemFontOfSize (  )

 self . view . addSubview ( wordTextField !)

 dateTextField = UITextField (frame: CGRectMake (  ,  ,  ,  ))

 dateTextField ?. backgroundColor = . clearColor ()

 dateTextField !. tag = 

 dateTextField ?. borderStyle = UITextBorderStyle . RoundedRect

 dateTextField ?. keyboardType = UIKeyboardType . Default

 dateTextField ?. returnKeyType = UIReturnKeyType . Done

 dateTextField ?. contentVerticalAlignment = UIControlContentVerticalAlignment . Center

 dateTextField ?. textColor = . blackColor ()

 dateTextField ?. textAlignment = . Left

 dateTextField ?. placeholder = " 日期 picker"

 dateTextField ?. font = UIFont . systemFontOfSize (  )

 self . view . addSubview ( dateTextField !)

 datePicker = UIDatePicker ()

 datePicker ?. datePickerMode = . DateAndTime

 datePicker ?. timeZone = NSTimeZone . systemTimeZone ()

 datePicker ?. addTarget ( self , action: "datePickerSelected:" , forControlEvents: UIControlEvents .ValueChanged)

 dateTextField !. inputView = datePicker

 var button = UIButton . buttonWithType ( UIButtonType . Custom ) as UIButton

 button. frame = CGRectMake (  ,  ,  ,  )

 button. backgroundColor = UIColor . redColor ()

 button. setTitleColor ( UIColor . blackColor (), forState:.Normal)

 button. setTitle ( " 保存 " , forState: UIControlState .Normal)

 button. titleLabel !. font = UIFont . boldSystemFontOfSize ( CGFloat (  ))

 button. showsTouchWhenHighlighted = true

 button. addTarget ( self , action: "saveLocalNotificationButton" , forControlEvents: UIControlEvents .TouchUpInside)

 self . view . addSubview (button)

 }

 // 保存按钮方法

 func saveLocalNotificationButton(){

 var contentDic = [ "KEY" : "VALUE" ]

 locaNotifcationSchedule (chedulDate: datePicker !. date , alertBody: " 通知看到 : /( wordTextField !. text ) " , content: contentDic)

 var alertView = UIAlertView (title: " 保存成功 " , message: nil , delegate: nil , cancelButtonTitle: " 返回 " )

 alertView. show ()

 wordTextField ?. resignFirstResponder ()

 dateTextField ?. resignFirstResponder ()

 }

 // 注册本地通知

 func locaNotifcationSchedule(#chedulDate: NSDate ,alertBody: String ,content: NSDictionary ) {

 var localNotif = UILocalNotification ()

 localNotif. fireDate = chedulDate

 localNotif. timeZone = NSTimeZone . defaultTimeZone ()

 //        localNotif.repeatInterval = repeatInterval 0 代表不重复

 localNotif. soundName =  "iPhone.caf" // 此属性可以不写(默认系统声音 UILocalNotificationDefaultSoundName )

 //        localNotif.hasAction = true;

 //        localNotif.alertAction = " 查看 ";

 localNotif. alertBody = alertBody

 localNotif. userInfo   = content

 UIApplication . sharedApplication (). scheduleLocalNotification (localNotif)  

 }

 // 删除所有注册的本地通知

 func locaNotifcationDeleteAll() {

 let application = UIApplication . sharedApplication ()

 application. cancelAllLocalNotifications ()

 var alertView = UIAlertView (title: " 所有本地通知都已移除 " , message: nil , delegate: nil , cancelButtonTitle: " 返回 " )

 alertView. show ()

 }

 // 动态改变 textfield 内容

 func datePickerSelected(datePicker: UIDatePicker ){

 let dateString = timeDateFormatter (). stringFromDate (datePicker. date )

 dateTextField !. text = dateString

 }

 override func touchesEnded(touches: NSSet , withEvent event: UIEvent ) {

 wordTextField ?. resignFirstResponder ()

 dateTextField ?. resignFirstResponder ()

 }

 override func didReceiveMemoryWarning() {

 super . didReceiveMemoryWarning ()

 }

 }
 
 
二:远程通知
 

首先是申请证书的网址

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  [[UIApplication sharedApplication ] setApplicationIconBadgeNumber:];  

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

 @"{

        //自定义参数

        "userinfo":

               {

                  "name":"remote notice"

               },

        //标准写法

        "aps":

               {

                  "alert":

                            {

                               "action-loc-key":"Open",//支持多语言

                               "body":"messgae content"//消息正文

                            },

                  ,//为App 的icon  标记 具体数值

                  "sound":"default" //播放的音频文件,default 表示系统默认的选择列铃声

              } 

      }";

到这里就差不多结束了.

php服务器推送消息

      <?php  

     $deviceToken = '38c866dd bb323b39 ffa73487 5e157ee5 a85e0b7ce90d56e9 fe145bcc 6c2c594b'; // masked for security reason
     // Passphrase for the private key (ck.pem file)
     // $pass = '';
     // Get the parameters from http get or from command line
     $message = $_GET[] or $message = 'Message received from javacom';
     $badge = (];
     $sound = $_GET[];
     // Construct the notification payload
     $body = array();
     $body['aps'] = array('alert' => $message);
     if ($badge)
     $body['aps']['badge'] = $badge;
     if ($sound)
     $body['aps']['sound'] = $sound;  

     $ctx = stream_context_create();
     stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');
     // assume the private key passphase was removed.
     // stream_context_set_option($ctx, 'ssl', 'passphrase', $pass);
     $fp = stream_socket_client(, STREAM_CLIENT_CONNECT, $ctx);
     if (!$fp) {
     print "Failed to connect $err $errstrn";
     return;
     }
     else {
     print "Connection OKn";
     }
     $payload = json_encode($body);
     $msg = chr() . pack() . pack('H*', str_replace(' ', '', $deviceToken)) . pack("n",strlen($payload)) . $payload;
     print "sending message :" . $payload . "n";
     fwrite($fp, $msg);
     fclose($fp);
     ?>
 
Swift
 

      // 远程推送通知 注册成功

 func application(application: UIApplication , didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData ) {

 println (deviceToken. description )

 }

 // 远程推送通知 注册失败

 func application(application: UIApplication , didFailToRegisterForRemoteNotificationsWithError error: NSError ) {

  {

 println ( "Push notifications are not supported in the iOS Simulator." )

 } else {

 println ( "application:didFailToRegisterForRemoteNotificationsWithError: /(error) " )

 }

 }

   // 8.0 之前   收到远程推送通知

 func application(application: UIApplication , didReceiveRemoteNotification userInfo: [ NSObject : AnyObject ]) {

 let notif    = userInfo as NSDictionary

 let apsDic   = notif. objectForKey ( "aps" ) as NSDictionary

 let alertDic = apsDic. objectForKey ( "alert" ) as String

 var alertView = UIAlertView (title: " 系统本地通知 " , message: alertDic, delegate: nil , cancelButtonTitle: " 返回 " )

 alertView. show ()

 }

 // 8.0 之后 收到远程推送通知

 func application(application: UIApplication , didReceiveRemoteNotification userInfo: [ NSObject : AnyObject ], fetchCompletionHandler completionHandler: ( UIBackgroundFetchResult ) -> Void ) {

 let notif    = userInfo as NSDictionary

 let apsDic   = notif. objectForKey ( "aps" ) as NSDictionary

 let alertDic = apsDic. objectForKey ( "alert" ) as String

 var alertView = UIAlertView (title: " 远程推送通知 " , message: alertDic, delegate: nil , cancelButtonTitle: " 返回 " )

 alertView. show ()

 }

 // 注册通知 alert 、 sound 、 badge ( 8.0 之后,必须要添加下面这段代码,否则注册失败)

 func application(application: UIApplication , didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings ) {

 application. registerForRemoteNotifications ()

 }
 
 


 
 
 
 

ios开发——实用技术OC-Swift篇&本地通知与远程通知详解的更多相关文章

  1. ios开发——实用技术总结Swift篇&amp;swift常用开发技术总结

    swift常用开发技术总结 懒加载:属性,数组(字典),控件... 数组(懒加载): lazy var shops:Array<Dictionary<String, String>& ...

  2. ios开发——实用技术OC-Swift篇&amp;触摸与手势识别

    iOS开发学习之触摸事件和手势识别   iOS的输入事件 触摸事件 手势识别 手机摇晃 一.iOS的输入事件   触摸事件(滑动.点击) 运动事件(摇一摇.手机倾斜.行走),不需要人为参与的 远程控制 ...

  3. iOS开发——实用技术OC篇&amp;单例模式的实实现(ACR&amp;MRC)

    单例模式的实实现(ACR&MRC) 在iOS开发中单例模式是一种非常常见的模式,虽然我们自己实现的比较少,但是,系统却提供了不少的到来模式给我们用,比如最常见的UIApplication,No ...

  4. iOS开发——实用技术OC篇&amp;事件处理详解

    事件处理详解 一:事件处理 事件处理常见属性: 事件类型 @property(nonatomic,readonly) UIEventType     type; @property(nonatomic ...

  5. iOS开发——技术精华Swift篇&amp;Swift 2.0和Objective-C2.0混编之第三方框架的使用

    swift 语言是苹果公司在2014年的WWDC大会上发布的全新的编程语言.Swift语言继承了C语言以及Objective-C的特性,且克服了C语言的兼容性问题.Swift语言采用安全编程模式,且引 ...

  6. iOS开发——新特性Swift篇&amp;Swift 2.0 异常处理

    Swift 2.0 异常处理 WWDC 2015 宣布了新的 Swift 2.0. 这次重大更新给 Swift 提供了新的异常处理方法.这篇文章会主要围绕这个方面进行讨论. 如何建造异常类型? 在 i ...

  7. iOS开发 - OC - 实现本地数据存储的几种方式一

    iOS常用的存储方式介绍 在iOS App开发过程中经常需要操作一些需要持续性保留的数据,比如用户对于App的相关设置.需要在本地缓存的数据等等.本文针对OC中经常使用的一下存储方式做了个整理. 常用 ...

  8. iOS开发——网络编程Swift篇&amp;Alamofire详解

    Alamofire详解 预览图 Swift Alamofire 简介 Alamofire是 Swift 语言的 HTTP 网络开发工具包,相当于Swift实现AFNetworking版本. 当然,AF ...

  9. iOS开发——网络编程Swift篇&amp;(八)SwiftyJSON详解

    SwiftyJSON详解 最近看了一些网络请求的例子,发现Swift在解析JSON数据时特别别扭,总是要写一大堆的downcast(as?)和可选(Optional),看?号都看花了.随后发现了这个库 ...

随机推荐

  1. Linux系统下配置环境变量

    一.环境变量文件介绍 转自:http://blog.csdn.net/cscmaker/article/details/7261921 Linux中环境变量包括系统级和用户级,系统级的环境变量是每个登 ...

  2. android:layout_weight的真实含义(转)

    首先声明只有在Linearlayout中,该属性才有效.之所以Android:layout_weight会引起争议,是因为在设置该属性的同时,设置android:layout_width为wrap_c ...

  3. Alignment ( 最长上升(下降)子序列 )

    Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 11397   Accepted: 3630 Description In t ...

  4. poj 3608 旋转卡壳求不相交凸包最近距离;

    题目链接:http://poj.org/problem?id=3608 #include<cstdio> #include<cstring> #include<cmath ...

  5. Difference Between Mod_Python & Mod_Wsgi | eHow

    Difference Between Mod_Python & Mod_Wsgi | eHow     x    YES    NO    Why not?     Thanks for he ...

  6. numpy创建array【老鱼学numpy】

    在上一篇文章中,我们已经看到了如何通过numpy创建numpy中的数组,这里再重复一下: import numpy as np # 数组 a = [[1, 2, 3], [4, 5, 6]] prin ...

  7. np.random.random()函数 参数用法以及numpy.random系列函数大全

    原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/9751471.html 1.np.random.random()函数参数 np.random.r ...

  8. LayIM.AspNetCore Middleware 开发日记(七)Asp.Net.Core.SignalR闪亮登场

    前言   前几篇介绍了整个中间件的构成,路由,基本配置等等.基本上没有涉及到通讯部分.不过已经实现了融云的通讯功能,由于是第三方的就不在单独去写.正好.NET Core SignalR已经出来好久了, ...

  9. python多进程详解和协程

    1.由于python多线程适合于多IO操作,但不适合于cpu计算型工作,这时候可以通过多进程实现.python多进程简单实用 # 多进程,可以cpu保持一致,python多线程适合多io.对于高cpu ...

  10. 浅谈CSRF攻击方式(转)

    引自:http://www.cnblogs.com/hyddd/一.CSRF是什么? CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one cli ...