iOS自定義推送消息提示框
看到標(biāo)題你可能會(huì)覺(jué)得奇怪 推送消息提示框不是系統(tǒng)自己彈出來(lái)的嗎? 為什么還要自己自定義呢?
因?yàn)轫?xiàng)目需求是這樣的:最近需要做 遠(yuǎn)程推送通知 和一個(gè)客服系統(tǒng) 包括店鋪客服和官方客服兩個(gè)模塊 如果有新的消息推送的時(shí)候 如果用戶(hù)當(dāng)前不在客服界面的時(shí)候 要求無(wú)論是在app前臺(tái) 還是app退到后臺(tái) 頂部都要彈出系統(tǒng)的那種消息提示框
這樣的需求 我們就只能自定義一個(gè)在app內(nèi) 彈出消息提示框
實(shí)現(xiàn)步驟如下:
1.我們自定義一個(gè)view 為 STPushView 推送消息的提示框view
#import <UIKit/UIKit.h> #import "STPushModel.h" @interface STPushView : UIView /** *推送數(shù)據(jù)模型 */ @property(nonatomic,strong) STPushModel *model; +(instancetype)shareInstance; + (void)show; + (void)hide; @end
#import "STPushView.h" #import "AppDelegate.h" @interface STPushView() @property (nonatomic, weak) UIImageView *imageV; @property (nonatomic,weak ) UILabel *timLabel; @property (nonatomic,weak ) UILabel *content; @end @implementation STPushView static STPushView *_instance = nil; +(instancetype)shareInstance { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _instance = [[STPushView alloc] init]; }); return _instance; } +(instancetype) allocWithZone:(struct _NSZone *)zone { if (!_instance) { _instance = [super allocWithZone:zone]; } return _instance ; } - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { self.backgroundColor = CUSTOMCOLOR(15, 14, 12); CGFloat margin = 12; UIImageView *imageV = [[UIImageView alloc] init]; imageV.userInteractionEnabled = NO; imageV.image = [UIImage imageNamed:@"logo"]; imageV.layer.cornerRadius = 5; [self addSubview:imageV]; self.imageV = imageV; [imageV mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(self).offset(margin); make.centerY.equalTo(self.mas_centerY); make.width.mas_equalTo(30); make.height.mas_equalTo(30); }]; UILabel *titleLabel = [[UILabel alloc] init]; titleLabel.textColor = [UIColor whiteColor]; titleLabel.font = [UIFont boldSystemFontOfSize:12]; titleLabel.text = @"121店官方客服"; [self addSubview:titleLabel]; [titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(imageV.mas_right).offset(margin); make.top.equalTo(self.mas_top).offset(margin); make.height.mas_equalTo(16); }]; [titleLabel sizeToFit]; UILabel *timLabel = [[UILabel alloc] init]; timLabel.font = [UIFont systemFontOfSize:12]; timLabel.userInteractionEnabled = NO; timLabel.textColor = [UIColor whiteColor]; timLabel.text = @"剛剛"; timLabel.textColor = [UIColor lightGrayColor]; [self addSubview:timLabel]; self.timLabel = timLabel; [timLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(titleLabel.mas_right).offset(margin); make.top.equalTo(self.mas_top).offset(margin); make.width.mas_lessThanOrEqualTo(40); make.height.mas_equalTo(16); }]; UILabel *content = [[UILabel alloc] init]; content.numberOfLines = 2; content.font = [UIFont systemFontOfSize:13]; content.textColor = [UIColor whiteColor]; content.userInteractionEnabled = NO; [self addSubview:content]; self.content = content; [content mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(imageV.mas_right).offset(margin); make.top.equalTo(titleLabel.mas_bottom).offset(-3); make.right.equalTo(self.mas_right).offset(-margin); make.height.mas_equalTo(35); }]; UIView *toolbar = [[UIView alloc] init]; toolbar.backgroundColor = CUSTOMCOLOR(121, 101, 81); toolbar.layer.cornerRadius = 3; [self addSubview:toolbar]; [toolbar mas_makeConstraints:^(MASConstraintMaker *make) { make.width.mas_equalTo(35); make.height.mas_equalTo(6); make.centerX.equalTo(self.mas_centerX); make.bottom.equalTo(self.mas_bottom).offset(-2); }]; } return self; } - (void)setModel:(STPushModel *)model { _model = model; self.timLabel.text = @"剛剛"; self.content.text = model.content; } + (void)show { [UIApplication sharedApplication].statusBarHidden = YES; STPushView *pushView = [STPushView shareInstance]; pushView.hidden = NO; AppDelegate *app = (AppDelegate*)[UIApplication sharedApplication].delegate; [app.window bringSubviewToFront:pushView]; [UIView animateWithDuration:0.25 animations:^{ pushView.frame = CGRectMake(0, 0, SCREEN_WIDTH, pushViewHeight); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [UIView animateWithDuration:0.25 animations:^{ pushView.frame = CGRectMake(0, -pushViewHeight, SCREEN_WIDTH, pushViewHeight); } completion:^(BOOL finished) { [UIApplication sharedApplication].statusBarHidden = NO; pushView.hidden = YES; }]; }); }]; } + (void)hide { STPushView *pushView = [STPushView shareInstance]; [UIView animateWithDuration:0.25 animations:^{ pushView.frame = CGRectMake(0, -pushViewHeight, SCREEN_WIDTH, pushViewHeight); } completion:^(BOOL finished) { [UIApplication sharedApplication].statusBarHidden = NO; pushView.hidden = YES; }]; } @end
上面pushView需要一個(gè)模型 實(shí)現(xiàn)代碼如下
// push 推送的model 推送過(guò)來(lái)的數(shù)據(jù)如下: /** content = dsfdsnfds; id = 5077; mid = 1270339; title = dsfdsnfds; url = "3?_from=push"; urlType = 3; **/ #import <Foundation/Foundation.h> @interface STPushModel : STBaseModel<NSCoding> //STBaseModel 是一個(gè)繼承自NSObject的類(lèi) 我主要是在這個(gè)類(lèi)中實(shí)現(xiàn)了字典轉(zhuǎn)模型的功能 你可以直接修改為NSObject /***id**/ @property (copy,nonatomic) NSString* recordId; /***標(biāo)題**/ @property (copy, nonatomic) NSString *title; /***url**/ @property (copy, nonatomic) NSString *url; /***url 類(lèi)型**/ @property (copy, nonatomic) NSString* urlType; /***圖標(biāo)的高度**/ @property (assign,nonatomic) NSString * mid; /***推送內(nèi)容**/ @property (copy, nonatomic) NSString* content; @end
因?yàn)樯婕暗胶脦讉€(gè)頁(yè)面需要使用同樣的推送消息數(shù)據(jù) 進(jìn)行判斷而處理相應(yīng)的業(yè)務(wù) 所有我對(duì)此模型做了歸檔處理
#import "STPushModel.h" @implementation STPushModel /** * 保存對(duì)象到文件中 * * @param aCoder <#aCoder description#> */ -(void)encodeWithCoder:(NSCoder *)aCoder { [aCoder encodeObject:self.recordId forKey:@"recordId"]; [aCoder encodeObject:self.title forKey:@"title"]; [aCoder encodeObject:self.url forKey:@"url"]; [aCoder encodeObject:self.urlType forKey:@"urlType"]; [aCoder encodeObject:self.mid forKey:@"mid"]; [aCoder encodeObject:self.content forKey:@"content"]; } /** * 從文件中讀取對(duì)象 * * @param aDecoder <#aDecoder description#> * * @return <#return value description#> */ -(id)initWithCoder:(NSCoder *)aDecoder { //注意:在構(gòu)造方法中需要先初始化父類(lèi)的方法 if (self=[super init]) { self.recordId=[aDecoder decodeObjectForKey:@"recordId"]; self.title=[aDecoder decodeObjectForKey:@"title"]; self.url=[aDecoder decodeObjectForKey:@"url"]; self.urlType=[aDecoder decodeObjectForKey:@"urlType"]; self.mid=[aDecoder decodeObjectForKey:@"mid"]; self.content= [aDecoder decodeObjectForKey:@"content"]; } return self; } @end
做好了上面的準(zhǔn)備工作之后 接下來(lái)我們就需要 APPdelegate里面注冊(cè)遠(yuǎn)程推送通知 并且監(jiān)聽(tīng)推送消息
這里以個(gè)推為例子:
第一步在下面的方法中 實(shí)現(xiàn)個(gè)推的注冊(cè)方法
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // 注冊(cè)個(gè)推推送服務(wù) [[GeTuiApilmpl sharedInstance] geTuiRegister]; }
GeTuiApilmpl 是一個(gè)單例類(lèi) 專(zhuān)門(mén)用于注冊(cè)個(gè)推的推送方法 實(shí)現(xiàn)代碼如下:
#import <Foundation/Foundation.h> #import "GeTuiSdk.h" @interface GeTuiApilmpl : NSObject <GeTuiSdkDelegate> + (GeTuiApilmpl *) sharedInstance; - (void) geTuiRegister; @end
#import "GeTuiApilmpl.h" @implementation GeTuiApilmpl + (GeTuiApilmpl *) sharedInstance{ static id instance = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ instance = [[self alloc] init]; }); return instance; } - (id)init { self = [super init]; if (self) { NSString *path = [[NSBundle mainBundle] pathForResource:@"libGexin" ofType:@"plist"]; NSDictionary *dic = [NSDictionary dictionaryWithContentsOfFile:path]; [GeTuiSdk startSdkWithAppId:[dic objectForKey:@"GT_APPID"] appKey:[dic objectForKey:@"GT_APPKEY"] appSecret:[dic objectForKey:@"GT_APPSECRET"] delegate:self]; } return self; } #pragma mark - GeTuiSdkDelegate /** SDK啟動(dòng)成功返回cid */ - (void)GeTuiSdkDidRegisterClient:(NSString *)clientId { // [4-EXT-1]: 個(gè)推SDK已注冊(cè),返回clientId NSLog(@"\n>>>[GeTuiSdk RegisterClient]:%@\n\n", clientId); } /** SDK遇到錯(cuò)誤回調(diào) */ - (void)GeTuiSdkDidOccurError:(NSError *)error { // [EXT]:個(gè)推錯(cuò)誤報(bào)告,集成步驟發(fā)生的任何錯(cuò)誤都在這里通知,如果集成后,無(wú)法正常收到消息,查看這里的通知。 NSLog(@"\n>>>[GexinSdk error]:%@\n\n", [error localizedDescription]); } /** SDK收到透?jìng)飨⒒卣{(diào) */ - (void)GeTuiSdkDidReceivePayload:(NSString *)payloadId andTaskId:(NSString *)taskId andMessageId:(NSString *)aMsgId andOffLine:(BOOL)offLine fromApplication:(NSString *)appId { // [4]: 收到個(gè)推消息 NSData *payload = [GeTuiSdk retrivePayloadById:payloadId]; NSString *payloadMsg = nil; if (payload) { payloadMsg = [[NSString alloc] initWithBytes:payload.bytes length:payload.length encoding:NSUTF8StringEncoding]; } NSString *msg = [NSString stringWithFormat:@" payloadId=%@,taskId=%@,messageId:%@,payloadMsg:%@%@", payloadId, taskId, aMsgId, payloadMsg, offLine ? @"<離線消息>" : @""]; NSLog(@"\n>>>[GexinSdk ReceivePayload]:%@\n\n", msg); /** *匯報(bào)個(gè)推自定義事件 *actionId:用戶(hù)自定義的actionid,int類(lèi)型,取值90001-90999。 *taskId:下發(fā)任務(wù)的任務(wù)ID。 *msgId: 下發(fā)任務(wù)的消息ID。 *返回值:BOOL,YES表示該命令已經(jīng)提交,NO表示該命令未提交成功。注:該結(jié)果不代表服務(wù)器收到該條命令 **/ [GeTuiSdk sendFeedbackMessage:90001 taskId:taskId msgId:aMsgId]; } /** SDK收到sendMessage消息回調(diào) */ - (void)GeTuiSdkDidSendMessage:(NSString *)messageId result:(int)result { // [4-EXT]:發(fā)送上行消息結(jié)果反饋 NSString *msg = [NSString stringWithFormat:@"sendmessage=%@,result=%d", messageId, result]; NSLog(@"\n>>>[GexinSdk DidSendMessage]:%@\n\n", msg); } /** SDK運(yùn)行狀態(tài)通知 */ - (void)GeTuiSDkDidNotifySdkState:(SdkStatus)aStatus { // [EXT]:通知SDK運(yùn)行狀態(tài) NSLog(@"\n>>>[GexinSdk SdkState]:%u\n\n", aStatus); } /** SDK設(shè)置推送模式回調(diào) */ - (void)GeTuiSdkDidSetPushMode:(BOOL)isModeOff error:(NSError *)error { if (error) { NSLog(@"\n>>>[GexinSdk SetModeOff Error]:%@\n\n", [error localizedDescription]); return; } NSLog(@"\n>>>[GexinSdk SetModeOff]:%@\n\n", isModeOff ? @"開(kāi)啟" : @"關(guān)閉"); } -(void)geTuiRegister{ }
然后再appDelegate 調(diào)用注冊(cè)遠(yuǎn)程推送的方法
/** 注冊(cè)用戶(hù)通知 */ - (void)registerUserNotification { /* 注冊(cè)通知(推送) 申請(qǐng)App需要接受來(lái)自服務(wù)商提供推送消息 */ // 判讀系統(tǒng)版本是否是“iOS 8.0”以上 if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0 || [UIApplication instancesRespondToSelector:@selector(registerUserNotificationSettings:)]) { // 定義用戶(hù)通知類(lèi)型(Remote.遠(yuǎn)程 - Badge.標(biāo)記 Alert.提示 Sound.聲音) UIUserNotificationType types = UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound; // 定義用戶(hù)通知設(shè)置 UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:types categories:nil]; // 注冊(cè)用戶(hù)通知 - 根據(jù)用戶(hù)通知設(shè)置 [[UIApplication sharedApplication] registerUserNotificationSettings:settings]; [[UIApplication sharedApplication] registerForRemoteNotifications]; } else { // iOS8.0 以前遠(yuǎn)程推送設(shè)置方式 // 定義遠(yuǎn)程通知類(lèi)型(Remote.遠(yuǎn)程 - Badge.標(biāo)記 Alert.提示 Sound.聲音) UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound; // 注冊(cè)遠(yuǎn)程通知 -根據(jù)遠(yuǎn)程通知類(lèi)型 [[UIApplication sharedApplication] registerForRemoteNotificationTypes:myTypes]; } }
然后再設(shè)置了窗口的跟控制器 之后 調(diào)用:addPushView方法 添加 消息提示框STPushView: addPushView實(shí)現(xiàn)代碼如下
#pragma mark 推送信息展示 //添加推送view - (void)addPushView { STPushView *topView = [STPushView shareInstance]; topView.frame = CGRectMake(0, -pushViewHeight, SCREEN_WIDTH, pushViewHeight); [_window addSubview:topView]; self.topView = topView; topView.hidden = YES; UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hudClick)]; UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)]; [topView addGestureRecognizer:tap]; [tap requireGestureRecognizerToFail:pan]; topView.gestureRecognizers = @[tap,pan]; } #pragma mark addPushView相關(guān)事件 - (void)hudClick { self.topView.userInteractionEnabled = NO; [UIView animateWithDuration:0.25 animations:^{ self.topView.frame = CGRectMake(0, -pushViewHeight, SCREEN_WIDTH, pushViewHeight); }completion:^(BOOL finished) { [UIApplication sharedApplication].statusBarHidden = NO; [self hudClickOperation]; }]; } - (void)hudClickOperation { [self push:nil]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ self.topView.userInteractionEnabled = YES; }); } - (void)pan:(UIPanGestureRecognizer*)pan { CGFloat distance = pushViewHeight-(pushViewHeight-[pan translationInView:self.window].y); if (distance<-20) { [UIView animateWithDuration:0.25 animations:^{ self.topView.frame = CGRectMake(0, -pushViewHeight, SCREEN_WIDTH, pushViewHeight); }completion:^(BOOL finished) { [UIApplication sharedApplication].statusBarHidden = NO; }]; } } //顯示pushView - (void)displayPushView { [STPushView show]; }
上面push方法的實(shí)現(xiàn)代碼如下: 處理邏輯 是根據(jù)我自己的項(xiàng)目中需求定的 在這里實(shí)現(xiàn)你需要處理的代碼
- (void)push:(NSDictionary *)params{ STPushModel *model = [ NSKeyedUnarchiver unarchiveObjectWithFile:KRAPI_PUSH_DATA]; //如果是h5 if ([model.urlType isEqualToString:@"h5"]) { BOOL isStore = [[AnalysisUrl sharedInstance] analysisWebUrl:model.url]; BOOL isGoods = [[AnalysisUrl sharedInstance] analysisGoodsIdWebUrl:model.url]; BOOL isRedBag =[[AnalysisUrl sharedInstance] analyredBagWebUrl:model.url]; BOOL istrace =[[AnalysisUrl sharedInstance] analytraceWebUr:model.url]; BOOL islog =[[AnalysisUrl sharedInstance] analylogWebUrl:model.url]; if (isStore || isGoods) { [[WYPageManager sharedInstance] pushViewControllerWithUrlString:model.url currentUrlString:TRAKER_URL_INDEX]; }else if (isRedBag) { RedBageViewController * regBag =[[RedBageViewController alloc]init]; NSArray *array = [model.url componentsSeparatedByString:@"="]; NSString * string = [array lastObject]; regBag.messageID = string; regBag.redType = @"coupon"; UITabBarController *tabVC = (UITabBarController *)self.window.rootViewController; UINavigationController *pushClassStance = (UINavigationController *)tabVC.viewControllers[tabVC.selectedIndex]; // 跳轉(zhuǎn)到對(duì)應(yīng)的控制器 regBag.hidesBottomBarWhenPushed = YES; [pushClassStance pushViewController:regBag animated:YES]; return; }else if (istrace) { RedBageViewController * regBag =[[RedBageViewController alloc]init]; NSString * string = [StrUtils getIdFromURLString:model.url interceptString:@"/trace/"]; regBag.messageID = string; regBag.redType = @"trace"; UITabBarController *tabVC = (UITabBarController *)self.window.rootViewController; UINavigationController *pushClassStance = (UINavigationController *)tabVC.viewControllers[tabVC.selectedIndex]; // 跳轉(zhuǎn)到對(duì)應(yīng)的控制器 regBag.hidesBottomBarWhenPushed = YES; [pushClassStance pushViewController:regBag animated:YES]; return; }else if (islog) { RedBageViewController * regBag =[[RedBageViewController alloc]init]; NSString * string = [StrUtils getIdFromURLString:model.url interceptString:@"/log/"]; regBag.messageID = string; regBag.redType = @"log"; UITabBarController *tabVC = (UITabBarController *)self.window.rootViewController; UINavigationController *pushClassStance = (UINavigationController *)tabVC.viewControllers[tabVC.selectedIndex]; // 跳轉(zhuǎn)到對(duì)應(yīng)的控制器 regBag.hidesBottomBarWhenPushed = YES; [pushClassStance pushViewController:regBag animated:YES]; return; } else{ if (![model.url isEqualToString:@""]) { UIStoryboard *setStoryboard = [UIStoryboard storyboardWithName:@"UserCenter" bundle:nil]; TotalWebViewController *setVC = [setStoryboard instantiateViewControllerWithIdentifier:@"TotalWebViewController"]; setVC.shopUrl = model.url; setVC.shopTitle = [model.title isEqualToString:@""] ? @"121店" : model.title; UITabBarController *tabVC = (UITabBarController *)self.window.rootViewController; UINavigationController *pushClassStance = (UINavigationController *)tabVC.viewControllers[tabVC.selectedIndex]; setVC.hidesBottomBarWhenPushed = YES; [pushClassStance pushViewController:setVC animated:YES]; } } }else if ([model.urlType isEqualToString:@"native"]){ if ([model.url isEqualToString:@"1"]) { //一元體驗(yàn)購(gòu) 已經(jīng)刪除 }else if ([model.url isEqualToString:@"2"]){ if (([[STCommonInfo getAuthType] intValue] != 1)) { [self createGroundGlass]; }else{ STProFitViewController *vc = [[STProFitViewController alloc] init]; UITabBarController *tabVC = (UITabBarController *)self.window.rootViewController; UINavigationController *pushClassStance = (UINavigationController *)tabVC.viewControllers[tabVC.selectedIndex]; vc.hidesBottomBarWhenPushed = YES; [pushClassStance pushViewController:vc animated:YES]; } }else if ([model.url isEqualToString:@"3"]){ if (([[STCommonInfo getAuthType] intValue] != 1)) { [self createGroundGlass]; }else{ MessageMainVC *messageVC = [[MessageMainVC alloc] init]; messageVC.hidesBottomBarWhenPushed = YES; UITabBarController *tabVC = (UITabBarController *)self.window.rootViewController; UINavigationController *pushClassStance = (UINavigationController *)tabVC.viewControllers[tabVC.selectedIndex]; [pushClassStance pushViewController:messageVC animated:YES]; } }else if ([model.url hasPrefix:@"http://"]&&([model.url rangeOfString:@"client"].location!=NSNotFound)){ //跳轉(zhuǎn)到客服接 界面 NSString *orgIdString =[[AnalysisUrl sharedInstance] extractOrgId:model.url]; NSString *siteIdString = [[AnalysisUrl sharedInstance] extractOrgIdStoreId:model.url]; [[WYPageManager sharedInstance] pushViewController:@"TLChatViewController" withParam: @{ @"title_nameString":@"官方客服", @"orgIdString":orgIdString, @"siteIdString":siteIdString, @"currentURL":model.url } animated:YES]; } } }
然后再AppDelegate 實(shí)現(xiàn)以下方法
/** 自定義:APP被“推送”啟動(dòng)時(shí)處理推送消息處理(APP 未啟動(dòng)--》啟動(dòng))*/- (void)receiveNotificationByLaunchingOptions:(NSDictionary *)launchOptions { if (!launchOptions) return; /* 通過(guò)“遠(yuǎn)程推送”啟動(dòng)APP UIApplicationLaunchOptionsRemoteNotificationKey 遠(yuǎn)程推送Key */ NSDictionary *userInfo = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]; if (userInfo) { NSLog(@"\n>>>[Launching RemoteNotification]:%@", userInfo); } } #pragma mark - 用戶(hù)通知(推送)回調(diào) _IOS 8.0以上使用 /** 已登記用戶(hù)通知 */ - (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings { // 注冊(cè)遠(yuǎn)程通知(推送) [application registerForRemoteNotifications]; } #pragma mark - 遠(yuǎn)程通知(推送)回調(diào) /** 遠(yuǎn)程通知注冊(cè)成功委托 */ - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { NSString *myToken = [[deviceToken description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]]; myToken = [myToken stringByReplacingOccurrencesOfString:@" " withString:@""]; NSUserDefaults *kr = [NSUserDefaults standardUserDefaults]; [kr setValue:myToken forKey:@"deviceToken"]; [kr synchronize]; [GeTuiSdk registerDeviceToken:myToken]; [[PostDeviceToken sharedInstance] postUpDeviceToken]; NSLog(@"\n>>>[DeviceToken Success]:%@\n\n", myToken); } /** 遠(yuǎn)程通知注冊(cè)失敗委托 */ - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { [GeTuiSdk registerDeviceToken:@""]; NSLog(@"\n>>>[DeviceToken Error]:%@\n\n", error.description); } #pragma mark - APP運(yùn)行中接收到通知(推送)處理 /** APP已經(jīng)接收到“遠(yuǎn)程”通知(推送) - 透?jìng)魍扑拖?*/ - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler { // 處理APN NSLog(@"\n>>>[Receive RemoteNotification - Background Fetch]:%@\n\n", userInfo); completionHandler(UIBackgroundFetchResultNewData); NSString *payLoadString = [[MyPrevent sharedInstance] dictionary:userInfo objectForKey:@"payload"]; [[SpotPunch sharedInstance] spotPunch:@"999.999.1" pointTwo:@"21" info:payLoadString]; // NSUserDefaults *kr = [NSUserDefaults standardUserDefaults]; if (!([[STCommonInfo getAuthType] intValue] != 1)) { NSData *jsonData = [payLoadString dataUsingEncoding:NSUTF8StringEncoding]; NSDictionary *jsonDic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:nil]; STPushModel *model = [STPushModel modelObjectWithDict:jsonDic]; [NSKeyedArchiver archiveRootObject:model toFile:KRAPI_PUSH_DATA]; //如果應(yīng)用程序在前臺(tái) 就顯示客服提示框 if (application.applicationState == UIApplicationStateActive) { self.topView.model = model; [self displayPushView]; //此方法 的實(shí)現(xiàn) 在上一步中 就是展示提示框出來(lái) } } }
然后這些工作做好了之后 就是你需要在個(gè)推的后臺(tái) 配置推送證書(shū) 這個(gè)配置的步驟 大家可以到個(gè)推官網(wǎng)去參考文檔 配置
這里我假設(shè) 你已經(jīng)配置到證書(shū)了 經(jīng)過(guò)上面的步驟 我們的遠(yuǎn)程推送通知的方法 基本完成 現(xiàn)在我們運(yùn)行 測(cè)試下 你會(huì)發(fā)現(xiàn)即使在前臺(tái) 有新消息推送的時(shí)候 頂部也會(huì)彈出和系統(tǒng)一樣的提示框 點(diǎn)擊 跳轉(zhuǎn)到對(duì)應(yīng)的頁(yè)面的方法邏輯根據(jù)你的需要 去做跳轉(zhuǎn)處理
測(cè)試效果如下:
用戶(hù)在后臺(tái) 收到的消息提示如下:
用戶(hù)在前臺(tái) 收到的消息提示如下:
本文已被整理到了《iOS推送教程》,歡迎大家學(xué)習(xí)閱讀。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- iOS10添加本地推送(Local Notification)實(shí)例
- iOS10 適配遠(yuǎn)程推送功能實(shí)現(xiàn)代碼
- 使用iOS推送時(shí)警告錯(cuò)誤的解決方法
- iOS10實(shí)現(xiàn)推送功能時(shí)的注意點(diǎn)和問(wèn)題總結(jié)
- iOS點(diǎn)擊推送消息跳到應(yīng)用指定頁(yè)面方法
- iOS10全新推送功能實(shí)現(xiàn)代碼
- iOS實(shí)現(xiàn)遠(yuǎn)程推送原理及過(guò)程
- 解析iOS10中的極光推送消息的適配
- 輕松搞定iOS本地消息推送
- iOS學(xué)習(xí)筆記之遠(yuǎn)程推送、靜默推送與自定義消息推送
相關(guān)文章
個(gè)人對(duì)于異步和多線程的關(guān)系的理解分享
異步和多線程并不是一個(gè)同等關(guān)系,異步是最終目的,多線程只是我們實(shí)現(xiàn)異步的一種手段。異步是當(dāng)一個(gè)調(diào)用請(qǐng)求發(fā)送給被調(diào)用者,而調(diào)用者不用等待其結(jié)果的返回而可以做其它的事情。2014-08-08ios UITableView 自定義右滑刪除的實(shí)現(xiàn)代碼
這篇文章主要介紹了ios UITableView 自定義右滑刪除的實(shí)現(xiàn)代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-07-07iOS開(kāi)發(fā)中CAlayer層的屬性以及自定義層的方法
這篇文章主要介紹了iOS開(kāi)發(fā)中CAlayer層的屬性以及自定義層的方法,代碼基于傳統(tǒng)的Objective-C,需要的朋友可以參考下2015-11-11IOS實(shí)現(xiàn)簽到特效(散花效果)的實(shí)例代碼
這篇文章主要介紹了IOS實(shí)現(xiàn)簽到特效(散花效果)的實(shí)例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-05-05iOS中使用UItableviewcell實(shí)現(xiàn)團(tuán)購(gòu)和微博界面的示例
這篇文章主要介紹了iOS中使用UItableviewcell實(shí)現(xiàn)團(tuán)購(gòu)和微博界面的示例,開(kāi)發(fā)語(yǔ)言基于傳統(tǒng)的Objective-C,需要的朋友可以參考下2016-01-01iOS開(kāi)發(fā)之導(dǎo)航欄各種右滑返回失效的解決方法匯總
這篇文章主要給大家總結(jié)介紹了關(guān)于iOS開(kāi)發(fā)教程之導(dǎo)航欄各種右滑返回失效的解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)各位iOS具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-08-08IOS UI學(xué)習(xí)教程之設(shè)置UITextField各種屬性
這篇文章主要為大家詳細(xì)介紹了IOS UI學(xué)習(xí)教程之設(shè)置UITextField各種屬性,感興趣的小伙伴們可以參考一下2016-03-03