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!
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…