-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

その理由はかなり単純明快です。メイン キューで操作をキューに入れました。次に、誰か (このコード) がメイン キューに操作を実行するように指示しました。あなたの操作は実行されました。これは、メインの runloop を手動で実行してはならない理由の 1 つです。それはあらゆる種類の奇妙なことを引き起こします。

それを防ぐ方法について:メインの実行ループを手動でポンプしないでください。また、そうするライブラリに対してバグを開きます(メインの実行ループを途中で実行するためのAppleに対するものを含むNSAttributedString initWithHTML:...)。

呼び出し元のコードがユーザー エージェント文字列を必要とする理由がよくわかりません。それは一般的にあなたのビジネスではありませんが、かなり静的でもあるため、他の手段で決定できるはずです (少なくとも、答えをハードコーディングするだけではありません)。目標が分からないので、これを何に置き換えたらよいかわかりませんが、このアプローチは良い方法ではありません。

于 2012-03-06T20:36:30.447 に答える