ios推送通知 - CSDN
  • 收到推送 - (void)application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary*)userInfo fetchCompletionHandler:(void(^)(UIBackgroundFetchResultresult))completi

    1.APP后台挂起状态

    2.APP前台运行中

    收到推送

    - (void)application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary*)userInfo fetchCompletionHandler:(void(^)(UIBackgroundFetchResultresult))completionHandlerNS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED;
    - (void)application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary*)userInfoNS_AVAILABLE_IOS(3_0) __TVOS_PROHIBITED;
    

    方法①是ios7新加入的方法,并且如果实现了方法①那么方法②就被覆盖掉不再执行了.
    方法①以有几个特性:当程序在前台运行时,收到远程推送,会立刻调用此方法,但是如果程序在后台挂起,收到消息(未点击推送消息时)并不会执行方法①,如果想在收到消息的时候有需求需要执行一些代码,那么可以让服务器发给APNS时在aps 字典中加入

    aps ={
    content-available = 1;
    }
    

    这个字段,那么当应用在后台挂起时接收到推送消息时就会立即执行方法①,当然,当你再点击推送消息时,还会再执行一次(这两种情况可以根据applicationState这个属性区分),,而方法②只会在点击推送消息,或者应用在前台运行时接收到消息时才会调用。

    需要注意的是:方法②在后台挂起的时候,点击图标进入不会再次执行

    3.APP被杀死状态

    1.点击横幅进入2.点击图标进入:

    -(BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:    (nullableNSDictionary*)launchOptionsNS_AVAILABLE_IOS(3_0);
    

    都会这个方法来启动程序,两者区别在于点击推送消息启动应用会把推送的消息userInfo通过launchOptions参数传递过来

    if(launchOptions) {
    NSDictionary*dicUserInfo = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]; 
      }
    

    可以通过这个参数是否为空来判断程序是否是点击推送消息启动了应用。launchOptions有几个key:

    UIApplicationLaunchOptionsRemoteNotificationKey//返回一个远程推送的userInfo字典类型参数;
    
    UIApplicationLaunchOptionsLocalNotificationKey//返回一个UILocalNotification对象;
    

    Demo地址:https://github.com/yuying2012/WJDStudyLibrary
    这是一个大工程,请从工程中寻找相关模块代码.

    展开全文
  • ——本地推送通知推送通知的作用?在App退到后台或者完全退出时,可以使用通知来告诉用户某件事情,比如推送新的聊天消息、新闻等通知对应的效果: 在主屏幕的顶端会出现通知消息 当手机锁屏时出现在锁屏界面,可以...

    ——本地推送通知

    推送通知的作用?

    在App退到后台或者完全退出时,可以使用通知来告诉用户某件事情,比如推送新的聊天消息、新闻等

    通知对应的效果:

    1. 在主屏幕的顶端会出现通知消息
    2. 当手机锁屏时出现在锁屏界面,可以通过滑动打开该App,
    3. 在通知中心中出现推送的消息
    4. App图标会有微标值① badgeValue
    5. 推送通知提示音

    注意:
    发送通知时,如果程序正在前台允许,那么推送通知UI就不会显示出来;点击通知系统默认会打开该App。

    这里写图片描述 - 这里写图片描述
    这里写图片描述 - 这里写图片描述


    通知的种类:

    • 通知设计模式(NSNotification)
    • 本地通知(UILocalNotification)
    • 远程通知(APNs)

    通知设计模式:
    ——是一种设计模式,是一种设计思想,是抽象的,推送通知(本地和远程)是肉眼可以看到的,是有界面的。

    本地推送通知:
    ——本地通知不需要连接网络,一般是开发人员在合适的情况下在App内发送通知,应用场景:当能够确定在某个时间时需要提醒用户。

    远程通知:
    ——远程通知必须需要连接网络,远程推送服务又称为APNs(Apple Push Notification Services),一般是服务器端发送通知。

    对于用户,通知一般是指的推送通知,即本地推送通知和远程推送通知
    推送通知的代理类是: AppDelegate


    推送通知的使用场景:

    • 一些任务管理App,会在任务时间即将到达时,通知你该做任务了。如:提醒事项App、 电影App:电影即将开始提示用户按时到达影院。
    • 聊天App:程序退出到后台或者完全退出时收到消息
    • 电商App:推荐新品时
    • 新闻App:推送新闻

    知识准备

    • (BOOL)application:(UIApplication )application didFinishLaunchingWithOptions:(NSDictionary )launchOptions :启动选项参数:当程序是通过点击应用程序图标时该参数是nil,当应用程序完全退出时,点击推送通知时该参数不为空,key为UIApplicationLaunchOptionsLocalNotificationKey

    通常当用户点击通知时会做一些业务处理,如QQ在前台状态下会将提醒数字+1, 当应用程序在后台状态或完全退出状态下会打开对应的聊天窗口


    本地通知的基本使用

    #import "ViewController.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    }
    
    // 简单实例:点击通知进入App
    - (IBAction)postLocalNotification:(id)sender {
        UILocalNotification *localNotification = [[UILocalNotification alloc] init];
        localNotification.alertBody = @"hello, 你好啊!- alertBody + fireDate";
        localNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:3]; // 3秒钟后
    
        //--------------------可选属性------------------------------
        if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.2) {
            localNotification.alertTitle = @"推送通知提示标题:alertTitle"; // iOS8.2
        }
    
        // 锁屏时在推送消息的最下方显示设置的提示字符串
        localNotification.alertAction = @"点击查看消息";
    
        // 当点击推送通知消息时,首先显示启动图片,然后再打开App, 默认是直接打开App的
        localNotification.alertLaunchImage = @"LaunchImage.png";
    
        // 默认是没有任何声音的 UILocalNotificationDefaultSoundName:声音类似于震动的声音
        localNotification.soundName = UILocalNotificationDefaultSoundName;
    
        // 传递参数
        localNotification.userInfo = @{@"type": @"1"};
    
        //重复间隔:类似于定时器,每隔一段时间就发送通知
    //  localNotification.repeatInterval = kCFCalendarUnitSecond;
    
        localNotification.category = @"choose"; // 附加操作
    
        // 定时发送
        [[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
        NSInteger applicationIconBadgeNumber =  [[UIApplication sharedApplication] applicationIconBadgeNumber] + 1;
        [[UIApplication sharedApplication] setApplicationIconBadgeNumber:applicationIconBadgeNumber];
    
        // 立即发送
    //    [[UIApplication sharedApplication] presentLocalNotificationNow:localNotification];
    }
    
    // 示例1:简单示例:点击通知进入App
    //- (IBAction)postLocalNotification:(id)sender {
    //    UILocalNotification *localNotification = [[UILocalNotification alloc] init];
    //    localNotification.alertBody = @"hello, 你好啊!- alertBody + fireDate";
    //    localNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:5]; // 5秒钟后
    //    
    //    [[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
    //}
    @end

    #import "AppDelegate.h"
    #import "AppDelegate+PrivateMethod.h"
    
    @interface AppDelegate ()
    
    @end
    
    @implementation AppDelegate
    
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        // Override point for customization after application launch.
    
        if (launchOptions != nil) {
            UILocalNotification *localNotification = launchOptions[UIApplicationLaunchOptionsLocalNotificationKey];
            if (localNotification != nil) {
                // 程序完全退出状态下,点击推送通知后的业务处理
                // 如QQ会打开想对应的聊天窗口
                NSInteger applicationIconBadgeNumber = application.applicationIconBadgeNumber - 1;
                application.applicationIconBadgeNumber = applicationIconBadgeNumber >= 0 ? applicationIconBadgeNumber : 0;
            }
        }
    
        [self registerUserNotificationSettingsForIOS80];
    
        return YES;
    }
    
    
    // 当App在前台状态下,如果有通知会调用该方法
    // 当应用程序在后台状态下,点击推送通知,程序从后台进入前台后,会调用该方法(从锁屏界面点击推送通知从后台进入前台也会执行)
    // 当应用程序完全退出时不调用该方法
    - (void)application:(UIApplication *)application didReceiveLocalNotification:(nonnull UILocalNotification *)notification {
        NSLog(@"%@", notification);
    
        // 处理点击通知后对应的业务
        UIApplicationState applicationState = [[UIApplication sharedApplication] applicationState];
        if (applicationState == UIApplicationStateActive) {     // 前台
            // 例如QQ会增加tabBar上的badgeValue未读数量
        } else if (applicationState == UIApplicationStateInactive) {// 从前台进入后台
            // 例如QQ会打开对应的聊天窗口
            NSInteger applicationIconBadgeNumber = application.applicationIconBadgeNumber - 1;
            application.applicationIconBadgeNumber = applicationIconBadgeNumber >= 0 ? applicationIconBadgeNumber : 0;
        }
    
        [application cancelLocalNotification:notification];
    }
    
    // 监听附加操作按钮
    - (void)application:(UIApplication *)application handleActionWithIdentifier:(nullable NSString *)identifier forLocalNotification:(nonnull UILocalNotification *)notification completionHandler:(nonnull void (^)())completionHandler {
        NSLog(@"identifier:%@", identifier);
        completionHandler();
    }
    
    // 该方法在iOS9.0后调用,iOS9.0之前调用上面那个方法
    - (void)application:(UIApplication *)app handleActionWithIdentifier:(nullable NSString *)identifier forLocalNotification:(nonnull UILocalNotification *)notification withResponseInfo:(nonnull NSDictionary *)responseInfo completionHandler:(nonnull void (^)())completionHandler {
        // ====identifier:no, content:{UIUserNotificationActionResponseTypedTextKey = "not agree";}
        NSLog(@"====identifier:%@, content:%@", identifier, responseInfo);
        completionHandler();
    }
    @end

    #import "AppDelegate.h"
    
    @interface AppDelegate (PrivateMethod)
    
    - (void)registerUserNotificationSettingsForIOS80;
    
    @end
    
    #import "AppDelegate+PrivateMethod.h"
    
    @implementation AppDelegate (PrivateMethod)
    
    - (void)registerUserNotificationSettingsForIOS80 {
        // iOS8.0 适配
        if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)]) {
            // categories: 推送消息的附加操作,可以为nil,此时值显示消息,如果不为空,可以在推送消息的后面增加几个按钮(如同意、不同意)
    
            UIMutableUserNotificationCategory *category = [[UIMutableUserNotificationCategory alloc] init];
            category.identifier = @"choose";
    
            // 同意
            UIMutableUserNotificationAction *action1 = [[UIMutableUserNotificationAction alloc] init];
            action1.identifier = @"yes";
            action1.title = @"同意";
            action1.activationMode = UIUserNotificationActivationModeForeground;  // 点击按钮是否进入前台
            action1.authenticationRequired = true;
            action1.destructive = false;
    
            // 不同意
            UIMutableUserNotificationAction *action2 = [[UIMutableUserNotificationAction alloc] init];
            action2.identifier = @"no";
            action2.title = @"不同意";
            action2.activationMode = UIUserNotificationActivationModeBackground;  // 后台模式,点击了按钮就完了
            action2.authenticationRequired = true;
            action2.destructive = true;
            if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9.0) {
                action2.behavior = UIUserNotificationActionBehaviorTextInput;
                action2.parameters = @{UIUserNotificationTextInputActionButtonTitleKey: @"拒绝原因"};
            }
    
    
            [category setActions:@[action1, action2] forContext:UIUserNotificationActionContextDefault];
    
    
            NSSet<UIUserNotificationCategory *> *categories = [NSSet setWithObjects:category, nil];
    
            UIUserNotificationType types = UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
            UIUserNotificationSettings *notificationSettings = [UIUserNotificationSettings settingsForTypes:types categories:categories];
            [[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];
        }
    }
    @end
    

    运行效果:

    这里写图片描述

    这里写图片描述

    这里写图片描述

    这里写图片描述

    这里写图片描述

    这里写图片描述

    这里写图片描述


    —————远程推送通知—————


    什么是远程推送通知

    • 从远程服务器推送给客户端的通知,需要连接网络
    • 远程推送服务,又称为APNs 苹果推送通知服务(Apple Push Notification services)

    传统推送通知

    传统推送通知是相对于APNs而言的,传统推送通知的原理是:当APP打开时和App的服务器建立一个长连接(需要网络),当需要通知的时候,App服务器通过长连接向对应的客户端发送数据,当客户端接收到数据时使用UILocalNotfication本地通知的方式来展示,这样就实现了传统推送通知。

    传统推送通知必须要联网,如果关闭了App或者打开了App但是无法连接服务器了,这些情况都收不到通知了。

    APNs远程推送通知:只要手机联网了,不管App是打开或者关闭都能接收到苹果服务器推送的通知


    APNs

    • 所有苹果设备在联网状态下都会与苹果服务器建立长连接,连接是双向的,苹果设备可以向苹果服务器发送请求,苹果服务器也可以向苹果设备发送请求。

    苹果服务器常用的通知功能:

    • 时间校准
    • 系统升级
    • 查找我的iPhone

    长连接的好处:更加及时

    远程通知的过程:
    例如微信App:首先每个联网并打开微信的App都与微信服务器有一个长连接,当微信A用户向微信B用户发送一个消息时,微信A用户将消息发送到微信服务器,然后微信服务器判断微信B用户是否和微信服务器建立了长连接,如果有直接通过微信B用户和微信服务器建立的连接管道直接发送即可,这样微信B用户就能收到消息;如果微信B用户此时没有打开微信App,那么微信服务器就将消息发送给苹果服务器,苹果服务器再讲消息发送到某台苹果设备上。苹果是怎么知道该发送给那台设备呢?用户A发送消息时需要将用户B的UDID和微信App的Bundle ID 附带在消息上一块发送给B用户,这些消息微信服务器又发送给苹果服务器,苹果服务器通过UDID就知道发送给那台设备了,然后通过Bundle ID就知道是哪个App发送的了。苹果根据UDID + Bundle ID 生成一个deviceToken, 这样每条微信消息中都加上deviceToken苹果服务器就能识别设备和App了。
    例如 微信A用户发送消息:{“to”:”1234567”, “msg”:”hello”} ——-》微信服务器{“deviceToken”:”RSFWERWR23L342JOI2NLMO2H4”, “to”:”1234567”, “msg”:”hello”} —–》APNs服务器 ——》微信B用户

    deviceToken 在客户端发送之前就请求???

    实现步骤:

    1. 创建真机调试证书并配置推送证书文件:apns_development.cer和描述文件
      1. 首先创建真机证书、AppIDs(要选择Push Notifications), AppIDs创建完后可以看到状态是Configurable,是黄色的圆点,此时还不能使用推送通知,还要继续配置一下,选择Edit–>Push Notifications—> Create Certificate(创建推送通知证书),当证书创建完成后,可以看到AppID中的状态就变成了绿色的圆点(可用状态)
        这里写图片描述
        这里写图片描述
        这里写图片描述
        这里写图片描述
        这里写图片描述
        这里写图片描述
        这里写图片描述
        这里写图片描述
        这里写图片描述
    2. 请求苹果服务器获取deviceToken
    3. 发送deviceToken给App的服务器
    4. 监听用户点击远程推送通知的行为

    当配置App IDs时需要选择Push Notifications,然后Edit,Create Certificate(创建证书),然后闯将证书选择Apple Push Notification servide SSL(Sandbox)

    获取deviceToken:

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        NSDictionary *dictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
    
        // 程序完全退出,点击通知[launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]有值,
        UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, 300, 300)];
        textView.text = dictionary.description;
        [self.window.rootViewController.view addSubview:textView];
        if (dictionary != nil) {
            // 处理程序完全退出时,点击推送通知
        }
    
    
        if ([[[UIDevice currentDevice] systemVersion] floatValue] > 8.0) {
            UIUserNotificationType types = UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIUserNotificationTypeSound;
            UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
            [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
    
            [[UIApplication sharedApplication] registerForRemoteNotifications];
        } else {
            UIRemoteNotificationType types = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
            [[UIApplication sharedApplication] registerForRemoteNotificationTypes:types];
        }
    
    
        return YES;
    }
    
    - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(nonnull NSData *)deviceToken {
        // <37d1dd32 c19a22a0 066cf575 013f968b a89f80b8 2780dd06 be8af24c 521d0c4d>
        NSLog(@"deviceToken: %@", deviceToken);
    }
    
    // 我使用的iOS10.0.3,锁屏和从后台进入前台会调用该方法,在前台调用下面那个方法,程序完全退出时这两个方法都不调用,可以通过判断launchOptions 中的键是否有值来判断,这里使用的是iOS10.0.3,好像不同系统这几种状态调用那个方法不一样???
    - (void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo {
        NSLog(@"从后台进入前台、锁屏界面 这两种情况会调用该方法");
    }
    
    // 前台
    // 该方法需要设置Background Modes --> Remote Notifications
    - (void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo fetchCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler {
    
        NSLog(@"didReceiveRemoteNotification");
        [_window.rootViewController.view addSubview:[[UISwitch alloc] init]];
        completionHandler(UIBackgroundFetchResultNewData);
    }
    
    @end

    第三方PushMeBaby: 用于模拟自己的APP服务器,服务器发送格式:
    {
    “apns”: {
    “alert”: “This is some fancy message.”,
    “badge”: 1,
    “content-available”: “xxx” // 可选,不是必须的
    }
    }

    这里写图片描述
    这里写图片描述

    上面那个代理方法都是用户点击通知以后才会调用,如果想一收到消息(用户还没点击通知)就会调用该方法,需要有3个条件
    1. 设置Background Modes –> Remote Notifications
    2. 在代理方法中调用代码块 completionHandler(UIBackgroundFetchResultNewData);
    3. App服务器发送数据时要增加一个”content-available”字段,值随意写
    满足以上三个条件,当接收到通知时立即会调用代理方法


    极光推送JPush


    上面测试是使用第三放PushMeBaby来模拟自己App对应的服务器,PushMeBaby用于将消息发送给苹果哦服务器,实际开发中可定不能使用这种方式,要么自己搭建自己的推送服务器和苹果服务器进行交换,要么使用其他第三方平台服务,第三方实现的更加方便、更加完善

    远程推送:是指服务器向客户端发送消息。
    即时通讯:是用户向用户发送消息。

    集成步骤

    http://docs.jiguang.cn/jpush/client/iOS/ios_sdk/
    https://community.jiguang.cn/t/jpush-ios-sdk/4247

    展开全文
  • iOS推送通知关闭

    2018-12-27 14:12:40
    - (void)registerRemoteNotification:(UIApplication *)application{      if ([[UIDevice currentDevice].systemVersion floatValue] &gt;= 10.0) ... //iOS10特有  UNUserNotificat...

    - (void)registerRemoteNotification:(UIApplication *)application{

        

        

        if ([[UIDevice currentDevice].systemVersion floatValue] >= 10.0)

        {

            //iOS10特有

            UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];

            // 必须写代理,不然无法监听通知的接收与点击

            center.delegate = self;

            [center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionBadge | UNAuthorizationOptionSound) completionHandler:^(BOOL granted, NSError * _Nullable error) {

                if (granted) {

                    // 点击允许

                    DLog(@"注册成功");

                    [center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {

                        NSLog(@"%@", settings);

                    }];

                } else {

                    // 点击不允许

                    DLog(@"注册失败");

                    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

                       

                        [self performSelectorOnMainThread:@selector(getPushAlert) withObject:nil waitUntilDone:YES];

                    });

     

                    

                    

                }

            }];

        }else if ([[UIDevice currentDevice].systemVersion floatValue] >8.0){

            //iOS8 - iOS10

    //        [application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeSound | UIUserNotificationTypeBadge categories:nil]];

            UIUserNotificationSettings *setting=[[UIApplication  sharedApplication] currentUserNotificationSettings];

            if (UIUserNotificationTypeNone!=setting.types) {

                  DLog(@"注册成功");

            }

            else

            {

                  DLog(@"注册失败");

    这里必须要避开主线程

                dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

                    

                    [self performSelectorOnMainThread:@selector(getPushAlert) withObject:nil waitUntilDone:YES];

                });

              

            }

            

            

        }else if ([[UIDevice currentDevice].systemVersion floatValue] < 8.0) {

    //         UIRemoteNotificationType type = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];

    //         if(UIRemoteNotificationTypeNone != type) {

    //               DLog(@"注册成功");

    //        }else{

    //               DLog(@"注册失败");

    //        }

            

     

        }

        // 注册获得device Token

    //    [[UIApplication sharedApplication] registerForRemoteNotifications];

    }

     

     

    -(void)getPushAlert{

        UIAlertView *alert = [[UIAlertView alloc]

                              initWithTitle:@"温馨提示"

                              message:@"未开启通知,会错过很多重要信息。请到【设置】中开启"

                              delegate:self

                              cancelButtonTitle:nil

                              otherButtonTitles:@"确定", nil];

        

        alert.tag = 111;

        

        [alert show];

    }

    展开全文
  • 转载自:http://www.111cn.net/sj/ios8/90190.htm 通知(Notification)是开发框架中观察者模式的一种实现方式,内部的实现机制由Cocoa框架支持,通常用于试图控制器和数据模型的交互。通过通知,可以向一个...

    转载自:http://www.111cn.net/sj/ios8/90190.htm


    通知(Notification)是开发框架中观察者模式的一种实现方式,内部的实现机制由Cocoa框架支持,通常用于试图控制器和数据模型的交互。通过通知,可以向一个或者多个对象发送消息。

    继承自NSObject,实现了NSCopying Protocol协议。

    通知通过通知中心(NSNotificationCenter)广播给其他对象。通知包含一个名称(name), 对象(object属性), 和一个可选字典(dictionary 属性)三个参数。这些参数协助完成通知操作。

     
    通知的原理                                                  

    Notification一个 对象非常简单,就是poster要提供给observer的信息包裹。Notification 对象有两个重要的成员变量:name和object。一般name用来唯一标示一个通知对象,object都是指向发送者(poster)(为了让observer在接收到notification时可以回调到poster)所以,Notification有两个方法:- (NSString *)name, - (id)object可供调用。同时,Notification对象还包含一个参数,就是字典(可选参数),这个字典中存储一些传值过程中的信息,供接收者使用。系统要求这个参数是不可变字典。

    以上信息构建好后,我们就可以创建一个通知。

    NSNotification *notification = nil;

    notification = [NSNotification notificationWithName: aName object: aObj userInfo: aDictionary];

    其中,aName就是notification对象的名称,aObj 就是发送者,aDictionary是通知的可选字典参数。

    通知创建好后就可以在必要的时候发送通知,发送通知的时候,需要一个控制中心来发送通知,这个控制中心就是通知中心(NSNotificationCenter)。我们也可以通过控制中心创建并发送通知,通常我们也是这么做得。

     

    通知的实际运用                                            

    1. 页面关联性不大,但需要传递信息的地方。这两个页面一个作为发送者,一个作为监听者;

    2. 需要向多个地方发送信息。一个页面作为发送者,多个页面作为监听者。

     
    如何使用通知                                      

    1.注册通知

    2.发送通知

    3.移除通知

     

    代码实现

    建立一个ViewController,修改为MRC。在.m文件里面操作。

    先看注册通知

    - (void)viewDidLoad {
        [super viewDidLoad];
        UIView *mainView = [[[UIView alloc]initWithFrame:[UIScreen mainScreen].bounds]autorelease];
        self.view = mainView;
        
        UIButton *redButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        redButton.frame = CGRectMake(100, 100, 100, 30);
        [redButton setTitle:@"Red" forState:UIControlStateNormal];
        [redButton addTarget:self action:@selector(setRedColor) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:redButton];
        
        UIButton *blueButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        [blueButton setTitle:@"Blue" forState:UIControlStateNormal];
        blueButton.frame = CGRectMake(100, 150, 100, 30);
        [blueButton addTarget:self action:@selector(setBlueColor) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:blueButton];
        /**
         *  注册通知
         */
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(doChange:) name:@"ColorChange" object:nil];
       
    }


    发送通知

    - (void)setBlueColor{
        /**
         *  发送通知
         */
        NSDictionary *dic = [NSDictionary dictionaryWithObject:@"blueColor" forKey:@"color"];
        [[NSNotificationCenter defaultCenter] postNotificationName:@"ColorChange" object:self userInfo:dic];
    }

    - (void)setRedColor{
        /**
         *  发送通知
         */
        NSDictionary *dic = [NSDictionary dictionaryWithObject:@"redColor" forKey:@"color"];
        [[NSNotificationCenter defaultCenter]postNotificationName:@"ColorChange" object:self userInfo:dic];
    }

    - (void)doChange:(NSNotification *)notification{
        NSDictionary *dic = [notification userInfo];
        NSString *colorStr = [dic valueForKey:@"color"];
        UIColor *color = nil;
        
        if ([colorStr isEqualToString:@"blueColor"]) {
            color = [UIColor blueColor];
        }
        if ([colorStr isEqualToString:@"redColor"]) {
            color = [UIColor redColor];
        }
        self.view.backgroundColor = color;
    }


    移除通知

     
    - (void)dealloc{
        /**
         *  移除通知
         */
        [[NSNotificationCenter defaultCenter]removeObserver:self];
        [super dealloc];
    }

    实现效果如下。点击红色屏幕变成红色,点击蓝色,屏幕变成蓝色。




    iOS上简单推送通知(Push Notification)的实现


    1、理解Apple推送通知的机制


    从上面的流程图中,可以看到一个能接收推送通知的App,需要3个东西:

    App ID(唯一标识一个App程序)

    Provisioning Profile(App程序的发布需要它,所以推送通知只能在真机上测试)

    Device Token(设备标识,这个是推送通知功能中特有的)

    而能推送通知的服务器端则要2个东西:

    SSL Certificate

    Private Key

    (由于我对信息加密不清楚,所以这里不解释)

    值得注意的是APNS(ApplePush Notification Service) Server,完成发送Device Token和通知内容的功能,而且这2个动作都是被动的,即第一个动作是由App发起的,第二个则是推送通知的服务器发起的。

    对我而言,理解就这么多了。下面我按照参考文章进行实验。

    2、创建App ID


    点击“New App ID”按钮后,如下


    Description的内容可以任意,Bundle Identifier (App ID Suffix)必须和创建App工程时的Bundle Identifier,如下


    点击“Submit”后,点击左侧导航中的“App IDs”,找到刚才新创建的App ID,如下


    点击“Configure”后,如下


    勾选“Enable for Apple Push Notification service”,然后点击红色的“Configure”按钮,这里暂时只针对Development取得证书。弹出一个对话框,如下


    点击“Continue”后,要我们上传一个CSR文件,如下


    下面使用钥匙串访问(KeychainAccess)应用程序创建上面需要的CSR文件(.certSigningRequest文件)

    3、创建CSR文件

    Keychain Access位于/Applications/Utilities目录中,打开它如下


    然后弹出窗口如下。


    UserEmail Address随意写就可以,Common Name也是一样,注意勾选“Save to disks”,然后点击“Continue”。很快就生成好了所需文件,去找到它。


    回到下面的网页中,上传刚才用KeychainAccess产生的HelloRemoteNotification.certSigningRequest文件。


    很快需要的证书就OK了,如下


    点击“Continue”,然后点击“Done”。


    发现上面的Status是Enabled,而且多了“Download”按钮,点击它,下载了一个名为“aps_development.cer”的文件。双击打开它,


    找到上图中“Keys”栏中名为“HelloRemoteNotification”的private key(注意是private key,而不是public key),右击它,选择“Export “HelloRemoteNotification”…”,这样会导出一个.p12文件(需要输入密码),如下(目前共有3个文件)


    下面开始用刚才产生的.p12文件,创建Profile provision文件

    4、创建ProvisioningProfile文件


    在上图中,点击“New Profile”按钮后,如下


    填写“Profile Name”;勾选“Certificate”;“App ID”选择正确的、之前我们创建的ID,即PushNotification;最后关联需要测试真机设备。点击“Submit”,如下


    可以看到多了一个Provisioning Profile文件,点击“Download”按钮下载它,这时我们一共产生4个文件,如下


    双击“PushNotification.mobileprovision”文件,或把它拖入到Xcode中。


    在Xcode中,找到Code Signing项,如上图,将Debug一项配置成刚才拖入Provisioning Profile对应的iPhone Developer。

    5、Xcode工程中取得Device Token


    在application:didFinishLaunchingWithOptions:方法里,注册使用远程通知。


    添加2个方法,application: didRegisterForRemoteNotificationsWithDeviceToken:和 application:didFailToRegisterForRemoteNotificationsWithError:,用于取得Device Token和打印错误。运行我们建的HelloRemoteNotification工程,如果以上步骤都正确,应该打印出Device Token,如下


    也可能出错如下


    6、创建.pem文件

    将已有的.cer文件转成.pem文件

    将已有的.p12文件转成.pem文件(需要输入密码)

    最后将上面2个.pem文件合并成1个.pem文件(需要输入新密码)


    aps_development.cer->HelloRemoteNotification.pem(下面改名为HelloRemoteNotificationCert.pem)

    HelloRemoteNotification.p12-> HelloRemoteNotificationKey.pem


    HelloRemoteNotification.pem +HelloRemoteNotificationKey.pem合并成ck2.pem

    7、编写PHP服务器代码,发送通知

    <?php

    // Put your device token here (without spaces):
    $deviceToken = '<Xcode控制台输出的Device Token>';

    // Put your private key's passphrase here:
    $passphrase = '<最后输入的密码>';

    // Put your alert message here:
    $message = 'My first push notification!';

    ////////////////////////////////////////////////////////////////////////////////

    $ctx = stream_context_create();
    stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck2.pem');
    stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);

    // Open a connection to the APNS server
    $fp = stream_socket_client(
     'ssl://gateway.sandbox.push.apple.com:2195', $err,
     $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);

    if (!$fp)
     exit("Failed to connect: $err $errstr" . PHP_EOL);

    echo 'Connected to APNS' . PHP_EOL;

    // Create the payload body
    $body['aps'] = array(
     'alert' => $message,
     'sound' => 'default'
     );

    // Encode the payload as JSON
    $payload = json_encode($body);

    // Build the binary notification
    $msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;

    // Send it to the server
    $result = fwrite($fp, $msg, strlen($msg));

    if (!$result)
     echo 'Message not delivered' . PHP_EOL;
    else
     echo 'Message successfully delivered' . PHP_EOL;

    // Close the connection to the server
    fclose($fp);

    注意:修改下面两行代码

    // Put your private key's passphrase here:

    $passphrase = '<最后输入的密码>';

    ......

    ......

    stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck2.pem');

    运行上面的php脚本,如下


    可以看到iPad上面收到的推送通知,如下,表示实践成功!



    展开全文
  • 1 本地通知 iOS80 11 本地通知发送 12 本地通知接收 ... 本地通知 iOS8.0 本地推送通知demo下载链接iOS 本地通知推送 iOS10.0 新API使用总结 1.1. 本地通知发送 ***iOS8.0之后才能用 //本地通知 UILoc

    1. 本地通知 iOS8.0

    本地推送通知demo下载链接

    iOS 本地通知推送 iOS10.0 新API使用总结

    1.1. 本地通知发送

    ***iOS8.0之后才能用
        //本地通知
        UILocalNotification *locationNo = [[UILocalNotification alloc] init];
        //触发时间
        locationNo.fireDate = [NSDate dateWithTimeIntervalSinceNow:10];
        //通知内容
        locationNo.alertBody = @"这是本地通知";
        //iOS8.2之后可见,一般不用
        if (@available(iOS 8.2,*)) {
            locationNo.alertTitle = @"哈哈,本地推送";
        }
        //锁屏(黑屏状态下,"滑动来"后面的字)--iOS10.0之后,没有滑动解锁功能了,这个属性也就不存在了
        locationNo.alertAction = @"查看这个本地推送";
        locationNo.hasAction = YES;
        //通知过来时的声音
        locationNo.soundName = UILocalNotificationDefaultSoundName;
        //应用图标提示--默认是0,没有改变,设置为负数,通知到达时图标提示就会消失
        locationNo.applicationIconBadgeNumber = -1;
    
        //直接设置应用图标提示为0,代表隐藏,和上面效果一致
        [UIApplication sharedApplication].applicationIconBadgeNumber = 0;
    
        //MARK: 额外信息--对于用户不重要,对于开发者很重要,用于接收通知时处理相应逻辑
        locationNo.userInfo = @{@"name":@"周玉",@"job":@"iOS开发工程师"};
    
        //加入到调度池---有可能有多个通知---取决于触发时间
        [[UIApplication sharedApplication] scheduleLocalNotification:locationNo];

    1.2. 本地通知接收

    //#import "AppDelegate.h" 注册通知
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        /*
         UIUserNotificationTypeNone    = 0,      
         UIUserNotificationTypeBadge   徽章标记
         UIUserNotificationTypeSound   声音
         UIUserNotificationTypeAlert   弹出效果
         */
        //注册通知
        //本地通知设置
        UIUserNotificationSettings *setting = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert categories:nil];
        [[UIApplication sharedApplication] registerUserNotificationSettings:setting];
    
        //当程序被杀死的情况下,接收到通知并执行事情--
        UILocalNotification *notification = launchOptions[UIApplicationLaunchOptionsLocalNotificationKey];
        if (notification) {
            NSLog(@"localNo = %@",notification.userInfo);//NSLog不会再打印
            //用测测试是否接收到通知
            UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
            label.backgroundColor = [UIColor redColor];
            [self.window.rootViewController.view addSubview:label];
    
        return YES;
    }
    // 程序没有被杀死时,接收到本地通知时调用--点击通知时会执行这个方法,如果程序被杀死时,这个方法不再走,在application: didFinishLaunchingWithOptions:方法中获取
    - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification{
        NSLog(@"notification.userInfo = %@",notification.userInfo);

    这里写图片描述

    这里写图片描述

    //锁屏(黑屏状态下,”滑动来”后面的字)–iOS10.0之后,没有滑动解锁功能了,这个属性也就不存在了
    locationNo.alertAction = @”查看这个本地推送”;
    locationNo.hasAction = YES;

    这里写图片描述

    这里写图片描述

    2. 本地通知逻辑处理 iOS8.0

    2.1. 发送推送通知

    //  发送通知
    //  ViewController.m
    //  本地推送
    //
    //  Created by zhouyu on 2017/12/27.
    //  Copyright © 2017年 zhouyu. All rights reserved.
    //
    
    #import "ViewController.h"
    #import "RedController.h"
    #import "BlueController.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.title = @"本地推送";
    
        [self setUpUI];
    }
    
    
    - (void)setUpUI{
        UIButton *btn1 = [[UIButton alloc] initWithFrame:CGRectMake(100, 300, 150, 60)];
        [btn1 setTitle:@"跳转红色控制器" forState:UIControlStateNormal];
        [btn1 setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
        [btn1 addTarget:self action:@selector(red) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:btn1];
    
        UIButton *btn2 = [[UIButton alloc] initWithFrame:CGRectMake(100, 400, 150, 60)];
        [btn2 setTitle:@"跳转蓝色控制器" forState:UIControlStateNormal];
        [btn2 setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
        [btn2 addTarget:self action:@selector(blue) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:btn2];
    }
    
    - (void)red{
        [self pushLocationNotificationWithAlertBody:@"跳转红色控制器" userInfo:@{@"key":@"red"}];
    }
    
    - (void)blue{
        [self pushLocationNotificationWithAlertBody:@"跳转蓝色控制器" userInfo:@{@"key":@"blue"}];
    }
    
    - (void)pushLocationNotificationWithAlertBody:(NSString *)body userInfo:(NSDictionary *)userInfo{
        //本地通知
        UILocalNotification *locationNo = [[UILocalNotification alloc] init];
        //触发时间
        locationNo.fireDate = [NSDate dateWithTimeIntervalSinceNow:5];
        //通知内容
        locationNo.alertBody = body;
        //通知过来时的声音
        locationNo.soundName = UILocalNotificationDefaultSoundName;
        //应用图标提示--默认是0,没有改变,设置为负数,通知到达时图标提示就会消失
        locationNo.applicationIconBadgeNumber = -1;
    
        //直接设置应用图标提示为0,代表隐藏,和上面效果一致
        [UIApplication sharedApplication].applicationIconBadgeNumber = 0;
    
        //MARK: 额外信息--对于用户不重要,对于开发者很重要
        locationNo.userInfo = userInfo;
    
        //加入到调度池---有可能有多个通知---取决于触发时间
        [[UIApplication sharedApplication] scheduleLocalNotification:locationNo];
    }
    
    @end

    2.2. AppDelegate接收推送通知进行逻辑处理

    //  接收通知并进行逻辑处理
    //  AppDelegate.m
    //  本地推送
    //
    //  Created by zhouyu on 2017/12/27.
    //  Copyright © 2017年 zhouyu. All rights reserved.
    //
    
    #import "AppDelegate.h"
    #import "ViewController.h"
    #import "RedController.h"
    #import "BlueController.h"
    
    @interface AppDelegate ()
    
    @end
    
    @implementation AppDelegate
    
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
        self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
        self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[[ViewController alloc] init]];
        [self.window makeKeyAndVisible];
        self.window.backgroundColor = [UIColor whiteColor];
    
        /*
         UIUserNotificationTypeNone    = 0,      
         UIUserNotificationTypeBadge   徽章标记
         UIUserNotificationTypeSound   声音
         UIUserNotificationTypeAlert   弹出效果
         */
        //注册通知
        //本地通知设置
        UIUserNotificationSettings *setting = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert categories:nil];
        [[UIApplication sharedApplication] registerUserNotificationSettings:setting];
    
        //当程序被杀死的情况下,如何接收到通知并执行事情--ios10.0之后废弃,需要用10.0之前版本测试
        UILocalNotification *notification = launchOptions[UIApplicationLaunchOptionsLocalNotificationKey];
        if (notification) {
            NSLog(@"localNo = %@",notification.userInfo);//NSLog不会再打印
            UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
            label.backgroundColor = [UIColor redColor];
            [self.window.rootViewController.view addSubview:label];
    
            [self jumpToControllerWithLocationNotification:notification];
        }
    
        return YES;
    }
    
    // 程序没有被杀死时,接收到本地通知时调用--点击通知时会执行这个方法,如果程序被杀死时,这个方法不再走,在application: didFinishLaunchingWithOptions:方法中获取
    - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification{
        NSLog(@"notification.userInfo = %@",notification.userInfo);
        [self jumpToControllerWithLocationNotification:notification];
    }
    
    - (void)jumpToControllerWithLocationNotification:(UILocalNotification *)localNo{
    
        //如果APP在前台,就不用走通知的方法了
        if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
            return;
        }
    
        //获取userInfo
        NSDictionary *userInfo = localNo.userInfo;
        UINavigationController *nav = (UINavigationController *)self.window.rootViewController;
        //判断跳转
        if ([userInfo[@"key"] isEqualToString:@"red"]) {
            [nav pushViewController:[[RedController alloc] init] animated:YES];
        } else if([userInfo[@"key"] isEqualToString:@"blue"]) {
            [nav pushViewController:[[BlueController alloc] init] animated:YES];
        }
    
    }
    
    @end
    

    //如果APP在前台,就不用走通知的方法了
    if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
    return;
    }

    这里写图片描述

    这里写图片描述

    这里写图片描述

    展开全文
  • 需求ios developer文件(自行获取解决) aps_development.cer 推送证书 aps_development.p12 钥匙串导出的p12文件 ios_development.cer 开发者证书 CSRequest.certSigningRequest 从请求机构请求...
  • ios如何实现推送通知

    2012-04-05 14:34:54
    推送通知的步骤:1、询问是否允许推送通知。2、如果用户允许在APPDELEGATE 中实现 - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{ ...
  • ios推送通知

    2018-05-21 16:09:36
    具体流程如下:在Launchpad中找到我们钥匙串,在钥匙串中,打开Keychain Access &gt; Certificate Assistant &gt; Request a Certificate From a Certificate Authority… 菜单,如下图所示: 在弹出的...
  • iOS 推送通知

    2013-08-27 12:37:17
    本文将带领开发者一步一步向着iOS推送通知的深处探寻,掌握如何配置iOS推送通知的奥义。 介绍一点点背景资料 众所周知,使用推送通知是一个很棒的、给应用添加实时消息通知的方式。这样做的结局是,开发者和用户...
  • iOS APP需要推送通知,要用到iOS推送证书,分为测试调试用的iOS推送证书(开发环境)和上架到App Store的ios 推送证书!(生产环境) APP要推送通知首先要在创建APPID时勾选推送服务。 推送证书是配置上传到推...
  • 1. 推送通知 注意:这里说的推送通知跟NSNotification有所区别 ... iOS中提供了2种推送通知 本地推送通知(Local Notification) 远程推送通知(Remote Notification) 2. 推送通知的作用 可以让不在前
  • 推送通知,也被叫做远程通知,是在iOS 3.0以后被引入的功能。是当程序没有启动或不在前台运行时,告诉用户有新消息的一种途径,是从外部服务器发送到应用程序上的。一般说来,当要显示消息或下载数据的时候,通知是...
  • iOS推送通知实现

    2013-01-09 13:51:42
    iOS推送想必大家都很熟悉,在App没有在运行有新消息时顶部状态栏会出现提示信息,锁屏状态下会出现消息提示框,在App图标上也会有红色的角标。 当然这些提示方式用户是可以在设置中心定制的。 下面我就结合网上...
  • 摘要:这是一篇编译的文章...本文将带领开发者一步一步向着iOS推送通知的深处探寻,掌握如何配置iOS推送通知的奥义。 介绍一点点背景资... 这是一篇编译的文章,内容均出自Parse.com的iOS开发教程,同时作者还提供了
  • iOS 推送通知详解

    2013-04-23 11:25:02
    本文将带领开发者一步一步向着iOS推送通知的深处探寻,掌握如何配置iOS推送通知的奥义。 介绍一点点背景资料 众所周知,使用推送通知是一个很棒的、给应用添加实时消息通知的方式。这样做的结局是,开发者和...
  • 与直接打开app相比,用户更倾向于通过通知直接进入app丰富多彩的功能,所以不管是安卓用户还是iOS用户,推送通知已经成为用户与自己手机之间进行互动的主要方式之一。那么,锁屏时候的通知栏就理所当然成了争夺用户...
  • iOS 推送,删除指定推送消息 远程推送经常会出现收到重复推送的问题,或者想删除某条推送消息的问题,本文将详细说明 静默推送iOS10 之后 Apple 新增了静默推送的功能,使 App 可以在收到推送之后执行一段...
  • iOS推送证书是用于推送 通知功能配置,需要配置到入极光推送、个推等推送平台。 iOS推送证书不能直接用于打包ipa,且推送证书只有p12,无关联描述文件。 iOS推送证书分为开发环境及生成环境,看下面具体申请步骤...
1 2 3 4 5 ... 20
收藏数 20,882
精华内容 8,352
热门标签
关键字:

ios推送通知