0

グランドセントラルディスパッチを使用してNSURLを設定しようとしていますが、グランドセントラルディスパッチブロックの外部でアクセスしようとするまで、変数が設定されてアクセス可能であるように見えます。

-(void)viewDidLoad {

[super viewDidLoad];

dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(backgroundQueue,^{

    self.ubiquitousURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];

   NSLog(@"ubiq inside: %@", self.ubiquitousURL);

    if (self.ubiquitousURL) {

        self.iCloudDocURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@Documents", self.ubiquitousURL]];
        self.iCloudDocString = [self.iCloudDocURL absoluteString];

        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(loadFiles) name: UIApplicationDidBecomeActiveNotification object:nil];

    } else {

        /* change to the main queue if you want to do something with the UI. For example: */
        dispatch_async(dispatch_get_main_queue(),^{

            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Please enable iCloud" message:nil delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];

            [alert show];

        });

    }

});


NSLog(@"ubiq outside: %@", self.ubiquitousURL);

}

最初のNSLogwhichは、で始まりubiq inside、正しいURLをubiq outside返し、NULLを返します。私はARCを使用しているので、メモリなどについて言及する必要はありません...これはGCDの問題です。

self.ubiquitousURLGCDブロックの外でアクセスできない理由を知っていますか?ありがとう。

4

2 に答える 2

4

非同期呼び出しを行っています。したがって、この行NSLog(@"ubiq outside: %@", self.ubiquitousURL);は、backgroundQueue内のコードが実行されたかどうかに関係なく実行されます。

最初に外部ログが表示され、次に内部ログが表示されます。

于 2012-07-08T00:30:21.803 に答える
3

dispatch_async「後で実行する」という意味です。したがって、ブロック内のコードはすぐには実行されません。NSLog「外部」呼び出しがすでに実行された後、後で実行されます。たとえば、呼び出しsleep(5)の前に置く場合NSLogは、おそらく値が表示されます。(ただし、実際のコードでは実際にこれを行うべきではありません。基本的に、アプリが5秒間フリーズします。)

そのプロパティを設定した後でメインキューでさらにコードを実行する場合は、次のようにします。

dispatch_async(backgroundQueue,^{
    self.ubiquitousURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];

    NSLog(@"ubiq inside: %@", self.ubiquitousURL);

    if (self.ubiquitousURL) {
        self.iCloudDocURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@Documents", self.ubiquitousURL]];
        self.iCloudDocString = [self.iCloudDocURL absoluteString];

        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(loadFiles) name: UIApplicationDidBecomeActiveNotification object:nil];

        // ************** NEW HOTNESS HERE **************
        dispatch_async(dispatch_get_main_queue(),^{
            NSLog(@"ubiq outside: %@", self.ubiquitousURL);
        });
    } else {
        /* change to the main queue if you want to do something with the UI. For example: */
        dispatch_async(dispatch_get_main_queue(),^{
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Please enable iCloud" message:nil delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
            [alert show];
        });
    }
});

その行をメソッド呼び出しに置き換えてNSLog、iCloud URLを取得した後で実際の作業を実行したい場合は、それを実行します。

于 2012-07-08T00:38:08.560 に答える