如何在等待委托被调用时让主线程进入休眠状态?

时间:2010-05-10 10:23:03

标签: ios iphone uiwebview delegates deadlock

考虑使用这些方法的类:

- (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];

问题似乎是在我离开当前调用堆栈之前没有调用委托,我没有这样做,因为我正在等待代理调用发生,即死锁。对我来说,似乎委托调用被推送到当前调用完成时调用的队列。所以问题是我可以修改这种行为吗?

注意:需要的原因是我在加载HTML之前无法执行JavaScript。

1 个答案:

答案 0 :(得分:1)

您不能使用主线程以外的UIWebView。因此,您可以省略所有锁定,只需让Web视图和运行循环处理您的委托调用。然后也应该从主线程调用委托方法。

在几个Cocoa类中存在main-thread-only问题,包括所有UIKit。这意味着,所有这些类的实现都依赖于仅从主线程调用(例如,它们隐式使用主线程的运行循环)。即使在实现自己的锁定时,也无法在其他线程上使用它们。