0

私が現在取り組んでいる iOS アプリでは、アプリはページが変わるたびにデータベースにアクセスして情報を取得します。クエリが実行され、クエリからの情報がページのフィールドに入力されるのを待っている間、ポップアップ、アニメーション化、および読み込みを示すビューがあるはずです。元々、インターネットに接続されているかどうかを確認し、接続されていればポップアップを表示し、別のメソッドがクエリを実行するメソッドがありました。これらのようにスレッド化された場所

[NSThread detachNewThreadSelector:@selector(appStartedLoading) toTarget:self withObject:nil]; 

ただし、これにより約 10% の確率でクラッシュの問題が発生します。私はその問題を完全には理解していませんが、そのような新しいスレッドを切り離すと、メインスレッドではないスレッドからサブビューが追加されることがあるためだと思います。それは、私の理論が論理的かどうかというサブクエスチョンのようなものです。

いずれにせよ、私たちは物事を行うメソッドを取り除き、スレッド化せずにメソッドを一度に 1 つずつ呼び出しました。このような

[self appStartedLoading];
[self performQuery]; //fake placeholder method for examples sake.

ただし、これにより、次のページが既に表示され、クエリが既に実行された後に、読み込み画面が表示されました。おそらく、アプリがクエリでビジー状態だったためです。サブビューが使用していた方法で別のスレッドでクエリを実行しようとしましたが、変更されませんでした。メインスレッドで appStartedLoading メソッドを実行して、ブロックするように伝えてみました。

[self performSelectorOnMainThread:@selector(appStartedLoading) withObject:nil waitUntilFinished: YES]; 

ブロックするように指示されているため、サブビューが追加されてアニメーション化されるまでクエリは実行されませんが、最初にページが変更されてから読み込み画面が表示されると思います。また、メソッドに小さなループを入れて、サブビューが追加されるまで終了しないようにしましたが、サブビューが画面に表示されなくてもすぐに終了します。ループはこれです。

while([[[self.window.subviews objectAtIndex:0] subviews] indexOfObject:loaderView] == NSNotFound)
    {
        i++;
        NSLog(@"this %d", i);
        [[self.window.subviews objectAtIndex:0] addSubview:loaderView];
    }  

サブビューを追加するように指示したので、一度だけ実行するのは理にかなっていますが、追加した後に表示されないのはなぜですか? 私は正直なところプログラミングがまだ得意ではなく、ここで何が起こっているのか非常に混乱しています。誰かがここで光を当てて、舞台裏で何が起こっているかの正しい方向に私を向けるのを手伝ってくれるなら、それは素晴らしいことです.

ここにクラッシュからのエラーログがあります

 bool _WebTryThreadLock(bool), 0xc8a7fa0: Tried to obtain the web lock from a thread other than the main thread or the web thread. This may be a result of calling to UIKit from a secondary thread. Crashing now...
1   WebThreadLock
2   -[UITextView setFrame:]
3   UIViewCommonInitWithFrame
4   -[UIView initWithCoder:]
5   -[UIScrollView initWithCoder:]
6   -[UITextView initWithCoder:]
7   UINibDecoderDecodeObjectForValue
8   -[UINibDecoder decodeObjectForKey:]
9   -[UIRuntimeConnection initWithCoder:]
10  UINibDecoderDecodeObjectForValue
11  UINibDecoderDecodeObjectForValue
12  -[UINibDecoder decodeObjectForKey:]
13  -[UINib instantiateWithOwner:options:]
14  -[UIViewController _loadViewFromNibNamed:bundle:]
15  -[UIViewController loadView]
16  -[UIViewController view]
17  -[UIViewController contentScrollView]
18  -[UINavigationController _computeAndApplyScrollContentInsetDeltaForViewController:]
19  -[UINavigationController _layoutViewController:]
20  -[UINavigationController _startTransition:fromViewController:toViewController:]
21  -[UINavigationController _startDeferredTransitionIfNeeded]
22  -[UINavigationController __viewWillLayoutSubviews]
23  -[UILayoutContainerView layoutSubviews]
24  -[UIView(CALayerDelegate) layoutSublayersOfLayer:]
25  -[NSObject performSelector:withObject:]
26  -[CALayer layoutSublayers]
27  CA::Layer::layout_if_needed(CA::Transaction*)
28  CA::Context::commit_transaction(CA::Transaction*)
29  CA::Transaction::commit()
30  CA::Transaction::release_thread(void*) 
31  _pthread_tsd_cleanup
4

1 に答える 1

0

バックグラウンド スレッドで最初の方法を試して、いつクラッシュするかをログ メッセージに投稿してください。私の推測では、あなたの while ループは、実際にそのことを呼び出すことは決してないため、スピンオフして青くなってbreak;いるということです。また、サブビュー ループのアプローチは複雑すぎます。他のすべてのものの上に何かを表示する必要がある場合は、それをビュー コントローラーのサブビューとして追加するか、ナビゲーション コントローラーのビューとして追加することをお勧めします。

于 2012-06-30T22:24:28.213 に答える