푸시 알림에서 앱이 시작 / 열렸는지 감지


172

푸시 알림에서 앱이 시작 / 열렸는지 알 수 있습니까?

시작 이벤트가 여기에서 잡힐 수 있다고 생각합니다.

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

    if (launchOptions != nil) {
         // Launched from push notification
         NSDictionary *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];

    }
}

그러나 앱이 백그라운드에있을 때 푸시 알림에서 앱이 열려 있는지 어떻게 알 수 있습니까?


6
이것은 오래되었지만 매우 유용한 게시물입니다. 불행히도 최고 답변은 실제로 문제를 해결하지 못합니다 (의견에서 알 수 있듯이). 현재 답변이 완료되지 않았으므로 새 답변을 '수락 됨'으로 표시하십시오.
MobileVet

1
이 질문의 조회수는 100 만회 이상이지만 선택한 답변이 잘못되었거나 완료되었습니다. 방문자에게는 투표 대신 활성으로 정렬하여 최신 솔루션을 찾으십시오.
Albert Renshaw

답변:


187

이 코드를 참조하십시오 :

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
    if ( application.applicationState == UIApplicationStateInactive || application.applicationState == UIApplicationStateBackground  )
    {
         //opened from a push notification when the app was on background
    }
}

와 동일

-(void)application:(UIApplication *)application didReceiveLocalNotification (UILocalNotification *)notification

19
@ManuelM. 이것은 푸시 알림에서 백그라운드의 앱이 포 그라운드로 가져 오는 시점을 감지하는 방법을 보여주는 좋은 대답입니다. 앱이 실행되지 않는 경우 아래 M.Othman의 답변이 필요합니다.
OpenUserX03

6
응용 프로그램에 전화를 받고 있습니다 : didReceiveRemoteNotification : 응용 프로그램이 백그라운드에 있는지 여부에 관계없이 알림을 탭 한 후이 답변이 내 요구에 완벽하게 부합합니다. iOS 7 & 8에서 테스트
Newtz

16
다른 사람들이 지적했듯이 이것은 "푸시 알림에서 시작 / 열림"을 감지하지 못합니다. 알림이 열릴 때가 아니라 알림을받을 때 호출됩니다. 따라서 bg로 알림을 받았지만 앱 아이콘을 눌러 앱을 열면 여기에있는 코드가 계속 실행되며 사용자가 열지 않은 페이지를 열 수 있습니다.
Bao Lei

4
@ManuelM. 이 방법은 백그라운드 모드-원격 알림이 선택된 경우 알림 센터 대 앱 아이콘을 통해 앱이 열려 있는지 여부를 알려주지 않습니다. 선택을 해제하면됩니다. 이 게시물의 차이 문서화했습니다 stackoverflow.com/questions/32061897/...을
바오 레이에게

2
Google 클라우드 메시징에서 작동하는지 확인했습니다.
CularBytes

127

늦었지만 아마도 유용

앱이 실행되고 있지 않을 때

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

..

푸시 알림을 확인해야하는 곳

NSDictionary *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (notification) {
    NSLog(@"app recieved notification from remote%@",notification);
    [self application:application didReceiveRemoteNotification:notification];
} else {
    NSLog(@"app did not recieve notification");
}

2
위의 스 니펫에서 알림은 (UILocalNotification *)가 아니라 (NSDictionary *)
cosmix

1
이렇게하면 실행 중이 아닌 앱에 대한 알림이 있는지 확인할 수 있습니다! 문제는 앱이 알림에서 열렸는지 감지하는 방법이었습니다. 이 경우 앱이 전혀 실행되지 않은 경우에도 didReceiveRemoteNotification이 호출됩니다. -답변이 마음에 듭니다. 많은 경우에 중요하지만 질문에 대한 정답은 아닙니다.
Axel Zehden

귀하의 답변 과이 답변 모두 동일한 일을하고 있습니까?
Honey

38

우리가 겪었던 문제는 앱이 시작된 후 뷰를 올바르게 업데이트하는 것이 었습니다. 여기에는 복잡한 라이프 사이클 방법 시퀀스가 ​​혼동됩니다.

수명주기 방법

iOS 10 테스트에서 다양한 사례에 대해 다음과 같은 일련의 수명주기 방법이 밝혀졌습니다.

DELEGATE METHODS CALLED WHEN OPENING APP  

Opening app when system killed or user killed  
    didFinishLaunchingWithOptions  
    applicationDidBecomeActive    

Opening app when backgrounded  
    applicationWillEnterForeground  
    applicationDidBecomeActive  

DELEGATE METHODS WHEN OPENING PUSH

Opening push when system killed
    [receiving push causes didFinishLaunchingWithOptions (with options) and didReceiveRemoteNotification:background]
    applicationWillEnterForeground
    didReceiveRemoteNotification:inactive
    applicationDidBecomeActive

Opening push when user killed
    didFinishLaunchingWithOptions (with options)
    didReceiveRemoteNotification:inactive [only completionHandler version]
    applicationDidBecomeActive

Opening push when backgrounded
    [receiving push causes didReceiveRemoteNotification:background]
    applicationWillEnterForeground
    didReceiveRemoteNotification:inactive
    applicationDidBecomeActive

문제

이제 우리는 다음을 수행해야합니다.

  1. 사용자가 푸시에서 앱을 여는 지 확인
  2. 푸시 상태를 기반으로 뷰 업데이트
  3. 후속 열기가 사용자를 동일한 위치로 되 돌리지 않도록 상태를 지우십시오.

까다로운 점은 응용 프로그램이 실제로 활성화 될 때보기를 업데이트해야한다는 것입니다. 이는 모든 경우에 동일한 수명주기 방법입니다.

솔루션 스케치

솔루션의 주요 구성 요소는 다음과 같습니다.

  1. notificationUserInfoAppDelegate에 인스턴스 변수를 저장하십시오 .
  2. 설정 notificationUserInfo = nil모두 applicationWillEnterForegrounddidFinishLaunchingWithOptions.
  3. 설정 notificationUserInfo = userInfo에서didReceiveRemoteNotification:inactive
  4. 에서 applicationDidBecomeActive항상 사용자 정의 메소드를 호출 openViewFromNotification하고 전달하십시오 self.notificationUserInfo. self.notificationUserInfonil 인 경우 일찍 반환하고, 그렇지 않으면의 알림 상태에 따라보기를 엽니 다 self.notificationUserInfo.

설명

푸시에서 열거 didFinishLaunchingWithOptionsapplicationWillEnterForeground항상 바로 직전에 호출되면 먼저 didReceiveRemoteNotification:inactive이러한 메소드에서 notificationUserInfo를 재설정하여 오래된 상태가 없도록합니다. 그런 다음 didReceiveRemoteNotification:inactive호출 되면 푸시에서 여는 것을 알고 있으므로 사용자를 올바른 뷰로 전달하기 위해 self.notificationUserInfo선택합니다 applicationDidBecomeActive.

사용자가 앱 스위처 내에서 앱을 연 경우 (즉, 앱이 포 그라운드에있는 동안 홈 버튼을 두 번 두드리는 경우) 푸시 알림을받는 경우가 마지막입니다. 이 경우에만 didReceiveRemoteNotification:inactive호출되며 WillEnterForeground와 didFinishLaunching도 호출되지 않으므로 해당 상황을 처리하기 위해 특별한 상태가 필요합니다.

도움이 되었기를 바랍니다.


마지막으로 작동하는 무언가, 감사합니다! receive앱 상태가 활성화되어 있거나 앱이 다시 시작될 때 "appResuming"플래그를 생성하고 메서드 에서 화면을 열었습니다 . 앱이 여전히 비활성 상태 일 때 VC 변경에 문제가 발생할 수 있습니다. Apple이 수명주기를 다시 바꿀 때까지 솔루션이 멋지게 보입니다.
shelll

iOS 9의 수명주기 메소드는 동일한 방식과 순서로 호출됩니까? 이미 iOS 9 기기가 없으므로 제대로 테스트 할 수 없습니다.
shelll

2
앱 스위처를 제외한 두 가지 더 많은 경우가 있습니다. 1) 알림 센터를 상단에서 당겨서 앱을 오버레이하는 경우 2) wifi / BT / etc가있는 iOS 패널을 하단에서 당겨서 앱을 오버레이하는 경우. 세 가지 경우 모두을 applicationWillResignActive호출 한 다음을 호출합니다 applicationDidBecomeActive. 그래서 후 applicationWillResignActive때까지 수신 알림 저장하지 않습니다라고 applicationDidEnterBackgroundapplicationDidBecomeActive이라고합니다.
shelll

@shelll 사례를 추가해 주셔서 감사합니다. 항상 더 복잡해집니다! iOS9에 대해 잘 모르겠습니다. 나는 그들이 같다고 생각하는 것이 안전하지만 누가 알는지 말하고 싶습니다.
Eric Conner 17

그냥 머리 위로. 나는 오늘 iOS 11 Beta 9를 테스트하고 있었고 포 그라운드에 앱이 있고 전화를 잠근 다음 잠금 화면에서 푸시 알림을 선택하는 경우 applicationWillEnterForeground가 아닌 applicationWillEnterForeground를 호출하기 전에 didReceiveRemoteNotification : background를 호출한다는 것을 알았습니다. iOS 10에서 applicationWillEnterForeground를 호출 한 다음 didReceiveRemoteNotification : inactive를 호출하여보고있는 내용은 아직 다루지 않았습니다. 내 생각에 이것은 iOS 코드의 버그이지만 iOS 11 릴리스가 얼마나 가까이 있는지를 알고 있으면 알아야 할 것입니다.
Roy

24

이것은 잘 착용 된 게시물입니다 ...하지만 여전히 다양한 의견에서 지적한 것처럼 문제에 대한 실제 해결책 이 누락되었습니다 .

원래 질문은 푸시 알림에서 앱이 언제 시작 / 열렸 는지 감지하는 것입니다 ( 예 : 사용자가 알림을 탭함). 실제로이 사례에 대한 답변은 없습니다.

알림이 도착하면 통화 흐름에서 이유를 확인할 수 있습니다. application:didReceiveRemoteNotification...

통지가 수신 될 때 호출되는 통지는 사용자가 탭하면 다시. 이 때문에 UIApplicationState사용자가 탭을 보았을 때 알 수 없습니다 .

또한 iOS 9 이상 (아마도 8)에서 시작한 후 다시 호출 되는 application:didFinishLaunchingWithOptions...것처럼 앱의 '콜드 스타트'상황을 더 이상 처리 할 필요가 없습니다 application:didReceiveRemoteNotification....

그렇다면 사용자 탭이 이벤트 체인을 시작했는지 어떻게 알 수 있습니까? 내 해결책은 앱이 백그라운드 또는 콜드 스타트에서 나오기 시작하는 시간을 표시 한 다음 그 시간을 확인하는 것입니다 application:didReceiveRemoteNotification.... 0.1 초 미만이면 탭이 스타트 업을 트리거했는지 확인할 수 있습니다.

스위프트 2.x

class AppDelegate: UIResponder, UIApplicationDelegate {

  var wakeTime : NSDate = NSDate()        // when did our application wake up most recently?

  func applicationWillEnterForeground(application: UIApplication) {    
    // time stamp the entering of foreground so we can tell how we got here
    wakeTime = NSDate()
  }

  func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
    // ensure the userInfo dictionary has the data you expect
    if let type = userInfo["type"] as? String where type == "status" {
      // IF the wakeTime is less than 1/10 of a second, then we got here by tapping a notification
      if application.applicationState != UIApplicationState.Background && NSDate().timeIntervalSinceDate(wakeTime) < 0.1 {
        // User Tap on notification Started the App
      }
      else {
        // DO stuff here if you ONLY want it to happen when the push arrives
      }
      completionHandler(.NewData)
    }
    else {
      completionHandler(.NoData)
    }
  }
}

스위프트 3

class AppDelegate: UIResponder, UIApplicationDelegate {

    var wakeTime : Date = Date()        // when did our application wake up most recently?

    func applicationWillEnterForeground(_ application: UIApplication) {
      // time stamp the entering of foreground so we can tell how we got here
      wakeTime = Date()
    }

  func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {

      // ensure the userInfo dictionary has the data you expect
      if let type = userInfo["type"] as? String, type == "status" {
        // IF the wakeTime is less than 1/10 of a second, then we got here by tapping a notification
        if application.applicationState != UIApplicationState.background && Date().timeIntervalSince(wakeTime) < 0.1 {
          // User Tap on notification Started the App
        }
        else {
          // DO stuff here if you ONLY want it to happen when the push arrives
        }
        completionHandler(.newData)
      }
      else {
        completionHandler(.noData)
      }
    }
}

iOS 9 이상에서 두 가지 경우 (백그라운드의 앱, 실행되지 않는 앱)에 대해 이것을 테스트했으며 매력처럼 작동합니다. 0.1도 상당히 보수적이며 실제 값은 ~ 0.002s이므로 0.01도 좋습니다.


1
실제로 알림을 탭하는 것과 앱에서 상태 표시 줄을 여는 것을 구별하는 유일한 작동 솔루션 인 것으로 보입니다.
liviucmg

4
이것은 모든 StackOverflow에서 유일하게 작동하는 솔루션입니다. 내가 추가하고 싶은 유일한 것은 iOS 10 이상을 지원할 때 UNNotificationCenterAPI, 특히 UNNotificationCenterDelegate 메소드 를 사용할 수 있다는 것입니다. 이러한 API 호출 기능 userNotificationCenter(UNUserNotificationCenter, didReceive: UNNotificationResponse, withCompletionHandler: @escaping () -> Void) 은 사용자가 실제로 알림을 누른 경우에만 가능합니다.
DenHeadless

스위프트 3을 어떻게 찾습니까?
Jochen Österreicher

앱이 비활성 상태 인 경우 (사용자가 알림 센터를 아래로 스 와이프하거나 제어 센터를 스 와이프하면) 솔루션이 작동하지 않고 알림을받습니다. 사용자가 알림을 탭하면 앱이 applicationWillEnterForeground 전화를 받지 않으므로 솔루션에서 탭을 감지하지 못합니다.
DevGansta

@DevGansta UNUserNotificationCenter.current().delegate에서 application:didFinishLaunchingWithOptions와 같이 수업을 추가 userNotificationCenter(didReceive response)하면 설명 된 경우 탭 후 앱이 호출됩니다.
Dorian Roy

22

앱이 종료되고 사용자가 푸시 알림을 탭하면

public func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
   if launchOptions?[UIApplicationLaunchOptionsKey.remoteNotification] != nil {
      print("from push")
    }
}

앱이 백그라운드에 있고 사용자가 푸시 알림을 탭하면

사용자가 시스템 표시 알림에서 앱을 열면 앱이 포 그라운드로 진입하려고 할 때 시스템이이 메소드를 다시 호출 하여 사용자 인터페이스를 업데이트하고 알림과 관련된 정보를 표시 할 수 있습니다.

public func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
  if application.applicationState == .inactive {
    print("from push")
  }
}

앱에 따라 content-availableinside로 자동 푸시를 보낼 수도 aps있으므로 다음 사항도 알고 있어야합니다. https : //.com/a/33778990/1418457 참조


2
더러운 해킹처럼 느끼지 않는 대답 만하십시오. 내가 누락 된 것은 앱이 백그라운드에 있고 사용자가 수동으로 열면 어떻게 확인합니까? 여전히 푸시 콜드 스타트를 확인하고 배경에서 푸시 할 수 있습니다.
Jochen Österreicher

1
@ JochenÖsterreicher 안녕하세요, 여기에 요약 해주세요. medium.com/@onmyway133/…
onmyway133

19

'비 실행'상태의 Swift 2.0 (로컬 및 원격 알림)

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {


// Handle notification
if (launchOptions != nil) {

    // For local Notification
    if let localNotificationInfo = launchOptions?[UIApplicationLaunchOptionsLocalNotificationKey] as? UILocalNotification {

        if let something = localNotificationInfo.userInfo!["yourKey"] as? String {
            self.window!.rootViewController = UINavigationController(rootViewController: YourController(yourMember: something))
        }


    } else

    // For remote Notification
    if let remoteNotification = launchOptions?[UIApplicationLaunchOptionsRemoteNotificationKey] as! [NSObject : AnyObject]? {

        if let something = remoteNotification["yourKey"] as? String {
            self.window!.rootViewController = UINavigationController(rootViewController: YourController(yourMember: something))
        }
    }

}


return true
}

15

에서 application:didReceiveRemoteNotification:앱이 전경 또는 배경에있을 때 체크 당신은 통지를받은 여부.

백그라운드에서 수신 한 경우 알림에서 앱을 시작합니다.

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
    if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
        NSLog(@"Notification received by running app");
    } else {
        NSLog(@"App opened from Notification");
    }
}

3
사용자가 다른 화면에있는 동안 알림을 보내면 (예 : 상태 표시 줄을 아래로 내리고 앱에서 알림을받는 경우) "알림에서 열린 앱"은 오 탐지입니다.
Kevin Cooper

4
@Kevin 정확합니다. 애플이 왜 알림 처리 프로세스를 설계하는 인턴처럼 보이는지 궁금해합니다.
Andreas

활성 상태에서 수신 된 알림을 탭하면 어떻게 감지 할 수
있습니까

13

신속하게 :

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
    PFPush.handlePush(userInfo)

    if application.applicationState == UIApplicationState.Inactive || application.applicationState == UIApplicationState.Background {
        //opened from a push notification when the app was in the background

    }

}

4

예, appDelegate 에서이 방법으로 감지 할 수 있습니다 .

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
      /* your Code*/
}

현지 알림의 경우 :

- (void)application:(UIApplication *)application
didReceiveLocalNotification:(UILocalNotification *)notification
{
         /* your Code*/
}

1
앱이 실행되고 있지 않으면이 메소드가 호출되지 않습니다. 그게 무슨 여기 질문
Pfitz

내 문제는 알림을 처리하는 것이 아니라 배너를 클릭 할 때 (앱이 백그라운드에있을 때) 알림이 열렸는지 아는 것입니다.
joao

3

누군가 신속한 3에서 답을 원한다면

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
    switch application.applicationState {
    case .active:
        //app is currently active, can update badges count here
        break
    case .inactive:
        //app is transitioning from background to foreground (user taps notification), do what you need when user taps here
        break
    case .background:
        //app is in background, if content-available key of your notification is set to 1, poll to your backend to retrieve data and update your interface here
        break
    default:
        break
    }
}

응용 프로그램이 응용 프로그램이 종료 될 때 푸시 알림을 눌러 열려있는 경우 만 방법을 알고
user3804063

1
누군가가 푸시를 누르면 종료 여부에 관계없이 앱이 열립니다. 그리고 .inactive 경우는 호출
하미드 샤사 바리에게

1
푸시를

지역 알림은 어떻습니까?
Amir Shabani

3

Xamarin 사용자를 위해 게시

푸시 알림을 통해 앱이 시작되었는지 감지하는 핵심은 AppDelegate.FinishedLaunching(UIApplication app, NSDictionary options)메소드와 전달 된 옵션 사전입니다.

로컬 알림 인 경우 옵션 사전에이 키가 포함됩니다 UIApplication.LaunchOptionsLocalNotificationKey.

원격 알림 인 경우입니다 UIApplication.LaunchOptionsRemoteNotificationKey.

키가 LaunchOptionsLocalNotificationKey이면 객체의 유형이 UILocalNotification됩니다. 그런 다음 알림을보고 특정 알림을 확인할 수 있습니다.

전문가 팁 : UILocalNotification동일한 방식으로 식별자가 없습니다 UNNotificationRequest. 를 테스트 할 때 UILocalNotification논리를 기반으로 특정 requestId를 사용할 수 있도록 requestId를 포함하는 UserInfo에 사전 키를 넣 습니다.

iOS 10 이상 기기에서도 UNUserNotificationCenter' AddNotificationRequest&를 사용하여 위치 알림을 만들 UNMutableNotificationContent때 앱이 실행되고 있지 않을 때 (내가 죽었을 때) 알림 센터에서 알림을 눌러 시작하면 사전에 여전히 포함되어 있음을 알았습니다. UILocalNotificaiton객체입니다.

이는 알림 기반 실행을 확인하는 코드가 iOS8 및 iOS 10+ 기기에서 작동 함을 의미합니다

public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
    _logger.InfoFormat("FinishedLaunching");

    if(options != null)
    {
        if (options.ContainsKey(UIApplication.LaunchOptionsLocalNotificationKey))
        {
            //was started by tapping a local notification when app wasn't previously running.
            //works if using UNUserNotificationCenter.Current.AddNotificationRequest OR UIApplication.SharedApplication.PresentLocalNotificationNow);

            var localNotification = options[UIApplication.LaunchOptionsLocalNotificationKey] as UILocalNotification;

            //I would recommended a key such as this :
            var requestId = localNotification.UserInfo["RequestId"].ToString();
        }               
    }
    return true;
}

2

설명서에서 바로

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo:nil

앱이 실행 중이고 원격 알림을받는 경우 앱은이 메서드를 호출하여 알림을 처리합니다.

이 방법을 구현할 때는 알림을 사용하여 적절한 조치를 취해야합니다.

그리고 조금 후에

푸시 알림이 도착했을 때 앱이 실행되고 있지 않은 경우이 방법은 앱을 시작하고 시작 옵션 사전에 적절한 정보를 제공합니다.

앱은 해당 푸시 알림을 처리하기 위해이 메서드를 호출하지 않습니다.

대신에, 당신의 구현

application:willFinishLaunchingWithOptions:

또는

application:didFinishLaunchingWithOptions:

메소드는 푸시 알림 페이로드 데이터를 가져 와서 적절하게 응답해야합니다.


2

: 나는 내 자신의 사용을보다 정확하게 그것을 시각화하고 다른 모든 상태를 고려하는 내가 만든 상태 차트로 시작합니다 https://docs.google.com/spreadsheets/d/e/2PACX-1vSdKOgo_F1TZwGJBAED4C_7cml0bEATqeL3P9UKpBwASlT6ZkU3iLdZnOZoevkMzOeng7gs31IFhD-L/pubhtml ? gid = 0 & single = true

이 차트를 사용하면 거의 모든 사용 사례에서 작동하는 강력한 알림 처리 시스템을 개발하기 위해 실제로 필요한 것이 무엇인지 알 수 있습니다.

완벽한 솔루션 ↓

  • didReceiveRemoteNotification에 알림 페이로드 저장
  • applicationWillEnterForegrounddidFinishLaunchingWithOptions 에서 저장된 알림 지우기
  • 제어 센터 / 알림 센터가 당겨진 경우를 해결하기 위해 willResignActiveCalled 플래그를 사용하여 처음 에 false로 설정할 수 있습니다. applicationWillResignActive 메소드 에서 true 로 설정하십시오 .
  • 에서 didReceiveRemoteNotification의 방법, willResignActiveCalled이 거짓 인 경우에만 통지 (사용자 정보) 저장.
  • applicationDidEnterBackgroundapplicationDidBecomeActive 메소드 에서 willResignActiveCalled를 false 로 재설정하십시오 .

참고 : Eric의 답변에 대한 의견에는 비슷한 답변이 제안되지만, 상태 시트는 내 앱에서했던 것처럼 가능한 모든 시나리오를 찾는 데 도움이됩니다.

특정 사례를 처리하지 않으면 아래에서 전체 코드를 찾아 아래에 의견을 작성하십시오.

AppDelegate

class AppDelegate: UIResponder, UIApplicationDelegate {
  private var willResignActiveCalled = false

  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    NotificationUtils.shared.notification = nil
    return true
  }
  func applicationWillResignActive(_ application: UIApplication) {
    willResignActiveCalled = true
  }
  func applicationDidEnterBackground(_ application: UIApplication) {
    willResignActiveCalled = false
  }
  func applicationWillEnterForeground(_ application: UIApplication) {
    NotificationUtils.shared.notification = nil
  }
  func applicationDidBecomeActive(_ application: UIApplication) {
    willResignActiveCalled = false
    NotificationUtils.shared.performActionOnNotification()
  }
  func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    if !willResignActiveCalled { // Check if app is in inactive by app switcher, control center, or notification center
      NotificationUtils.shared.handleNotification(userInfo: userInfo)
    }
  }
}

NotificationUtils : 데이터베이스 (CoreData / Realm)를 처리하고 응용 프로그램의 다른 부분으로 이동하는 데 필요한 모든 코드를 작성하고 알림을받을 때 수행해야하는 다른 모든 작업을 수행 할 수 있습니다.

   class NotificationUtils {
  static let shared = NotificationUtils()
  private init() {}

  var notification : [AnyHashable: Any]?

  func handleNotification(userInfo : [AnyHashable: Any]){
    if UIApplication.shared.applicationState == UIApplicationState.active {
      self.notification = userInfo //Save Payload
      //Show inApp Alert/Banner/Action etc
      // perform immediate action on notification
    }
    else if UIApplication.shared.applicationState == UIApplicationState.inactive{
      self.notification = userInfo
    }
    else if UIApplication.shared.applicationState == UIApplicationState.background{
      //Process notification in background,
      // Update badges, save some data received from notification payload in Databases (CoreData/Realm)
    }
  }

  func performActionOnNotification(){
    // Do all the stuffs like navigating to ViewControllers, updating Badges etc
    defer {
      notification = nil
    }
  }
}

이것이 답변이 아니기 때문에 이것을 주석으로 넣는 것이 좋습니다.
매디

제안에 대한 @Maddy 덕분에, 모든 세부 사항과 대답 업데이트
체탄 아난드

1
func application(_ application: UIApplication, didReceiveRemoteNotification data: [AnyHashable : Any]) {
    print("Push notification received: \(data)")

    if let info = data["aps"] as? Dictionary<String, AnyObject> {
        let alertMsg = info["alert"] as! String
        print(alertMsg)
        switch application.applicationState {
        case .active:
            print("do stuff in case App is active")
        case .background:
            print("do stuff in case App is in background")
           // navigateToChatDetailViewControler(pushdata: data)
        case .inactive:
            print("do stuff in case App is inactive")
            // navigateToChatDetailViewControler(pushdata: data)
        }
    }
}

1

신뢰할 수있는 방법은 하나 뿐이며 iOS 10 이상 에서만 작동합니다 .

UNUserNotificationCenter구현 UNUserNotificationCenterDelegate방법 사용 :

- (void) userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler {

    //Here you can get your original push if you need to
    NSDictionary* pusDict = response.notification.request.content.userInfo;

    if ([response.actionIdentifier isEqualToString: UNNotificationDefaultActionIdentifier]) {
        //User tapped the notification
    } else if ([response.actionIdentifier isEqualToString: UNNotificationDismissActionIdentifier]) {
        //User dismissed the notification 
    } else if ([response.actionIdentifier isEqualToString: MYCustomActionId]) {
        //User chose my custom defined action
    }
    ...
}

0

당신이 사용할 수있는:

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo

원격 푸시 알림을 처리합니다.

여기 문서를 확인하십시오



0
     // shanegao's code in Swift 2.0
     func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject])
    {
            if ( application.applicationState == UIApplicationState.Inactive || application.applicationState == UIApplicationState.Background ){
                    print("opened from a push notification when the app was on background")
            }else{
                    print("opened from a push notification when the app was on foreground")
            }
    }

그러나 앱이 닫히면 어떻게 될까요? 트위터 나 인스 타 그램처럼 그것은 어떻게 든 그것을 감지하고 심지어 앱이 닫히면 새로운 게시물이나 사진 또는 프로필 등으로 리디렉션됩니다.
Tarvo Mäesepp

0

이 질문의 문제점은 앱을 "열기"가 잘 정의되어 있지 않다는 것입니다. 앱이 실행 중이 아닌 상태에서 콜드 시작되거나 비활성 상태 (예 : 다른 앱에서 다시 전환)로 다시 활성화되었습니다. 가능한 모든 상태를 구별하는 솔루션은 다음과 같습니다.

typedef NS_ENUM(NSInteger, MXAppState) {
    MXAppStateActive = 0,
    MXAppStateReactivated = 1,
    MXAppStateLaunched = 2
};

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // ... your custom launch stuff
    [[MXDefaults instance] setDateOfLastLaunch:[NSDate date]];
    // ... more custom launch stuff
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    // Through a lot of trial and error (by showing alerts), I can confirm that on iOS 10
    // this method is only called when the app has been launched from a push notification
    // or when the app is already in the Active state.  When you receive a push
    // and then launch the app from the icon or apps view, this method is _not_ called.
    // So with 99% confidence, it means this method is called in one of the 3 mutually exclusive cases
    //    1) we are active in the foreground, no action was taken by the user
    //    2) we were 'launched' from an inactive state (so we may already be in the main section) by a tap
    //       on a push notification
    //    3) we were truly launched from a not running state by a tap on a push notification
    // Beware that cases (2) and (3) may both show UIApplicationStateInactive and cant be easily distinguished.
    // We check the last launch date to distinguish (2) and (3).

    MXAppState appState = [self mxAppStateFromApplicationState:[application applicationState]];
    //... your app's logic
}

- (MXAppState)mxAppStateFromApplicationState:(UIApplicationState)state {
    if (state == UIApplicationStateActive) {
        return MXAppStateActive;
    } else {
        NSDate* lastLaunchDate = [[MXDefaults instance] dateOfLastLaunch];
        if (lastLaunchDate && [[NSDate date] timeIntervalSinceDate:lastLaunchDate] < 0.5f) {
            return MXAppStateLaunched;
        } else {
            return MXAppStateReactivated;
        }
    }
    return MXAppStateActive;
}

MXDefaults대한 작은 래퍼입니다 NSUserDefaults.


0

에 대한 swift

 func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]){

    ++notificationNumber
    application.applicationIconBadgeNumber =  notificationNumber;

    if let aps = userInfo["aps"] as? NSDictionary {

        var message = aps["alert"]
        println("my messages : \(message)")

    }
}

0

Xcode 10 스위프트 4.2

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {

    let state : UIApplicationState = application.applicationState
    if (state == .Inactive || state == .Background) {
        // coming from background
    } else {
        // App is running in foreground
    }
}

0

iOS 10+의 경우이 상태를 사용하여 앱 상태에 관계없이 알림을 클릭 한시기를 알 수 있습니다.

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {

    //Notification clicked
    completionHandler()
}

0

M.Othman의 대답은 포함하지 않는 애플 리케이션을위한 올바른 장면 대리자를 들어 장면 위임 앱 이 나를 위해 일 아이폰 OS (13)

다음은 코드를 작성하여 장면을 연결합니다.

if connectionOptions.notificationResponse == nil { 
//Not opened from push notification
} else {
  //Opened from push notification
}

이전 버전을 지원하기위한 앱 대리자를위한 코드 didFinishLaunchingWithOptions

let notification = launchOptions?[UIApplication.LaunchOptionsKey.remoteNotification]
        if (notification != nil) {

            //Launched from push notification
        } else {

            //Launch from other source
        }

-1

스위프트 사용자 :

푸시 또는 이와 유사한 방식으로 열 때 다른 페이지를 시작하려면 다음과 didFinishLaunchingWithOptions같이 확인해야합니다 .

let directVc: directVC! = directVC(nibName:"directVC", bundle: nil)
let pushVc: pushVC! = pushVC(nibName:"pushVC", bundle: nil)

if let remoteNotification = launchOptions?[UIApplicationLaunchOptionsRemoteNotificationKey] as? NSDictionary {
     self.navigationController = UINavigationController(rootViewController: pushVc!)
} else {
     self.navigationController = UINavigationController(rootViewController: directVc!)
}
self.window!.rootViewController = self.navigationController

위임에는 멤버있는 navigationController이 없습니다
파블로 Cegarra에게

1
AppDelegate.h 파일에서 탐색 컨트롤러를 만듭니다. 사용 중이며 작동합니다!
AAA

-1

신속하게 :

푸시 알림 (백그라운드 페치 포함)을 실행 중입니다. 내 앱이 백그라운드에 있고 푸시 알림을 받으면 appDelegate의 didReceiveRemoteNotification이 두 번 호출됩니다. 한 번은 알림이 수신되고 다른 하나는 사용자가 알림 알림을 클릭 할 때입니다.

알림 경고가 클릭되었는지 감지하려면 appDelegate의 didReceiveRemoteNotification 내부에서 applicationState raw value == 1인지 확인하십시오.

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject: AnyObject]) {
    // If not from alert click applicationState(1)
    if (application.applicationState.rawValue != 1) {
        // Run your code here
    }
}

이게 도움이 되길 바란다.


-1

앱이 shanegao백그라운드에 있으면 사용할 수 있습니다

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
    if ( application.applicationState == UIApplicationStateInactive || application.applicationState == UIApplicationStateBackground  )
    {
         //opened from a push notification when the app was on background
    }
}

그러나 응용 프로그램을 시작하고 응용 프로그램을 닫고 응용 프로그램을 디버깅하려는 경우 구성표 편집으로 이동하고 왼쪽 메뉴에서 실행 을 선택한 다음 시작에서 실행 파일이 실행될 때까지 기다린 다음 응용 프로그램을 시작할 때 응용 프로그램을 시작할 수 있습니다 푸시 알림을 클릭하십시오

구성표 편집> 실행> 실행 파일 시작 대기

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.