LoginSignup
51
47

More than 5 years have passed since last update.

コールバックで指定したブロックをメインスレッドで実行する

Posted at

Blocksが浸透して、システムの実装でもコールバックを受け取って実行するタイプのものが増えてきました。
返ってきた値を見て、必要に応じてUIAlertViewやUIActionViewを出したい、というときなどにハマったので、覚書。

たとえば、Twitterアカウントを利用する際、使用できるアカウントがあるかのチェックをしたい際にはrequestAccessToAccountsWithType:options:completion:メソッドを使用しますが、
このcompletionで指定したブロックが実行されるのはメインスレッドではないため、ここでUIを操作しようとするとたいへんなことになります。

.m
ACAccountStore* store = [[ACAccountStore alloc] init];
ACAccountType* type = [store accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];

[store requestAccessToAccountsWithType:type options:nil completion:^(BOOL granted, NSError *error) {
    // bad pattern 
    // grantedに応じてアラートを出したい
    if (!granted) {
        UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"エラー" message:@"" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [alert show];
    }
}];

そこで、dispatch_get_main_queue()を使用して、メインスレッドで処理を実行させます。

.
[store requestAccessToAccountsWithType:type options:nil completion:^(BOOL granted, NSError *error) {
    // it works!
    if (!granted) {
        dispatch_async(dispatch_get_main_queue(), ^{
            UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"エラー" message:@"" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
            [alert show];
        });
    }
}];

参考

EKEventStore#requestAccessToEntityTypeのcallbackがmain thread以外の場所で実行される件とその対処

Allocating/showing a UIAlertView in a Block statement

51
47
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
51
47