How to execute a block immediately in a function?

时光毁灭记忆、已成空白 提交于 2019-12-25 07:07:46

问题


I search on the web, but what I found is not what I expect.

I have a function with a block inside, and this function return before doing the treatment into the block. So my function return 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;
}

Which method can I use for execute a block immediately in my function ?

Thanks a lot everyone !!!


回答1:


The Google library you are using is designed to be asynchronous - it is making calls to a web service and they can take an arbitrarily long time to complete. You must take this into consideration when thinking of a synchronous solution - you may block for an arbitrarily long time.

The best solution for you is to redesign your code so it to is asynchronous.

If you cannot make your code asynchronous for some reason then you can make an asynchronous call appear synchronous, but you must be careful. In essence all you need to do is use a semaphore: have the callback block to the asynchronous call signal the semaphore, and after making the asynchronous call wait on the semaphore. However for this to work you need to know that the thread you are waiting on the semaphore is not the same thread that will be used for the callback - or the callback will be blocked. You need to determine what guarantees the Google library makes about the thread the callback will be invoked on and write your code appropriately.

And if all that sounds too complicated go back to the first recommendation - make your code asynchronous!

HTH




回答2:


Instead of returning a value like this.You can make a function that does not return anything and takes a block as an argument. The block will take the value as a parameter.




回答3:


Change your existing code to the code below

-(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);
            }
        }
    }];
}

And then call like below

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

Cheers.



来源:https://stackoverflow.com/questions/31850598/how-to-execute-a-block-immediately-in-a-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!