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
,返回YES首先调用didFinishLaunchingWithOptions
的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:
返回与是否调用成功或失败方法无关。听起来您可能想在此处阅读“运行循环”: