Method returning value from asynchronous block with FacebookSDK

拜拜、爱过 提交于 2019-11-29 08:19:20

I created a similar wrapper in the past and my approach was passing a "completion block" when calling my wrapper method; this completion block is then triggered once all the asynchronous calls are done running, and it receives whatever data your method would return in a synchronous scenario (in your case, the array of friends).

To illustrate - you could have your "myFriends" method redefined as:

+ (void)myFriendsWithCompletionBlock:(void (^)(NSArray *friends))completionBlock;

Then in the implementation, right after the friends = [NSArray arrayWithArray:fbFriends]; line, you would add this:

if (completionBlock != nil) {
    completionBlock(friends);
}

... and remove the return statement at the end.

Finally, on your view controller (or any object using the method, you would do something like this:

[FacebookWrapper myFriendsWithCompletionBlock:^(NSArray *friends){
    // do what you need to do with the friends array
}];

Of course, this is still asynchronous - but there's no way around since that's how the Facebook SDK was build (and, to be fair, this is probably the best way to do it - waiting for requests to finish synchronous would be terrible!)

Edit: I noticed you're also returning from the wrapper method in case it fails; in that situation, instead of returning you would do something like this:

if (completionBlock != nil) {
    completionBlock(nil);
}

That would cause the friends array to be nil when your completion block is called - you can then treat that error there however seems appropriate to you.

Hope this helped!

If you are dispatching an asynchronouos block, you can communicate with your UIViewController subclass by calling back to it:

[self someSelectorWithCallbackData:stuffWhichYouWantToGiveBack];

This will call self to get captured by the block, and so will work as expected. From the relevant method you can refresh the view / reload the tableview / dance a jig as required.

Depending on the context, you may need to __block scope self, eg

__block UIViewController *bsself = self;

But if you do the latter, be careful to avoid a retain loop (the build and analysis tools are fairly good at pointing this out).

Think you need to use a protol @class Webservice;

@protocol WebserviceDelegate
@optional

-(void)webservice:(Webservice *)webservice didFetchPosts:(NSArray *)posts;
-(void)webservice:(Webservice *)webservice didFetchComments:(NSArray *)comments forPostID:(NSString *)postID launchComments:(BOOL)launch;
-(void)webservice:(Webservice *)webservice didLoginWithUser:(User *)user;
-(void)webservice:(Webservice *)webservice didVoteWithSuccess:(BOOL)success forObject:(id)object direction:(BOOL)up;

@end

@interface Webservice : NSObject {
    __weak id <WebserviceDelegate> delegate;
}
//Delegate
@property (weak) id <WebserviceDelegate> delegate;



-(void)getHomepage {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        NSURLResponse *response;
        NSError *error;

        // Create the URL Request
        NSMutableURLRequest *request = [Webservice NewGetRequestForURL:[NSURL URLWithString:@"https://www.hnsearch.com/bigrss"]];

        // Start the request
        NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];


        //Handle response
        //Callback to main thread
        if (responseData) {
            NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSStringEncodingConversionAllowLossy];

            if (responseString.length > 0) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    [self parseIDsAndGrabPosts:responseString];
                });
            }
            else {
                dispatch_async(dispatch_get_main_queue(), ^{
                    [delegate webservice:self didFetchPosts:nil];
                });

            }
        }
        else {
            dispatch_async(dispatch_get_main_queue(), ^{
                [delegate webservice:self didFetchPosts:nil];
            });
        }


    });
}


-(void)parseIDsAndGrabPosts:(NSString *)parseString {
    // Parse String and grab IDs
    NSMutableArray *items = [@[] mutableCopy];
    NSArray *itemIDs = [parseString componentsSeparatedByString:@"<hnsearch_id>"];
    for (int xx = 1; xx < itemIDs.count; xx++) {
        NSString *idSubString = itemIDs[xx];
        [items addObject:[idSubString substringWithRange:NSMakeRange(0, 13)]];
    }


    // Send IDs back to HNSearch for Posts
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        NSURLResponse *response;
        NSError *error;

        // Create Request String
        NSString *requestString = @"http://api.thriftdb.com/api.hnsearch.com/items/_bulk/get_multi?ids=";
        for (NSString *item in items) {
            requestString = [requestString stringByAppendingString:[NSString stringWithFormat:@"%@,", item]];
        }

        // Create the URL Request
        NSMutableURLRequest *request = [Webservice NewGetRequestForURL:[NSURL URLWithString:requestString]];

        // Start the request
        NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];


        //Handle response
        //Callback to main thread
        if (responseData) {
            NSArray *responseArray = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingAllowFragments error:&error];

            if (responseArray) {
                NSMutableArray *postArray = [@[] mutableCopy];
                for (NSDictionary *dict in responseArray) {
                    [postArray addObject:[Post postFromDictionary:dict]];
                }

                NSArray *orderedPostArray = [self orderPosts:postArray byItemIDs:items];

                dispatch_async(dispatch_get_main_queue(), ^{
                    [delegate webservice:self didFetchPosts:orderedPostArray];

                    // Update Karma for User
                    if ([HNSingleton sharedHNSingleton].User) {
                        [self reloadUserFromURLString:[NSString stringWithFormat:@"https://news.ycombinator.com/user?id=%@", [HNSingleton sharedHNSingleton].User.Username]];
                    }
                });
            }
            else {
                dispatch_async(dispatch_get_main_queue(), ^{
                    [delegate webservice:self didFetchPosts:nil];
                });

            }
        }
        else {
            dispatch_async(dispatch_get_main_queue(), ^{
                [delegate webservice:self didFetchPosts:nil];
            });
        }


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