Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/228.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 等待DidFinishLaunchingWith Options中的服务操作,并在延迟后调用DidRegisterForRemotionTificationsWith DeviceToken_Ios_Grand Central Dispatch_Appdelegate - Fatal编程技术网

Ios 等待DidFinishLaunchingWith Options中的服务操作,并在延迟后调用DidRegisterForRemotionTificationsWith DeviceToken

Ios 等待DidFinishLaunchingWith Options中的服务操作,并在延迟后调用DidRegisterForRemotionTificationsWith DeviceToken,ios,grand-central-dispatch,appdelegate,Ios,Grand Central Dispatch,Appdelegate,我不确定我的问题到底适合哪里。问题是: 我希望在应用程序启动时注册推送通知。我正在AppDelegate中注册的已使用选项完成启动 sem = dispatch_semaphore_create(0); [manager registerForPushNotifications]; dispatch_semaphore_signal(sem); dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); 如果我没有使用GCD,返回YES,在这种情

我不确定我的问题到底适合哪里。问题是:
我希望在应用程序启动时注册推送通知。我正在AppDelegate
中注册的已使用选项完成启动

sem = dispatch_semaphore_create(0);
[manager registerForPushNotifications];
dispatch_semaphore_signal(sem);
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); 
如果我没有使用
GCD
返回YESdidFinishLaunchingWithOptions
的code>,在这种情况下,不调用my my service方法,该方法要从
DidRegisterForRemotionTificationsSwithDeviceToken
调用以发送设备令牌

// system push notification registration success callback, delegate to pushManager
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    NSString *token = [[deviceToken description] stringByTrimmingCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:@"<>"]];
    token = [token stringByReplacingOccurrencesOfString:@" " withString:@""];
    NSLog(@"content---%@", token);
    [[NSUserDefaults standardUserDefaults]setObject:token forKey:@"deviceToken"];
    [self registerForPushWooshNotification];
    [[PushNotificationManager pushManager] handlePushRegistration:deviceToken];
}  

-(void)registerForPushWooshNotification
{
    NSDictionary *params = @{@"TokenId": [[NSUserDefaults standardUserDefaults]objectForKey:@"deviceToken"]
                             };

    [_sharedHandler.requestManager POST:TGURL_PUSHWOOSH_NOTIFICATION
                             parameters:params
                                success:^(AFHTTPRequestOperation *operation, id responseObject) {

                                    NSError *e;
                                    NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:[operation.responseString dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers error:&e];
                                    NSLog(@"------ Registered for Pushwoosh ------");
                                }
                                failure:^(AFHTTPRequestOperation *operation, NSError *error) {

                                }];
}  
//系统推送通知注册成功回调,委托给pushManager
-(无效)应用程序:(UIApplication*)应用程序DIdRegisterForRemotionTificationswithDeviceToken:(NSData*)deviceToken{
NSString*标记=[[deviceToken description]stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@”“];
token=[token StringByReplacingOfString:@“with String:@]”的发生率;
NSLog(@“内容-%@”,令牌);
[[NSUserDefaults standardUserDefaults]setObject:token forKey:@“deviceToken”];
[自注册形式通知];
[[PushNotificationManager pushManager]handlePushRegistration:deviceToken];
}  
-(无效)登记人登记通知
{
NSDictionary*params=@{@“TokenId”:[[NSUserDefaults standardUserDefaults]objectForKey:@“deviceToken”]
};
[\u sharedHandler.requestManager POST:TGURL\u PUSHWOOSH\u通知
参数:params
成功:^(AFHTTPRequestOperation*操作,id响应对象){
n错误*e;
NSDictionary*jsonDict=[NSJSONSerialization JSONObjectWithData:[operation.responseString数据使用编码:NSUTF8StringEncoding]选项:NSJSONReadingMutableContainers错误:&e];
NSLog(@“-----注册为Pushwoosh------”;
}
失败:^(AFHTTPRequestOperation*操作,NSError*错误){
}];
}  
但是,由于我已经实现了
GCD
didRegisterForRemoteNotificationsWithDeviceToken
从未被调用

摘要

1。我必须在应用程序启动时注册应用程序。
2.需要在应用程序启动时调用Web服务。
3.如果未使用GCD:返回是;首先调用,并且在延迟后调用DidRegisterForRemomentNotificationsWithDeviceToken。
4.如果使用了GCD:从不调用didRegisterForRemoteNotificationsWithDeviceToken。


在发布此问题之前,我在google上搜索了和,但没有成功。

这里的问题是,通过等待信号量,您正在阻止主线程,并且您希望稍后发生的回调将在主线程上传递。因为您正在阻塞主线程,所以回调永远不会发生。如果你想让你的应用程序在收到回调之前不做任何事情,你必须用另一种方式进行设置

从哲学上讲,最接近您现在拥有的解决方案是在等待回调的同时旋转主运行循环,但是有许多不同的方法可以做到这一点,而这可能不是我会选择的方法。也就是说,如果你想这样做,它可能看起来像这样:

@implementation AppDelegate
{
    BOOL didRegisterCalled;
    NSData* token;
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [application registerForRemoteNotifications];

    NSLog(@"registerForRemoteNotifications called. waiting for callback.");

    while (!didRegisterCalled)
    {
        [[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate: [NSDate date]];
    }

    NSLog(@"Register call back happened, and execution resumed");

    return YES;
}

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    didRegisterCalled = YES;
    token = [deviceToken copy];
}

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
    didRegisterCalled = YES;
    token = nil;
}

@end
@implementation AppDelegate
{
    BOOL didRegisterCalled;
    NSData* token;
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    NSLog(@"Calling registerForRemoteNotifications and deferring the rest of app startup.");
    [application registerForRemoteNotifications];
    return YES;
}

- (void)theRestOfTheAppStartupProcess
{
    NSLog(@"Finishing app startup now that registration has happened.");
}


- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    token = [deviceToken copy];
    if (!didRegisterCalled)
    {
        didRegisterCalled = YES;
        [self theRestOfTheAppStartupProcess];
    }
}

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
    token = nil;
    if (!didRegisterCalled)
    {
        didRegisterCalled = YES;
        [self theRestOfTheAppStartupProcess];
    }
}

@end
@implementation AppDelegate
{
    dispatch_queue_t appStartupQueue;
    NSData* token;
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    appStartupQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
    dispatch_suspend(appStartupQueue);
    dispatch_set_target_queue(appStartupQueue, dispatch_get_main_queue());
    dispatch_async(appStartupQueue, ^{
        [self theRestOfTheAppStartupProcess];
    });

    NSLog(@"Calling registerForRemoteNotifications and deferring the rest of app startup.");
    [application registerForRemoteNotifications];
    return YES;
}

- (void)theRestOfTheAppStartupProcess
{
    NSLog(@"Finishing app startup now that registration has happened.");
}


- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    token = [deviceToken copy];
    if (appStartupQueue)
    {
        dispatch_resume(appStartupQueue);
        appStartupQueue = nil;
    }
}

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
    token = nil;
    if (appStartupQueue)
    {
        dispatch_resume(appStartupQueue);
        appStartupQueue = nil;
    }
}

@end
最简单的方法是将启动任务拆分为一个单独的方法,并让回调函数调用该方法。(FWIW,这可能是我会选择的方法。)看起来可能是这样的:

@implementation AppDelegate
{
    BOOL didRegisterCalled;
    NSData* token;
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [application registerForRemoteNotifications];

    NSLog(@"registerForRemoteNotifications called. waiting for callback.");

    while (!didRegisterCalled)
    {
        [[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate: [NSDate date]];
    }

    NSLog(@"Register call back happened, and execution resumed");

    return YES;
}

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    didRegisterCalled = YES;
    token = [deviceToken copy];
}

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
    didRegisterCalled = YES;
    token = nil;
}

@end
@implementation AppDelegate
{
    BOOL didRegisterCalled;
    NSData* token;
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    NSLog(@"Calling registerForRemoteNotifications and deferring the rest of app startup.");
    [application registerForRemoteNotifications];
    return YES;
}

- (void)theRestOfTheAppStartupProcess
{
    NSLog(@"Finishing app startup now that registration has happened.");
}


- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    token = [deviceToken copy];
    if (!didRegisterCalled)
    {
        didRegisterCalled = YES;
        [self theRestOfTheAppStartupProcess];
    }
}

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
    token = nil;
    if (!didRegisterCalled)
    {
        didRegisterCalled = YES;
        [self theRestOfTheAppStartupProcess];
    }
}

@end
@implementation AppDelegate
{
    dispatch_queue_t appStartupQueue;
    NSData* token;
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    appStartupQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
    dispatch_suspend(appStartupQueue);
    dispatch_set_target_queue(appStartupQueue, dispatch_get_main_queue());
    dispatch_async(appStartupQueue, ^{
        [self theRestOfTheAppStartupProcess];
    });

    NSLog(@"Calling registerForRemoteNotifications and deferring the rest of app startup.");
    [application registerForRemoteNotifications];
    return YES;
}

- (void)theRestOfTheAppStartupProcess
{
    NSLog(@"Finishing app startup now that registration has happened.");
}


- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    token = [deviceToken copy];
    if (appStartupQueue)
    {
        dispatch_resume(appStartupQueue);
        appStartupQueue = nil;
    }
}

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
    token = nil;
    if (appStartupQueue)
    {
        dispatch_resume(appStartupQueue);
        appStartupQueue = nil;
    }
}

@end
另一种方法可能是设置调度队列,挂起它,然后让回调恢复它。可能是这样的:

@implementation AppDelegate
{
    BOOL didRegisterCalled;
    NSData* token;
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [application registerForRemoteNotifications];

    NSLog(@"registerForRemoteNotifications called. waiting for callback.");

    while (!didRegisterCalled)
    {
        [[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate: [NSDate date]];
    }

    NSLog(@"Register call back happened, and execution resumed");

    return YES;
}

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    didRegisterCalled = YES;
    token = [deviceToken copy];
}

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
    didRegisterCalled = YES;
    token = nil;
}

@end
@implementation AppDelegate
{
    BOOL didRegisterCalled;
    NSData* token;
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    NSLog(@"Calling registerForRemoteNotifications and deferring the rest of app startup.");
    [application registerForRemoteNotifications];
    return YES;
}

- (void)theRestOfTheAppStartupProcess
{
    NSLog(@"Finishing app startup now that registration has happened.");
}


- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    token = [deviceToken copy];
    if (!didRegisterCalled)
    {
        didRegisterCalled = YES;
        [self theRestOfTheAppStartupProcess];
    }
}

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
    token = nil;
    if (!didRegisterCalled)
    {
        didRegisterCalled = YES;
        [self theRestOfTheAppStartupProcess];
    }
}

@end
@implementation AppDelegate
{
    dispatch_queue_t appStartupQueue;
    NSData* token;
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    appStartupQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
    dispatch_suspend(appStartupQueue);
    dispatch_set_target_queue(appStartupQueue, dispatch_get_main_queue());
    dispatch_async(appStartupQueue, ^{
        [self theRestOfTheAppStartupProcess];
    });

    NSLog(@"Calling registerForRemoteNotifications and deferring the rest of app startup.");
    [application registerForRemoteNotifications];
    return YES;
}

- (void)theRestOfTheAppStartupProcess
{
    NSLog(@"Finishing app startup now that registration has happened.");
}


- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    token = [deviceToken copy];
    if (appStartupQueue)
    {
        dispatch_resume(appStartupQueue);
        appStartupQueue = nil;
    }
}

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
    token = nil;
    if (appStartupQueue)
    {
        dispatch_resume(appStartupQueue);
        appStartupQueue = nil;
    }
}

@end

但您目前的情况将导致僵局。

谢谢您的回答。请问web服务调用在哪里,应用程序是否要等待它完成,即我是否会得到响应?因为在我的实现中(没有GCD),当我从didFinishLaunchingWithOptions返回时,不会调用服务调用的成功或失败块。从
-application:didFinishLaunchingWithOptions:
返回与是否调用成功或失败方法无关。听起来您可能想在此处阅读“运行循环”: