当您的应用程序处于打开状态且位于前台时显示库存iOS通知横幅?

pka*_*amb 107 uikit toast apple-push-notifications ios uilocalnotification

当Apple的官方iOS消息应用程序处于打开状态并位于前台时,来自其他联系人的新消息会触发库存本机iOS通知警报横幅.见下图.

这在App Store的第三方应用程序中是否可行?应用程序处于打开状态且位于前台时,应用程序的本地和/或推送通知?

在测试我的应用时,会收到通知,但不会显示iOS警报用户界面.

但是,这种行为出现在苹果的官方消息应用程序:

消息是打开的并且在前台. 仍显示通知警报.

本地和远程通知编程指南说:

当操作系统提供本地通知或远程通知且目标应用程序未在前台运行时,它可以通过警报,图标标记号或声音向用户显示通知.

如果应用程序在传递通知时在前台运行,则应用程序委托会收到本地或远程通知.

所以是的,我们可以在前台接收通知数据.但我认为无法呈现本机iOS通知警报UI.

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo 
{
    // I know we still receive the notification `userInfo` payload in the foreground.
    // This question is about displaying the stock iOS notification alert UI.

    // Yes, one *could* use a 3rd party toast alert framework. 
    [self use3rdPartyToastAlertFrameworkFromGithub]
}
Run Code Online (Sandbox Code Playgroud)

然后消息是否使用私有API在前台显示警报?

对于这个问题的目的,请不要提出任何第三方"敬酒",弹出警报在github上或者等我只是有兴趣,如果这可以用做库存,提供原生iOS本地或推送通知提醒用户界面,而你应用程序是开放的,在前台.

pka*_*amb 130

iOS 10添加了UNUserNotificationCenterDelegate用于在应用程序位于前台时处理通知的协议.

UNUserNotificationCenterDelegate协议定义了接收通知和处理操作的方法.当您的应用程序位于前台时,到达的通知将传递到您的委托对象,而不是使用系统界面自动显示.

迅速:

optional func userNotificationCenter(_ center: UNUserNotificationCenter, 
                     willPresent notification: UNNotification, 
      withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void)
Run Code Online (Sandbox Code Playgroud)

Objective-C的:

- (void)userNotificationCenter:(UNUserNotificationCenter *)center 
       willPresentNotification:(UNNotification *)notification 
         withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler;
Run Code Online (Sandbox Code Playgroud)

UNNotificationPresentationOptions标志允许您指定UNNotificationPresentationOptionAlert显示使用通知中的文本警报.

这是关键,因为它允许您在应用程序打开时和前台显示警报,这是iOS 10的新功能.

示例代码:

class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        // Set UNUserNotificationCenterDelegate
        UNUserNotificationCenter.current().delegate = self

        return true
    }

}

// Conform to UNUserNotificationCenterDelegate
extension AppDelegate: UNUserNotificationCenterDelegate {

    func userNotificationCenter(_ center: UNUserNotificationCenter,
           willPresent notification: UNNotification,
           withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void)
    {
        completionHandler(.alert)
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 不要忘记在`application(_:willFinishLaunchingWithOptions:)`或`application(_:didFinishLaunchingWithOptions :))`方法中添加`UNUserNotificationCenter.current().delegate = self` (7认同)
  • 你能提供一个工作代码示例,其中系统显示传入的前景通知,好像应用程序在哪里? (4认同)
  • 另外,请确保您的设备没有处于[请勿打扰模式](https://support.apple.com/en-gb/HT204321),否则通知将显示在通知中心,但不会显示在应用程序的前台 (3认同)
  • 我的 2 美分:不要错过:导入 UserNotifications。! (2认同)

che*_*sam 88

要在应用程序位于前台时显示横幅消息,请使用以下方法.

iOS 10,Swift 3:

func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
    completionHandler([.alert, .badge, .sound])
}
Run Code Online (Sandbox Code Playgroud)

  • 哇.为什么这不是公认的答案? (2认同)
  • Chengsam,您可能要纠正此问题:不必将其放在`AppDelegate`中。必须将其放置在符合[`UNUserNotificationCenterDelegate`](https://developer.apple.com/documentation/usernotifications/unusernotificationcenterdelegate)的任何对象上。话虽如此,大多数开发人员都使他们的AppDelegate符合UNUserNotificationCenterDelegate。@YoavR。 (2认同)

pka*_*amb 16

编辑:

iOS 10中现在可以进行前景警报!请看这个答案.

适用于iOS 9及以下版本:

当您的应用程序处于打开状态且位于前台时,似乎无法显示库存iOS通知警报.Messages.app必须使用私有API.

当应用程序已经位于最前端时,系统不会显示任何警报,标记应用程序的图标或播放任何声音.- UILocalNotification文档

UIApplicationDelegate方法仍然被调用,让您的应用程序的本地或远程通知的回复:

application:didReceiveLocalNotification:
application:didReceiveRemoteNotification:
Run Code Online (Sandbox Code Playgroud)

但是,库存原生iOS通知警报横幅UI将不会显示在Apple的Messages.app中,它必须使用私有API.

您可以做的最好的事情是滚动自己的警报横幅或使用现有框架:

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo 
{    
    // Use a 3rd party toast alert framework to display a banner 
    [self toastAlertFromGithub]
}
Run Code Online (Sandbox Code Playgroud)

我在这里为这种行为打开了一个雷达: rdar://22313177

  • 那么whatsapp和其他着名的应用程序是如何做到的呢? (3认同)
  • 如果您建议使用第三方库,您应该包含`toastAlertFromGithub`的链接! (2认同)

Haf*_*eez 14

要在应用程序打开时显示通知,我们需要手动处理它.所以我在下面做的是收到通知后处理通知.

在AppDelegate.m中添加以下所有内容

  1. 处理通知电话
  2. 创建一个视图,添加AppIcon,Notification消息并将其显示为动画
  3. 添加触摸识别器,如果触摸则移除或在5秒内移除动画.

如果这是一个好的解决方案,请告诉我.对我来说工作得很好但不确定这是否正确.

- (void)application:(UIApplication *)applicationdidReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {


NSString *notifMessage = [[userInfo objectForKey:@"aps"] objectForKey:@"alert"];

//Define notifView as UIView in the header file
[_notifView removeFromSuperview]; //If already existing

_notifView = [[UIView alloc] initWithFrame:CGRectMake(0, -70, self.window.frame.size.width, 80)];
[_notifView setBackgroundColor:[UIColor blackColor]];

UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(10,15,30,30)];
imageView.image = [UIImage imageNamed:@"AppLogo.png"];

UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(60, 15, self.window.frame.size.width - 100 , 30)];
myLabel.font = [UIFont fontWithName:@"Helvetica" size:10.0];
myLabel.text = notifMessage;

[myLabel setTextColor:[UIColor whiteColor]];
[myLabel setNumberOfLines:0];

[_notifView setAlpha:0.95];

//The Icon
[_notifView addSubview:imageView];

//The Text
[_notifView addSubview:myLabel];

//The View
[self.window addSubview:_notifView];

UITapGestureRecognizer *tapToDismissNotif = [[UITapGestureRecognizer alloc] initWithTarget:self
                                                                                    action:@selector(dismissNotifFromScreen)];
tapToDismissNotif.numberOfTapsRequired = 1;
tapToDismissNotif.numberOfTouchesRequired = 1;

[_notifView addGestureRecognizer:tapToDismissNotif];


[UIView animateWithDuration:1.0 delay:.1 usingSpringWithDamping:0.5 initialSpringVelocity:0.1 options:UIViewAnimationOptionCurveEaseIn animations:^{

    [_notifView setFrame:CGRectMake(0, 0, self.window.frame.size.width, 60)];

} completion:^(BOOL finished) {


}];


//Remove from top view after 5 seconds
[self performSelector:@selector(dismissNotifFromScreen) withObject:nil afterDelay:5.0];


return;


}

//If the user touches the view or to remove from view after 5 seconds
- (void)dismissNotifFromScreen{

[UIView animateWithDuration:1.0 delay:.1 usingSpringWithDamping:0.5 initialSpringVelocity:0.1 options:UIViewAnimationOptionCurveEaseIn animations:^{

    [_notifView setFrame:CGRectMake(0, -70, self.window.frame.size.width, 60)];

} completion:^(BOOL finished) {


}];


}
Run Code Online (Sandbox Code Playgroud)

  • 这对于创建您自己的警报可能是一个很好的答案,但并未显示屏幕截图中所示的* Stock * iOS警报。 (3认同)
  • 我这样做了,因为此答案中的代码(虽然可能是不错的)并没有真正回答所提出的问题:在应用程序内显示** stock ** iOS Toast横幅。在SO上还有其他问题,那么这个答案将是很棒的。 (2认同)
  • 感谢 pkamb 的澄清,很有道理。我猜我错过了“股票”这个词。 (2认同)

Kav*_*gam 10

以下是在应用程序处于前台或开放阶段iOS 10和Swift 2.3时接收推送通知的代码

@available(iOS 10.0, *)
func userNotificationCenter(center: UNUserNotificationCenter, willPresentNotification notification: UNNotification, withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void)
{
     completionHandler([UNNotificationPresentationOptions.Alert,UNNotificationPresentationOptions.Sound,UNNotificationPresentationOptions.Badge])
}
Run Code Online (Sandbox Code Playgroud)

如果您需要访问userInfo的通知使用代码: notification.request.content.userInfo

userNotificationCenter(_:willPresent:withCompletionHandler:)只有在向属性有效负载添加时,才会调用该方法content-available:1.最终的有效载荷应该是这样的:

{
     "aps":{
          "alert":"Testing.. (7)",
          "badge":1,"sound":"default"
     },
     "content-available":1
}
Run Code Online (Sandbox Code Playgroud)

  • `userNotificationCenter(_:willPresent:withCompletionHandler:)` 将在您的应用程序在前台运行时被调用。所以它与“[content-available](https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html)”无关,它与“[background fetch](https://developer.apple.com/documentation/uikit/core_app/managing_your_app_s_life_cycle/preparing_your_app_to_run_in_the_background/updating_your_app_with_background_app_refresh)”。 (2认同)

小智 9

UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
content.body = body;
content.userInfo = userInfo;
content.sound = [UNNotificationSound defaultSound];
[content setValue:@(YES) forKeyPath:@"shouldAlwaysAlertWhileAppIsForeground"];

UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:@"Notif" content:content trigger:nil];
[[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
    DLog(@"Error:%@", error);
}];
Run Code Online (Sandbox Code Playgroud)

当应用程序处于iOS 10活动状态时,我可以显示推送通知.

  1. 来自服务器的推送通知应该是静默的.

  2. 从服务器接收远程通知时,您发送本地通知并设置keyPath的值:shouldAlwaysAlertWhileAppIsForeground = True


Mo *_*and 5

您可以自己处理通知并显示自定义警报.Viber,Whatsapp和BisPhone等应用程序都使用这种方法.

第三方自定义警报的一个示例是CRToast.

尝试在应用程序位于前台时安排本地通知,您将看到没有显示库存iOS警报:

if (application.applicationState == UIApplicationStateActive ) {
     UILocalNotification *localNotification = [[UILocalNotification alloc] init];
    localNotification.userInfo = userInfo;
    localNotification.soundName = UILocalNotificationDefaultSoundName;
    localNotification.alertBody = message;
    localNotification.fireDate = [NSDate date];
    [[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
}
Run Code Online (Sandbox Code Playgroud)

  • @matt我试图在主题上保留这个问题:在前台显示iOS库存信息.许多其他"最佳敬酒警报框架"问题.回答"不,你不能在前台展示iOS警报"是完全可以接受的,我将接受这个答案,直到这**在未来版本的iOS中可能. (5认同)

Les*_*win 5

斯威夫特3版本

当应用程序位于前台时,这会显示警报。

if #available(iOS 10.0, *)
{
    // need to setup the global notification delegate somewhere when your app starts
    //
    UNUserNotificationCenter.current().delegate = applicationDelegate

    // to show a message
    //
    let content = UNMutableNotificationContent()
    content.body = "MESSAGE"

    let request = UNNotificationRequest(identifier: "fred", content: content, trigger: nil)
    UNUserNotificationCenter.current().add(request)
    {
       error in // called when message has been sent

       debugPrint("Error: \(error)")
    }
}
Run Code Online (Sandbox Code Playgroud)

ApplicationDelegate 的实现UNUserNotificationCenterDelegate

@available(iOS 10.0, *)
public func userNotificationCenter(_ center : UNUserNotificationCenter, willPresent notification : UNNotification, withCompletionHandler completionHandler : @escaping (UNNotificationPresentationOptions) -> Void)
{
    completionHandler([.alert]) // only-always show the alert
}
Run Code Online (Sandbox Code Playgroud)