问题
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