Hiển thị biểu ngữ thông báo iOS có sẵn khi ứng dụng của bạn đang mở và ở nền trước?


123

Khi ứng dụng Tin nhắn iOS chính thức của Apple được mở và ở phía trước, các tin nhắn mới từ các liên hệ khác sẽ kích hoạt biểu ngữ cảnh báo thông báo iOS gốc. Xem hình ảnh bên dưới.

Điều này có khả thi trong các ứng dụng của bên thứ 3 trên App Store không? Thông báo cục bộ và / hoặc Đẩy cho ứng dụng của bạn trong khi ứng dụng của bạn đang mở và ở nền trước ?

Khi kiểm tra ứng dụng của tôi , thông báo sẽ nhận được nhưng không có giao diện người dùng cảnh báo iOS nào được hiển thị .

Nhưng hành vi này được thấy trong ứng dụng Tin nhắn chính thức của Apple:

Tin nhắn đang mở và ở phía trước.  Vẫn hiển thị cảnh báo thông báo.

Các lập trình thông báo địa phương và từ xa Hướng dẫn nói:

Khi hệ điều hành gửi thông báo cục bộ hoặc thông báo từ xa và ứng dụng mục tiêu không chạy ở nền trước , nó có thể hiển thị thông báo cho người dùng thông qua cảnh báo , số huy hiệu biểu tượng hoặc âm thanh.

Nếu ứng dụng đang chạy trong nền khi thông báo được gửi, người ủy quyền ứng dụng sẽ nhận được thông báo cục bộ hoặc từ xa.

Vì vậy, có, chúng tôi có thể nhận được dữ liệu thông báo khi ở phía trước. Nhưng tôi không thấy cách nào để hiển thị giao diện người dùng cảnh báo thông báo iOS gốc .

-(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]
}

Sau đó, Tin nhắn có sử dụng API riêng để hiển thị cảnh báo khi ở nền trước không?

Đối với mục đích của câu hỏi này, vui lòng không đề xuất bất kỳ cảnh báo bật lên "bánh mì nướng" nào của bên thứ ba trên github hoặc v.v. Tôi chỉ quan tâm nếu điều này có thể được thực hiện bằng giao diện người dùng cảnh báo có sẵn , iOS bản địa hoặc Thông báo đẩy trong khi của bạn ứng dụng đang mở và ở phía trước .

Câu trả lời:


152

iOS 10 thêm UNUserNotificationCenterDelegategiao thức để xử lý thông báo khi ứng dụng của bạn đang ở chế độ nền.

Các UNUserNotificationCenterDelegategiao thức định nghĩa các phương pháp để nhận thông báo và xử lý hành động. Khi ứng dụng của bạn ở chế độ nền trước, các thông báo đến sẽ được gửi đến đối tượng ủy quyền của bạn thay vì hiển thị tự động bằng giao diện hệ thống.

Nhanh:

optional func userNotificationCenter(_ center: UNUserNotificationCenter, 
                     willPresent notification: UNNotification, 
      withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void)

Mục tiêu-C:

- (void)userNotificationCenter:(UNUserNotificationCenter *)center 
       willPresentNotification:(UNNotification *)notification 
         withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler;

Các cờ UNNotificationPresentationOptions cho phép bạn chỉ định UNNotificationPresentationOptionAlertđể hiển thị cảnh báo bằng cách sử dụng văn bản được cung cấp bởi thông báo.

Đây là chìa khóa vì nó cho phép bạn hiển thị cảnh báo trong khi ứng dụng của bạn đang mở và ở nền trước , tính năng này mới cho iOS 10.


Mã mẫu:

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)
    }
    
}

4
Bạn có thể cung cấp một mẫu mã làm việc trong đó hệ thống hiển thị thông báo nền trước đến như thể ứng dụng ở đó nền không?
azmeuk

1
@azmeuk Kiểm tra câu trả lời của tôi ...
chengsam

8
Đừng quên thêm UNUserNotificationCenter.current().delegate = selfvào application(_:willFinishLaunchingWithOptions:)hoặc application(_:didFinishLaunchingWithOptions:)phương thức
Deniss Fedotovs

3
Ngoài ra, hãy đảm bảo rằng bạn không đặt thiết bị của mình ở chế độ Không làm phiền nếu không, các thông báo sẽ hiển thị trong Trung tâm thông báo, nhưng sẽ không hiển thị ở nền trước trên ứng dụng của bạn
Jadent

2
2 xu của tôi: đừng bỏ lỡ: nhập Thông báo Người dùng. !
ingconti

94

Để hiển thị thông báo biểu ngữ khi ứng dụng ở nền trước, hãy sử dụng phương pháp sau.

iOS 10+, Swift 3+ :

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

1
Chà, ở mọi nơi tôi đọc mọi người nói rằng điều này là không thể. Tôi rất vui vì tôi đã tìm thấy câu trả lời này, nó hoạt động chính xác như tôi mong đợi! Khi ứng dụng đang chạy, các thông báo đẩy giờ đây hiển thị chính xác như chúng sẽ hiển thị nếu ứng dụng ở chế độ nền. Cảm ơn bạn!
Torre Lasley

1
Đoạn mã này đi đâu? Trong appDelegate hay ở một nơi nào khác?
Yoav R.

@YoavR. AppDelegate
chengsam

Tôi đã sử dụng cùng một mã. Nhưng tôi không biết tại sao thông báo không hiển thị khi ứng dụng ở nền trước.
Boominadha Prakash M

2
Chengsam bạn có thể muốn sửa điều này: Nó không cần phải được đặt trong AppDelegate. Nó phải được đặt cho bất kỳ đối tượng nào phù hợp UNUserNotificationCenterDelegate. Điều đó đã nói rằng hầu hết các nhà phát triển đều AppDelegatetuân theo UNUserNotificationCenterDelegate. @YoavR.
Honey,

16

BIÊN TẬP:

Cảnh báo tiền cảnh hiện có thể thực hiện được trong iOS 10! Hãy xem câu trả lời này .

Đối với iOS 9 trở xuống:

Dường như không thể hiển thị cảnh báo thông báo iOS stock khi ứng dụng của bạn đang mở và ở nền trước. Messages.app phải sử dụng API riêng tư.

Hệ thống không hiển thị bất kỳ cảnh báo nào, huy hiệu biểu tượng của ứng dụng hoặc phát bất kỳ âm thanh nào khi ứng dụng đã ở trên cùng. - Tài liệu UILocalNotification

Các UIApplicationDelegatephương thức sẽ vẫn được gọi, cho phép ứng dụng của bạn phản hồi thông báo cục bộ hoặc từ xa:

application:didReceiveLocalNotification:
application:didReceiveRemoteNotification:

Tuy nhiên, giao diện người dùng biểu ngữ cảnh báo thông báo iOS gốc sẽ không được hiển thị như trong ứng dụng Messages.app của Apple, phải sử dụng API riêng tư.

Điều tốt nhất bạn có thể làm là cuộn biểu ngữ cảnh báo của riêng bạn hoặc sử dụng một khuôn khổ hiện có:

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

Tôi đã mở một radar cho hành vi này ở đây: rdar://22313177


3
Vậy whatsapp và các ứng dụng nổi tiếng khác làm được điều đó như thế nào?
Machado

@tardoandre có ảnh chụp màn hình không? Tôi cho rằng đó là bằng cách bắt chước cảnh báo iOS stock theo quan điểm của riêng họ.
pkamb

2
Bạn nên bao gồm liên kết toastAlertFromGithubnếu bạn đang đề xuất thư viện của bên thứ ba này để sử dụng!
Ketan Parmar

14

Để hiển thị thông báo trong khi Ứng dụng đang mở, chúng ta cần xử lý thủ công. Vì vậy, những gì tôi đang làm bên dưới là xử lý thông báo sau khi nhận được.

Thêm tất cả bên dưới trong AppDelegate.m

  1. Xử lý cuộc gọi để thông báo
  2. Tạo chế độ xem, thêm AppIcon, thông báo Thông báo và hiển thị nó dưới dạng hoạt ảnh
  3. Thêm Trình chỉnh sửa cảm ứng để xóa nếu chạm vào hoặc xóa trong 5 giây với hoạt ảnh.

Hãy cho tôi biết nếu đây là một giải pháp ok. Làm việc tốt cho tôi nhưng không chắc liệu đây có phải là cách đúng hay không.

- (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) {


}];


}

3
Đây có thể là câu trả lời tốt cho việc tạo ra cảnh báo riêng của bạn, nhưng nó không hiển thị các Cổ iOS Alert như trong ảnh chụp màn hình.
pkamb

Xin chào, Cảm ơn vì những lời tốt đẹp của bạn. Có, nó sẽ không giống như vậy (nếu bạn đang nói về sự xuất hiện) vì cái được hiển thị ở trên trong hình ảnh là thông báo iOS và thông báo qua mã là tùy chỉnh. Chúng ta có thể tái tạo các giao diện trong khung nhìn. Tôi nghĩ rằng WhatsApp có một nhìn gọn gàng với nền mờ, vv
Hafeez

1
Có người xuống bình chọn :( Sẽ được tốt đẹp để nghe tại sao Cảm ơn.!?..
Hafeez

2
Tôi đã làm, vì mã trong câu trả lời này (mặc dù nó có thể tốt) không thực sự trả lời câu hỏi được hỏi: hiển thị biểu ngữ bánh mì nướng iOS cổ phiếu bên trong ứng dụng. Có những câu hỏi khác trên SO mà câu trả lời này sẽ là tuyệt vời.
pkamb

1
Cảm ơn pkamb đã làm rõ, có ý nghĩa. Tôi đoán là từ "chứng khoán".
Hafeez

10

Đây là mã để nhận Thông báo đẩy khi ứng dụng ở nền trước hoặc ở giai đoạn mở, 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])
}

Nếu bạn cần truy cập userInfo của mã sử dụng thông báo: notification.request.content.userInfo

Phương thức userNotificationCenter(_:willPresent:withCompletionHandler:)chỉ được gọi nếu bạn thêm vào thuộc tính payload content-available:1. Tải trọng cuối cùng phải là một cái gì đó như:

{
     "aps":{
          "alert":"Testing.. (7)",
          "badge":1,"sound":"default"
     },
     "content-available":1
}

1
userNotificationCenter(_:willPresent:withCompletionHandler:)sẽ được gọi khi ứng dụng của bạn đang chạy ở nền trước. Vì vậy, nó KHÔNG thành vấn đề với " nội dung có sẵn ", liên quan đến " tìm nạp nền ".
DawnSong

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);
}];

Tôi có thể hiển thị thông báo đẩy khi ứng dụng đang hoạt động cho iOS 10.

  1. Thông báo đẩy từ máy chủ phải im lặng .

  2. Khi nhận được thông báo từ xa từ máy chủ, bạn gửi thông báo cục bộ và đặt giá trị cho keyPath: shouldAlwaysAlertWhileAppIsForeground = True


trong nhanh chóng 2 - nó là content.setValue("YES", forKeyPath: "shouldAlwaysAlertWhileAppIsForeground"), phải không? (với "Có" và không đúng)
Yoav R.

Thận trọng: Điều này sẽ làm hỏng ứng dụng của bạn trong iOS 12. Xem thảo luận tại đây: stackoverflow.com/questions/41373321/…
Matt Bearson 18/09/18

5

Bạn có thể tự xử lý thông báo và hiển thị cảnh báo tùy chỉnh. Các ứng dụng như Viber, Whatsapp và BisPhone sử dụng phương pháp này.

Một ví dụ về cảnh báo tùy chỉnh của bên thứ 3 là CRToast .

Hãy thử lên lịch thông báo cục bộ trong khi ứng dụng của bạn ở nền trước và bạn sẽ thấy rằng không có cảnh báo iOS còn hàng nào được hiển thị:

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];
}

Cảm ơn, nhưng tôi chỉ đang tìm kiếm câu trả lời bằng cách sử dụng cảnh báo thông báo iOS stock.
pkamb

1
được nhưng tôi nghĩ bạn không thể làm được, hãy xem thêm Liên kết này: stackoverflow.com/questions/14872088/…
Mo Farhand

6
@matt Tôi đang cố gắng đưa câu hỏi này vào chủ đề: hiển thị cảnh báo iOS stock ở phía trước. Rất nhiều câu hỏi khác về "khung cảnh báo bánh mì nướng tốt nhất". Một câu trả lời của "Không, bạn không thể hiển thị các cảnh báo iOS trong foreground" sẽ được hoàn toàn chấp nhận được, và tôi sẽ chấp nhận câu trả lời đó cho đến khi này có thể trong một phiên bản tương lai của iOS.
pkamb

4

Phiên bản Swift 3

Điều này cho thấy một cảnh báo khi ứng dụng ở nền trước.

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)")
    }
}

ApplicationDelegate's triển khai 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
}

chỉ để chắc chắn ... ý bạn là kể từ iOS 10, giờ đây bạn cũng có thể hiển thị cảnh báo / biểu ngữ / âm thanh ở phía trước giống như khi bạn làm trong nền?
Honey,

Tôi có thể đặt phần viết mã trên ở đâu? có nhận được không?
user1960169

@Leslie Godwin nó sẽ làm việc cho ios 8.0 cho hiển thị thông báo trong Foreground
Dilip Tiwari

2

Để hiển thị Thông báo cục bộ, đây là tùy chọn tốt nhất. cần ít mã hơn để viết "BRYXBanner" https://cocoapods.org/pods/BRYXBanner

let banner = Banner(title: "title", subtitle: "subtitle", image: UIImage(named: "addContact"), backgroundColor: UIColor(red:137.0/255.0, green:172.0/255.0, blue:2.0/255.0, alpha:1.000))
    banner.dismissesOnTap = true
    banner.show(duration: 1.0)

Đây BRYXBannerkhuôn khổ dường như không sử dụng các chứng khoán thông báo biểu ngữ iOS.
pkamb

1

Nếu mục tiêu triển khai của bạn> = iOS10, hãy sử dụng UNUserNotification như bên dưới-

func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent notification: UNNotification,
                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void)
    {
        // Change this to your preferred presentation option
        completionHandler([.alert, .sound])
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.