如何将 PushKit 的完成处理程序用于 reportNewIncomingCallWithUUID

How to use completion handler of PushKit for reportNewIncomingCallWithUUID

我正在为我的应用程序使用 CallKit。

- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(NSString *)type withCompletionHandler:(nonnull void (^)(void))completion
{
    NSDictionary *payloadDict = payload.dictionaryPayload[@"aps"];           

    [self reportIncomingCallFrom:callerName withUUID:self.uuidCallkit completion:^(NSError * _Nullable error) {

    }];
    if (completion) {
        completion();
    }
}

我的问题是:是写if completion then call completion,还是直接调用completion();?那么哪一个是正确的?

- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(NSString *)type withCompletionHandler:(nonnull void (^)(void))completion
{
    NSDictionary *payloadDict = payload.dictionaryPayload[@"aps"];           

    [self reportIncomingCallFrom:callerName withUUID:self.uuidCallkit completion:^(NSError * _Nullable error) {

    }];

    completion();
}

这是来电上报方法

- (void)reportIncomingCallFrom:(NSString *) from withUUID:(NSUUID *)uuid completion:(nullable void (^)(NSError *_Nullable error))completion
{
    CXHandle *callHandle = [[CXHandle alloc] initWithType:CXHandleTypeGeneric value:from];
    CXCallUpdate *callUpdate = [[CXCallUpdate alloc] init];

    callUpdate.remoteHandle = callHandle;
    callUpdate.supportsDTMF = YES;
    callUpdate.supportsHolding = NO;
    callUpdate.supportsGrouping = NO;
    callUpdate.supportsUngrouping = NO;
    callUpdate.hasVideo = NO;

    NSLog(@"income uuid here for income call %@",uuid);

    [self.callKitProvider reportNewIncomingCallWithUUID: uuid update:callUpdate completion:^(NSError *error) {
        if (!error) {
            NSLog(@"Incoming call successfully reported.");
        } else {
            NSLog(@"Failed to report incoming call successfully: %@.", [error localizedDescription]);
        }

        completion(error);
    }];
}

有时我在后台收不到推送。

我想知道我上面的方法是否正确。

这种情况下,直接调用completion()或者之前检查是否不是nil,是等价的,因为completion已经声明为nonnull.

所以,你可以直接打电话给 completion(),如果你有问题,那不是因为那个。

虽然检查 completion() 并不重要,因为它是 nonnull - 我发现代码存在另一个问题,可能导致 VOIP 推送未传送。

您应该从 CallKit 提供程序完成块内部调用 completion()。这会通知系统您已完成 VOIP 推送处理并调用了 CallKit。

但是,您通过通知 CallKit 异步调用它,因此当您内部有多个 NSLog() 调用时,可能会出现竞争条件。如果您在通知 CallKit 有来电之前调用推送处理完成块 - 从 iOS 13 开始,系统很可能会终止您的应用程序。

正确的方法如下:

- (void)pushRegistry:(PKPushRegistry *)registry  didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(NSString *)type withCompletionHandler:(nonnull void (^)(void))completion
{

    NSDictionary *payloadDict = payload.dictionaryPayload[@"aps"];           

    [self reportIncomingCallFrom:callerName withUUID:self.uuidCallkit completion:^(NSError * _Nullable error) {
        
        completion();

    }];

}

我还会在调用完成块后将调用移至 NSLog()