0

在我目前正在开发的 iOS 应用程序中,每次页面更改时,该应用程序都会访问数据库以检索信息。在等待查询执行和查询中的信息填充页面上的字段时,应该有一个视图可以弹出、动画并说正在加载。最初有一个方法检查是否有互联网连接,如果有就会显示弹出窗口,然后另一个方法会执行查询。这些像这样穿线的地方

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

然而,这在大约 10% 的情况下会导致崩溃问题。我不完全理解这个问题,但我认为这是因为分离这样的新线程有时(并非总是)会导致从不是主线程的线程添加子视图。这是一个子问题,我的理论是否合乎逻辑。

无论哪种方式,我们都摆脱了那种做事的方法,只是一次调用一个方法,而不使用线程。像这样

[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 回答