iphone - NSOperation、观察者和线程错误

标签 iphone sdk

我在 NSOperation 和观察者方面遇到问题。

我有一个 tabbarcontroller 和一个 splashController。我希望启动画面加载并下载文件,并且在下载文件时使 tabbarcontroller 出现在屏幕上。

问题是我有一个错误:

bool _WebTryThreadLock(bool), 0x3d2fa90: 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...

这是我的代码:

- (void)applicationDidFinishLaunching:(UIApplication *)application {

    queue = [[NSOperationQueue alloc] init];


    NSString *path = [NSString stringWithFormat:@"%@flux.xml",DOCPATH];
    //Le fichier existe dans le repertoire des documents
    if([[NSFileManager defaultManager] fileExistsAtPath:path])
        [window addSubview:tabBarController.view];
    else
    {
        splash = [[SplashController alloc] init];
        [window addSubview:splash.view];
    }

    DataLoadOperation *operation = [[DataLoadOperation alloc] initWithURL:[NSURL URLWithString:@"http://sly.33.free.fr/flux.xml"]];
    [self.queue addOperation:operation];
    [operation addObserver:self forKeyPath:@"isFinished" options:NSKeyValueObservingOptionNew context:nil];


}

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    [window addSubview:tabBarController.view];
    [window makeKeyAndVisible];
    NSLog(@"fini");

}

有人可以帮我吗?

最佳答案

键值观察通知发生在更改观察到的属性的同一线程上。 Apple 在 NSOperation 类引用中提到了以下警告:

"Although you can attach observers to these properties, you should not use Cocoa bindings to bind them to elements of your application’s user interface. Code associated with your user interface typically must execute only in your application’s main thread. Because an operation may execute in any thread, any KVO notifications associated with that operation may similarly occur in any thread."

在您的 observeValueForKeyPath:ofObject:change:context: 中方法中,您应该在主线程上执行任何 UIKit 操作。由于您要在其中执行多个步骤,因此您实际上可能希望在观察类中创建另一个名为 -dataLoadingFinished 的方法。您可以从 observe:… 内部在主线程上调用它。然后,您可以在其中包含所有 UI 调用,而不必调用 performSelectorOnMainThread对于每一个:

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
  [self performSelectorOnMainThread:@selector(dataLoadingFinished:) withObject:nil waitUntilDone:YES];
}

即使在线程不是问题的情况下,通常也会定义单独的方法来实际实现每个观察操作,以防止 observe:…以免变得太大。

另请注意,即使您只观察一个属性,验证您感兴趣的属性是否是提示更改通知的属性仍然是更好的做法。请参阅 Dave Dribin 的文章 Proper KVO Usage了解执行此操作的最佳方式。

关于iphone - NSOperation、观察者和线程错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1244243/

相关文章:

iphone - uiwebview中如何实现触摸事件?

iphone - 如何从上传的 iPhone 照片中获取正确的纬度和经度?

iphone - UIScrollView 奇怪的 ScrollIndicator 与 UITableView 相比

ios - arm64 首发二月号

Android SDK 管理器不工作 : Download interrupted: "Tag mismatch"

ios - 添加带有披露指示器的 UIVewiTabelCell 链接

xcode - Mac SDK : using latest SDK but ensuring backwards compatibility with earlier deployment target

android - 使用 Facebook SDK 3.0 登录 facebook

android - MediaPlayer.OnCompletionListener 和 View.OnClickListener?

ios - 读取权限后直接请求发布权限 - Facebook SDK for iOS 6