Как я могу заставить основной поток спать в ожидании вызова делегата? - PullRequest
1 голос
/ 10 мая 2010

Рассмотрим класс с этими методами:

- (id) initWithFrame: (CGRect) frame
{
    if (!(self = [super init]))
        return nil;
    webView = [[UIWebView alloc] initWithFrame:frame];
    [webView setDelegate:self];
    lock = [[NSConditionLock alloc] initWithCondition:LOCK_WAIT];
    return self;
}

- (void) setHTML: (NSString *) html
{
    [lock lockWhenCondition:LOCK_WAIT];
    [webView loadHTMLString:html baseURL:nil];
    [lock unlock];
}

- (void)webViewDidFinishLoad:(UIWebView *)aWebView
{
    [lock lockWhenCondition:LOCK_WAIT];
    // Locking to be able to unlock and change the  condition.
    [lock unlockWithCondition:LOCK_GO];
}

- (NSString *) stringByEvaluatingJavaScriptFromString: (NSString *) jsCommand
{
    [lock lockWhenCondition:LOCK_GO];
    NSString * res = [webView stringByEvaluatingJavaScriptFromString:jsCommand];
    [lock unlock];
    return res;
}

Давайте назовем этот класс SynchronousUIWebView . Из основного потока выполняю:

webView = [[SynchronousUIWebView alloc] initWithFrame:frame];
[webView setHTML:html];
[webView stringByEvaluatingJavaScriptFromString:jsCommand];

Кажется, проблема в том, что делегат не вызывается до тех пор, пока я не покину текущий стек вызовов, чего я не делаю, так как жду, когда произойдет вызов делегата, то есть тупик. Мне кажется, что вызов делегата помещается в очередь, которая вызывается, когда текущий вызов завершен. Итак, вопрос в том, могу ли я изменить это поведение?

Примечание. Причина, по которой это необходимо, заключается в том, что я не могу выполнить JavaScript, пока не загрузится HTML.

1 Ответ

1 голос
/ 10 мая 2010

Вы не можете использовать UIWebView из другого потока, кроме основного потока. Таким образом, вы можете оставить все свои блокировки и просто позволить веб-представлению и циклу выполнения обрабатывать ваш вызов делегата. Методы-делегаты также должны вызываться из основного потока.

Проблема main-thread-only существует в паре классов Какао, включая все UIKit. Это означает, что реализации всех этих классов основаны на вызове только из основного потока (например, они неявно используют цикл выполнения основного потока). Просто невозможно использовать их в других потоках, даже при реализации собственной блокировки.

...