如何在函数中立即执行块?

时间:2015-08-06 08:28:19

标签: ios objective-c block synchronous

我在网上搜索,但我找到的并不是我所期望的。

我有一个内部有一个块的函数,这个函数在对块进行处理之前返回。所以我的函数返回nil ...

NSString* returnTheFolder()
{
    NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
    GTLServiceDrive *service;
    __block NSMutableDictionary* titlesAndIdentifiers;
    __block __strong NSString* rootFolder;
    __block NSArray* allIdentifiers;
    NSString* userDefaultValue = [userDefaults objectForKey:@"User1"];
    titlesAndIdentifiers = [[NSMutableDictionary alloc]init];
    service = [[GTLServiceDrive alloc] init];
    service.authorizer = [GTMOAuth2ViewControllerTouch authForGoogleFromKeychainForName:KeychainForName clientID:ClientID clientSecret:ClientSecret];
GTLQueryDrive *query =
[GTLQueryDrive queryForFilesList];
query.maxResults = 9999999;
query.q = @"'root' in parents";  
    [service executeQuery:query completionHandler:^(GTLServiceTicket *ticket, GTLDriveFileList* files, NSError *error) {
        for (GTLDriveFile *folder in files)
        {
            if ([folder.mimeType isEqualToString:@"application/vnd.google-apps.folder"])
            {
                [titlesAndIdentifiers setValue:folder.identifier forKey:folder.title];
                    allIdentifiers = [[NSArray alloc]initWithArray:[titlesAndIdentifiers allKeysForObject:userDefaultValue]];
                    rootFolder = [allIdentifiers objectAtIndex:0];
            }
        }
    }];
    return rootFolder;
}

我可以使用哪种方法在我的函数中立即执行一个块?

非常感谢大家!!!

3 个答案:

答案 0 :(得分:0)

而不是像这样返回一个值。你可以创建一个不返回任何东西的函数,并将一个块作为参数。 该块将该值作为参数。

答案 1 :(得分:0)

将现有代码更改为以下代码

-(void)returnTheFolder:(void (^) (NSString *rootFolder))completion
{
    NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
    GTLServiceDrive *service;
    __block NSMutableDictionary* titlesAndIdentifiers;
    __block __strong NSString* rootFolder;
    __block NSArray* allIdentifiers;
    NSString* userDefaultValue = [userDefaults objectForKey:@"User1"];
    titlesAndIdentifiers = [[NSMutableDictionary alloc]init];
    service = [[GTLServiceDrive alloc] init];
    service.authorizer = [GTMOAuth2ViewControllerTouch authForGoogleFromKeychainForName:KeychainForName clientID:ClientID clientSecret:ClientSecret];
GTLQueryDrive *query =
[GTLQueryDrive queryForFilesList];
query.maxResults = 9999999;
query.q = @"'root' in parents";  
    [service executeQuery:query completionHandler:^(GTLServiceTicket *ticket, GTLDriveFileList* files, NSError *error) {
        for (GTLDriveFile *folder in files)
        {
            if ([folder.mimeType isEqualToString:@"application/vnd.google-apps.folder"])
            {
                [titlesAndIdentifiers setValue:folder.identifier forKey:folder.title];
                    allIdentifiers = [[NSArray alloc]initWithArray:[titlesAndIdentifiers allKeysForObject:userDefaultValue]];
                    rootFolder = [allIdentifiers objectAtIndex:0];
                    completion(rootFolder);
            }
        }
    }];
}

然后调用如下

[self returnTheFolder:^(NSString *rootFolder){
    NSLog(@"Root Folder = %@",rootFolder);
}];

干杯。

答案 2 :(得分:0)

您使用的Google库设计为异步 - 它正在调用Web服务,并且可能需要任意长时间才能完成。在考虑同步解决方案时,您必须考虑到这一点 - 您可能会阻塞任意长时间。

最佳解决方案是重新设计您的代码,使其成为异步。

如果由于某种原因无法使代码异步,那么您可以使异步调用显示为同步,但必须小心。本质上,您需要做的就是使用信号量:将异步调用信号的回调块设置为信号量,并在异步调用之后等待信号量。 然而为此工作,您需要知道您在信号量上等待的线程与用于回调的线程不同 - 否则将阻止回调。您需要确定Google库对调用回调的线程的保证,并正确编写代码。

如果所有这些听起来太复杂,请回到第一个建议 - 让你的代码异步!

HTH