看到标题你可能会觉得奇怪 推送消息提示框不是系统自己弹出来的吗? 为什么还要自己自定义呢?

因为项目需求是这样的:最近需要做 远程推送通知 和一个客服系统 包括店铺客服和官方客服两个模块 如果有新的消息推送的时候 如果用户当前不在客服界面的时候  要求无论是在app前台 还是app退到后台 顶部都要弹出系统的那种消息提示框

这样的需求 我们就只能自定义一个在app内 弹出消息提示框

实现步骤如下:

1.我们自定义一个view 为 STPushView 推送消息的提示框view

#import <UIKit/UIKit.h>
#import "STPushModel.h" @interface STPushView : UIView /** *推送数据模型 */
@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(, , ); CGFloat margin = ;
UIImageView *imageV = [[UIImageView alloc] init];
imageV.userInteractionEnabled = NO;
imageV.image = [UIImage imageNamed:@"logo"];
imageV.layer.cornerRadius = ;
[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();
make.height.mas_equalTo();
}]; UILabel *titleLabel = [[UILabel alloc] init];
titleLabel.textColor = [UIColor whiteColor];
titleLabel.font = [UIFont boldSystemFontOfSize:];
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();
}];
[titleLabel sizeToFit]; UILabel *timLabel = [[UILabel alloc] init];
timLabel.font = [UIFont systemFontOfSize:];
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();
make.height.mas_equalTo();
}]; UILabel *content = [[UILabel alloc] init];
content.numberOfLines = ;
content.font = [UIFont systemFontOfSize:];
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(-);
make.right.equalTo(self.mas_right).offset(-margin);
make.height.mas_equalTo();
}]; UIView *toolbar = [[UIView alloc] init];
toolbar.backgroundColor = CUSTOMCOLOR(, , );
toolbar.layer.cornerRadius = ;
[self addSubview:toolbar];
[toolbar mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.mas_equalTo();
make.height.mas_equalTo();
make.centerX.equalTo(self.mas_centerX);
make.bottom.equalTo(self.mas_bottom).offset(-);
}]; }
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(, , SCREEN_WIDTH, pushViewHeight); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)( * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [UIView animateWithDuration:0.25 animations:^{ pushView.frame = CGRectMake(, -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(, -pushViewHeight, SCREEN_WIDTH, pushViewHeight); } completion:^(BOOL finished) { [UIApplication sharedApplication].statusBarHidden = NO;
pushView.hidden = YES; }]; } @end

上面pushView需要一个模型 实现代码如下

// push 推送的model

推送过来的数据如下:
/**
content = dsfdsnfds;
id = 5077;
mid = 1270339;
title = dsfdsnfds;
url = "3?_from=push";
urlType = 3; **/
#import <Foundation/Foundation.h> @interface STPushModel : STBaseModel<NSCoding> //STBaseModel 是一个继承自NSObject的类 我主要是在这个类中实现了字典转模型的功能 你可以直接修改为NSObject /***id**/
@property (copy,nonatomic) NSString* recordId;
/***标题**/
@property (copy, nonatomic) NSString *title;
/***url**/
@property (copy, nonatomic) NSString *url;
/***url 类型**/
@property (copy, nonatomic) NSString* urlType;
/***图标的高度**/
@property (assign,nonatomic) NSString * mid;
/***推送内容**/
@property (copy, nonatomic) NSString* content; @end

因为涉及到好几个页面需要使用同样的推送消息数据 进行判断而处理相应的业务 所有我对此模型做了归档处理

#import "STPushModel.h"

@implementation STPushModel

/**
* 保存对象到文件中
*
* @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"];
} /**
* 从文件中读取对象
*
* @param aDecoder <#aDecoder description#>
*
* @return <#return value description#>
*/
-(id)initWithCoder:(NSCoder *)aDecoder
{
//注意:在构造方法中需要先初始化父类的方法
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

做好了上面的准备工作之后  接下来我们就需要 APPdelegate里面注册远程推送通知  并且监听推送消息

这里以个推为例子:

第一步在下面的方法中 实现个推的注册方法

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

  // 注册个推推送服务
[[GeTuiApilmpl sharedInstance] geTuiRegister]; }
GeTuiApilmpl 是一个单例类 专门用于注册个推的推送方法  实现代码如下:
#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;
} #pragma mark - GeTuiSdkDelegate
/** SDK启动成功返回cid */
- (void)GeTuiSdkDidRegisterClient:(NSString *)clientId {
// [4-EXT-1]: 个推SDK已注册,返回clientId
NSLog(@"\n>>>[GeTuiSdk RegisterClient]:%@\n\n", clientId);
} /** SDK遇到错误回调 */
- (void)GeTuiSdkDidOccurError:(NSError *)error {
// [EXT]:个推错误报告,集成步骤发生的任何错误都在这里通知,如果集成后,无法正常收到消息,查看这里的通知。
NSLog(@"\n>>>[GexinSdk error]:%@\n\n", [error localizedDescription]);
} /** SDK收到透传消息回调 */
- (void)GeTuiSdkDidReceivePayload:(NSString *)payloadId andTaskId:(NSString *)taskId andMessageId:(NSString *)aMsgId andOffLine:(BOOL)offLine fromApplication:(NSString *)appId {
// [4]: 收到个推消息
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);
/**
*汇报个推自定义事件
*actionId:用户自定义的actionid,int类型,取值90001-90999。
*taskId:下发任务的任务ID。
*msgId: 下发任务的消息ID。
*返回值:BOOL,YES表示该命令已经提交,NO表示该命令未提交成功。注:该结果不代表服务器收到该条命令
**/
[GeTuiSdk sendFeedbackMessage: taskId:taskId msgId:aMsgId];
} /** SDK收到sendMessage消息回调 */
- (void)GeTuiSdkDidSendMessage:(NSString *)messageId result:(int)result {
// [4-EXT]:发送上行消息结果反馈
NSString *msg = [NSString stringWithFormat:@"sendmessage=%@,result=%d", messageId, result];
NSLog(@"\n>>>[GexinSdk DidSendMessage]:%@\n\n", msg);
} /** SDK运行状态通知 */
- (void)GeTuiSDkDidNotifySdkState:(SdkStatus)aStatus {
// [EXT]:通知SDK运行状态
NSLog(@"\n>>>[GexinSdk SdkState]:%u\n\n", aStatus);
} /** SDK设置推送模式回调 */
- (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 ? @"开启" : @"关闭");
} -(void)geTuiRegister{
  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];
}

上面的 libGexin.plist 的配置内容如下:

然后再appDelegate 调用注册远程推送的方法

/** 注册用户通知 */
- (void)registerUserNotification {
/*
注册通知(推送)
申请App需要接受来自服务商提供推送消息
*/
// 判读系统版本是否是“iOS 8.0”以上
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0 ||
[UIApplication instancesRespondToSelector:@selector(registerUserNotificationSettings:)]) {
// 定义用户通知类型(Remote.远程 - Badge.标记 Alert.提示 Sound.声音)
UIUserNotificationType types = UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound;
// 定义用户通知设置
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
// 注册用户通知 - 根据用户通知设置
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
[[UIApplication sharedApplication] registerForRemoteNotifications];
} else { // iOS8.0 以前远程推送设置方式
// 定义远程通知类型(Remote.远程 - Badge.标记 Alert.提示 Sound.声音)
UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
// 注册远程通知 -根据远程通知类型
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:myTypes];
}
}

然后在AppDelegate的 didFinishLaunchingWithOptions 写上如下代码:

调用:addPushView方法 添加 消息提示框STPushView:  addPushView实现代码如下

#pragma mark 推送信息展示
//添加推送view
- (void)addPushView
{
STPushView *topView = [STPushView shareInstance];
topView.frame = CGRectMake(, -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相关事件
- (void)hudClick
{
self.topView.userInteractionEnabled = NO; [UIView animateWithDuration:0.25 animations:^{
self.topView.frame = CGRectMake(, -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)( * 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<-) {
[UIView animateWithDuration:0.25 animations:^{
self.topView.frame = CGRectMake(, -pushViewHeight, SCREEN_WIDTH, pushViewHeight);
}completion:^(BOOL finished) {
[UIApplication sharedApplication].statusBarHidden = NO;
}];
}
} //显示pushView
- (void)displayPushView
{
[STPushView show];
}

上面push方法的实现代码如下: 处理逻辑 是根据我自己的项目中需求定的 在这里实现你需要处理的代码

- (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];
// 跳转到对应的控制器
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];
// 跳转到对应的控制器
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];
// 跳转到对应的控制器
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:@""]) {
//一元体验购 已经删除 }else if ([model.url isEqualToString:@""]){
if (([[STCommonInfo getAuthType] intValue] != )) {
[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:@""]){
if (([[STCommonInfo getAuthType] intValue] != )) {
[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)){ //跳转到客服接 界面 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 实现以下方法

/** 自定义:APP被“推送”启动时处理推送消息处理(APP 未启动--》启动)*/
- (void)receiveNotificationByLaunchingOptions:(NSDictionary *)launchOptions {
if (!launchOptions)
return;
/*
通过“远程推送”启动APP
UIApplicationLaunchOptionsRemoteNotificationKey 远程推送Key
*/
NSDictionary *userInfo = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (userInfo) {
NSLog(@"\n>>>[Launching RemoteNotification]:%@", userInfo);
}
} #pragma mark - 用户通知(推送)回调 _IOS 8.0以上使用 /** 已登记用户通知 */
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
// 注册远程通知(推送)
[application registerForRemoteNotifications];
} #pragma mark - 远程通知(推送)回调 /** 远程通知注册成功委托 */
- (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);
} /** 远程通知注册失败委托 */
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
[GeTuiSdk registerDeviceToken:@""];
NSLog(@"\n>>>[DeviceToken Error]:%@\n\n", error.description);
} #pragma mark - APP运行中接收到通知(推送)处理
/** APP已经接收到“远程”通知(推送) - 透传推送消息 */
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler {
// 处理APN
NSLog(@"\n>>>[Receive RemoteNotification - Background Fetch]:%@\n\n", userInfo);
completionHandler(UIBackgroundFetchResultNewData);
// NSUserDefaults *kr = [NSUserDefaults standardUserDefaults];
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];
//如果应用程序在前台 就显示客服提示框
if (application.applicationState == UIApplicationStateActive) {
self.topView.model = model;
[self displayPushView]; //此方法 的实现 在上一步中 就是展示提示框出来
} }

然后这些工作做好了之后 就是你需要在个推的后台 配置推送证书  这个配置的步骤 大家可以到个推官网去参考文档 配置

这里我假设 你已经配置到证书了  经过上面的步骤 我们的远程推送通知的方法 基本完成 现在我们运行 测试下 你会发现即使在前台 有新消息推送的时候 顶部也会弹出和系统一样的提示框 点击 跳转到对应的页面的方法逻辑根据你的需要 去做跳转处理

测试效果如下:

用户在后台 收到的消息提示如下:

用户在前台 收到的消息提示如下:

自定义iOS 中推送消息 提示框的更多相关文章

  1. Android开发 ---构建对话框Builder对象,消息提示框、列表对话框、单选提示框、多选提示框、日期/时间对话框、进度条对话框、自定义对话框、投影

    效果图: 1.activity_main.xml 描述: a.定义了一个消息提示框按钮 点击按钮弹出消息 b.定义了一个选择城市的输入框 点击按钮选择城市 c.定义了一个单选提示框按钮 点击按钮选择某 ...

  2. 微信小程序API交互反馈,wx.showToast显示消息提示框

    导读:wx.showToast(OBJECT) 显示消息提示框. OBJECT参数说明: 参数 类型 必填 说明 最低版本 title String 是 提示的内容 icon String 否 图标, ...

  3. Android:Toast简单消息提示框

    Toast是简单的消息提示框,一定时间后自动消失,没有焦点. 1.简单文本提示的方法: Toast.makeText(this, "默认的toast", Toast.LENGTH_ ...

  4. 【转】提示框第三方库之MBProgressHUD iOS toast效果 动态提示框效果

    原文网址:http://www.zhimengzhe.com/IOSkaifa/37910.html MBProgressHUD是一个开源项目,实现了很多种样式的提示框,使用上简单.方便,并且可以对显 ...

  5. Android消息提示框Toast

    Android消息提示框Toast Toast是Android中一种简易的消息提示框.和Dialog不一样的是,Toast是没有焦点的,toast提示框不能被用户点击,而且Toast显示的时间有限,t ...

  6. Android 代码库(自定义一套 Dialog通用提示框 )

          做Android开发五年了,期间做做停停(去做后台开发,服务器管理),当回来做Android的时候,发现很生疏,好些控件以前写得很顺手,现在好像忘记些什么了,总要打开这个项目,打开那个项目 ...

  7. wpf实现仿qq消息提示框

    原文:wpf实现仿qq消息提示框 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/huangli321456/article/details/5052 ...

  8. UWP中的消息提示框(一)

    不管什么平台,应用内难免会出现一些消息提示框,下面就来聊聊我在UWP里用到的消息提示框. 弹窗也可按是否需要用户操作促发一些逻辑进行分为两大类. 不需要用户干涉的一类: MessageDialog:操 ...

  9. UWP中的消息提示框(二)

    在UWP中的消息提示框(一)中介绍了一些常见的需要用户主动去干涉的一些消息提示框,接下来打算聊聊不需要用户主动去干涉的一些消息提示框.效果就是像双击退出的那种提示框. 先说说比较简单的吧,通过系统To ...

随机推荐

  1. SQL Server 变更数据捕获(CDC)监控表数据

    一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 实现过程(Realization) 补充说明(Addon) 参考文献(References) ...

  2. 一个微软的DDD架构图

  3. MySQL MVCC(多版本并发控制)

    概述 为了提高并发MySQL加入了多版本并发控制,它把旧版本记录保存在了共享表空间(undolog),当事务提交之后将重做日志写入磁盘(前提innodb_flush_log_at_trx_commit ...

  4. [SQLServer大对象]——FileTable从文件系统迁移文件

    阅读导航 从文件系统中迁移文件到FileTable 批量加载文件到FileTable 如何批量加载文件到FileTable 通过博文[SQLServer大对象]——FileTable初体验,已经可以将 ...

  5. ReactNative与NativeScript对比报告

    综合这段时间对ReactNative(下称RN)和NativeScript(下称NS)的简单学习了解,分别从不同方面分析对比二者的优缺点. 页面结构 NS一个页面的目录结构: RN的一个页面一般就是一 ...

  6. Appium的安装-MAC平台

    其实Appium的安装方式主要有两种: 1)自己安装配置nodejs的环境,然后通过npm进行appium的安装 2)直接下载官网提供的dmg进行安装,dmg里面已经有nodejs的环境和appium ...

  7. C#+OpenGL+FreeType显示3D文字(1) - 从TTF文件导出字形贴图

    C#+OpenGL+FreeType显示3D文字(1) - 从TTF文件导出字形贴图 +BIT祝威+悄悄在此留下版了个权的信息说: 最近需要用OpenGL绘制文字,这是个很费时费力的事.一般的思路就是 ...

  8. 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC

    系列文章 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 七天学会ASP.NET MVC (二)——ASP.NET MVC 数据传递 七天学会ASP.NET MVC (三)— ...

  9. SSIS 参数的值

    一,SSIS Parameter Value 的type 一个Parameter的Value共有三种类型,分别是Design Value,Server Value,Execution Value. D ...

  10. 深入理解javascript函数系列第四篇——ES6函数扩展

    × 目录 [1]参数默认值 [2]rest参数 [3]扩展运算符[4]箭头函数 前面的话 ES6标准关于函数扩展部分,主要涉及以下四个方面:参数默认值.rest参数.扩展运算符和箭头函数 参数默认值 ...