Firebase 消息传递方法 swizzling 不起作用

Posted

技术标签:

【中文标题】Firebase 消息传递方法 swizzling 不起作用【英文标题】:Firebase messaging method swizzling not working 【发布时间】:2016-12-01 03:03:22 【问题描述】:

您好,我正在实施 FCM(Fire base 云消息传递)。我已经让应用程序从 FCM 控制台接收通知和数据。我有我的服务器通知和 Firebase 通知。我想分别处理两种类型的通知(来自我的服务器和来自 FCM)。我已经浏览了文档,这可以通过在 AppDelegate 中调整通知处理程序来实现

但问题是我只能在

中获取FCM消息数据(ios 10)
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler 

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

FCM 委托的回调

// The callback to handle data message received via FCM for devices running iOS 10 or above.
- (void)applicationReceivedRemoteMessage:(nonnull FIRMessagingRemoteMessage *)remoteMessage 

    // Print full message
    NSLog(@"Can get here firebase?%@", [remoteMessage appData]);

上面的回调永远不会被调用

我们如何使用 swizzling 单独设置 FCM 处理程序消息?

这是我的 Appdelegate didfinishlaunchingwith 选项

    application.applicationIconBadgeNumber = 0;

    if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_9_x_Max) 
        UIUserNotificationType allNotificationTypes =
        (UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge);
        UIUserNotificationSettings *settings =
        [UIUserNotificationSettings settingsForTypes:allNotificationTypes categories:nil];
        [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
     else 
        // iOS 10 or later
#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
        UNAuthorizationOptions authOptions =
        UNAuthorizationOptionAlert
        | UNAuthorizationOptionSound
        | UNAuthorizationOptionBadge;
        [[UNUserNotificationCenter currentNotificationCenter]
         requestAuthorizationWithOptions:authOptions
         completionHandler:^(BOOL granted, NSError * _Nullable error) 
         
         ];

        // For iOS 10 display notification (sent via APNS)
        [[UNUserNotificationCenter currentNotificationCenter] setDelegate:self];
        // For iOS 10 data message (sent via FCM)

        [[FIRMessaging messaging] setRemoteMessageDelegate:self];
#endif
    

    [[UIApplication sharedApplication] registerForRemoteNotifications];

    // [START configure_firebase]
    [FIRApp configure];
    // [END configure_firebase]
    // Add observer for InstanceID token refresh callback.
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tokenRefreshNotification:)
                                                 name:kFIRInstanceIDTokenRefreshNotification object:nil];    

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.window.backgroundColor = [UIColor whiteColor];

    _rootViewController = [[RootViewController alloc] initWithNibName:nil bundle:nil];


    [self.window setRootViewController:_rootViewController];
    [self.window makeKeyAndVisible];

    NSDictionary *remoteNotification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
    if (remoteNotification)
        [self handleRemoteNotification:remoteNotification shouldPrompt:NO];

    self.isFirstTime = true;
    self.isJustForRefresh = 0;

    return YES;

有人知道如何让它工作吗?

编辑:这是我的观察者观察函数和didregisterRemoteNotification函数

// [START refresh_token]
- (void)tokenRefreshNotification:(NSNotification *)notification 
    // Note that this callback will be fired everytime a new token is generated, including the first
    // time. So if you need to retrieve the token as soon as it is available this is where that
    // should be done.
    NSString *refreshedToken = [[FIRInstanceID instanceID] token];
    NSLog(@"InstanceID token: %@", refreshedToken);

    // Connect to FCM since connection may have failed when attempted before having a token.
    [self connectToFcm];

    // TODO: If necessary send token to application server.

// [END refresh_token]

// [START connect_to_fcm]
- (void)connectToFcm 
    [[FIRMessaging messaging] connectWithCompletion:^(NSError * _Nullable error) 
        if (error != nil) 
            NSLog(@"Unable to connect to FCM. %@", error);
         else 
            NSLog(@"Connected to FCM.");
        
    ];

// [END connect_to_fcm]

- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken 
    NSString *sanitizedDeviceToken = [[[[deviceToken description]
                                        stringByReplacingOccurrencesOfString:@"<" withString:@""]
                                       stringByReplacingOccurrencesOfString:@">" withString:@""]
                                      stringByReplacingOccurrencesOfString:@" " withString:@""];

    DLog(@"sanitized device token: %@", sanitizedDeviceToken);
    [PushNotificationManager API_registerAPNSToken:sanitizedDeviceToken
                                      onCompletion:^(BOOL success, NSError *error)];

    [[FIRInstanceID instanceID]setAPNSToken:deviceToken type:FIRInstanceIDAPNSTokenTypeSandbox];


更新:我已包含此功能但仍无法正常工作

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
    if (userInfo[@"gcm.message_id"] != nil) 
        NSLog(@"Should get here FCM?");
        [[FIRMessaging messaging]appDidReceiveMessage:userInfo];
    else 
        NSLog(@"test fetchCompletion handler: %@",userInfo.description);
    


【问题讨论】:

你不应该使用 swizzling github.com/onmyway133/blog/issues/64 【参考方案1】:

你可以看看这个答案吗?好像漏了FIRMessaging.messaging().connect()....

https://***.com/a/40881754/1005570

还有委托函数..

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
             fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) 
// If you are receiving a notification message while your app is in the background,
// this callback will not be fired till the user taps on the notification launching the application.
// TODO: Handle data of notification

// Print message ID.
print("Message ID: \(userInfo["gcm.message_id"]!)")

// Print full message.
print(userInfo)

FIRMessaging.messaging().appDidReceiveMessage(userInfo)

【讨论】:

对不起,代码很快。但我认为你可以得到它。 您好,更新我已经连接到 FCM 的代码,可以收到通知,但我的问题是使用 swizzling 方法?分别处理 FCM 通知和我自己的服务器通知(现在一切都按照意愿呈现和接收) 和测试IOS 10 哦,我明白你的意思了。那么用你上面实现的代码,你能从你自己的服务器收到任何通知吗?所以您遇到的问题是 1. 从两个来源收到通知但无法将它们分开。或者 2. 只收到来自 FCM 的通知,而不是您自己的服务器。 嗨谢谢我的问题是第一个。我可以收到通知,但无法将它们分开,并且永远不会调用 FCM 委托函数

以上是关于Firebase 消息传递方法 swizzling 不起作用的主要内容,如果未能解决你的问题,请参考以下文章