-1

我今天遇到了一个问题,我的应用程序无法及时启动。事实证明,我使用的一些第三方代码正在尝试使用以下技巧获取用户代理字符串:

-(NSString*)userAgentString
{
    webView = [[UIWebView alloc] init];
    webView.delegate = self;
    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"www.google.com"]]];

    // Wait for the web view to load our bogus request and give us the secret user agent.
    while (self.userAgent == nil) 
    {
        // This executes another run loop. 
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
    }

    return self.userAgent;
}

-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    self.userAgent = [request valueForHTTPHeaderField:@"User-Agent"];

    // Return no, we don't care about executing an actual request.
    return NO;
}

(来自http://blog.sallarp.com/iphone-ipad-get-user-agent-for-uiwebview/#more-1003

在调用该代码之前,我通过将一些操作添加到由 +[NSOperationQueue mainQueue] 返回的队列中来排队。这些操作旨在在调用 +[NSData dataWithContentsOfURL:] 时在后台执行。

一旦调用了运行循环上的方法,它就会执行我的排队操作,阻塞主线程并阻止应用程序启动。现在我已经得到了一个解决方法,确保在第三方代码执行之前不要排队任何操作,但是如果有人知道为什么会发生这种情况,以及将来如何防止它,我很想听听. 谢谢!

4

1 回答 1

1

原因很简单。您在主队列上排队操作。然后有人(这段代码)告诉主队列运行操作。您的操作已运行。这是您几乎不应该手动运行主运行循环的原因之一。它导致各种奇怪的事情发生。

至于如何防止它:不要手动抽出主运行循环,并针对这样做的库打开错误(包括针对苹果在中间运行主运行循环NSAttributedString initWithHTML:...)。

我不清楚为什么调用代码需要用户代理字符串。这通常不是您的业务,但它也是相当静态的,因此应该可以通过其他方式确定(其中最重要的是对答案进行硬编码)。在不知道目标的情况下,我不确定用什么来代替它,但是这种方法不是一个好方法。

于 2012-03-06T20:36:30.447 回答