ios开发——实用技术OC-Swift篇&本地通知与远程通知详解
本地通知与远程通知详解
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运行在后台
上面的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];
}
}
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需要接受来自服务商提供推送消息,
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即可
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);
?>
// 远程推送通知 注册成功
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篇&本地通知与远程通知详解的更多相关文章
- ios开发——实用技术总结Swift篇&swift常用开发技术总结
swift常用开发技术总结 懒加载:属性,数组(字典),控件... 数组(懒加载): lazy var shops:Array<Dictionary<String, String>& ...
- ios开发——实用技术OC-Swift篇&触摸与手势识别
iOS开发学习之触摸事件和手势识别 iOS的输入事件 触摸事件 手势识别 手机摇晃 一.iOS的输入事件 触摸事件(滑动.点击) 运动事件(摇一摇.手机倾斜.行走),不需要人为参与的 远程控制 ...
- iOS开发——实用技术OC篇&单例模式的实实现(ACR&MRC)
单例模式的实实现(ACR&MRC) 在iOS开发中单例模式是一种非常常见的模式,虽然我们自己实现的比较少,但是,系统却提供了不少的到来模式给我们用,比如最常见的UIApplication,No ...
- iOS开发——实用技术OC篇&事件处理详解
事件处理详解 一:事件处理 事件处理常见属性: 事件类型 @property(nonatomic,readonly) UIEventType type; @property(nonatomic ...
- iOS开发——技术精华Swift篇&Swift 2.0和Objective-C2.0混编之第三方框架的使用
swift 语言是苹果公司在2014年的WWDC大会上发布的全新的编程语言.Swift语言继承了C语言以及Objective-C的特性,且克服了C语言的兼容性问题.Swift语言采用安全编程模式,且引 ...
- iOS开发——新特性Swift篇&Swift 2.0 异常处理
Swift 2.0 异常处理 WWDC 2015 宣布了新的 Swift 2.0. 这次重大更新给 Swift 提供了新的异常处理方法.这篇文章会主要围绕这个方面进行讨论. 如何建造异常类型? 在 i ...
- iOS开发 - OC - 实现本地数据存储的几种方式一
iOS常用的存储方式介绍 在iOS App开发过程中经常需要操作一些需要持续性保留的数据,比如用户对于App的相关设置.需要在本地缓存的数据等等.本文针对OC中经常使用的一下存储方式做了个整理. 常用 ...
- iOS开发——网络编程Swift篇&Alamofire详解
Alamofire详解 预览图 Swift Alamofire 简介 Alamofire是 Swift 语言的 HTTP 网络开发工具包,相当于Swift实现AFNetworking版本. 当然,AF ...
- iOS开发——网络编程Swift篇&(八)SwiftyJSON详解
SwiftyJSON详解 最近看了一些网络请求的例子,发现Swift在解析JSON数据时特别别扭,总是要写一大堆的downcast(as?)和可选(Optional),看?号都看花了.随后发现了这个库 ...
随机推荐
- bzoj3996
把这个式子弄清楚就知道这是最小割了 相当于,选某个点i有收入ai,i,会损失ci, 如果i,j都被选则有额外收入ai,j+aj,i 明显,对每个点i,连(s,i,∑ai,j) (i,t,ci) 对每对 ...
- LeetCode Product of Array Except Self (除自身外序列之积)
题意:给一个序列nums,要求返回一个序列ans,两序列元素个数相同,ans第i个元素就是除了nums[i]之外所有的数相乘之积. 思路:时间O(n),额外空间O(0). 第一次扫一遍,处理nums[ ...
- 【Pure】
PureA set of small, responsive CSS modules that you can use in every web project.http://purecss.io/
- Java [Leetcode 43]Multiply Strings
题目描述: Given two numbers represented as strings, return multiplication of the numbers as a string. No ...
- HDU 5313 Bipartite Graph
题意:给一个二分图,问想让二分图变成完全二分图最多能加多少条边. 解法:图染色+dp+bitset优化.设最终的完全二分图两部分点集为A和B,A中点个数为x,B中点个数为y,边数则为x × y,答案即 ...
- HDU 4565 So Easy!
So Easy! Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Su ...
- Linux Vi 删除全部内容,删除某行到结尾,删除某段内容 的方法
1.打开文件 vi filename 2.转到文件结尾 G 或转到第9行 9G 3.删除所有内容(先用G转到文件尾) ,使用: :1,.d 或者删除第9行到第200行的内容(先用200G转到第200行 ...
- uva 11020 Efficient Solutions
题意:给你n个人,有两个属性x.y,如果不存在另外一个人x2,y2满足 x2<=x,y2<y 或者 x2<x,y2<=y,那么就称这个人是有优势的,每次给你一个人得信息,问你当 ...
- Android Activity 生命周期中onStart()和onResume()的区别
首先了解Activity的四种状态 Running状态:一个新的Activity启动入栈后,它在屏幕最前端,处于栈的最顶端,此时它处于可见并可和用户交互的激活状态.Paused状态:当Activity ...
- HW6.14
import java.util.Scanner; public class Solution { public static void main(String[] args) { Scanner i ...