jjzjj

objective-c - 在附加到 NSOperationQueue operationsCount 的 observeValueForKeyPath 中崩溃

coder 2024-01-11 原文

我的 UIView 子类中有 UITextView logView(尝试了 atomicnonatomic)和 NSOperationQueue uploadQueue 属性. 我在我的 NSOperationQueue 属性的 operationsCount 上添加了 KVO,如下所示:

[[self uploadQueue] addObserver:self
            forKeyPath:@"operationCount" 
               options:(NSKeyValueObservingOptionNew |
                        NSKeyValueObservingOptionOld)
               context:NULL];

观察者函数如下所示:

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context
{
    if ([object isKindOfClass: [NSOperationQueue class]]) {
        NSLog(@"Keypath is: %@ change dictionary is: %@", keyPath, change);
        NSInteger testnew = [[change objectForKey: @"new"] integerValue];
        NSInteger testold = [[change objectForKey: @"old"] integerValue];
        if (testnew > testold) {
            [[self logView] setText: [NSString stringWithFormat: @"Uploading %d files", testnew]];
            objc_setAssociatedObject([self logView], @"max_value_of_uploads", [change objectForKey: @"new"], OBJC_ASSOCIATION_COPY);
        } else {
            NSInteger value = [objc_getAssociatedObject([self logView], @"max_value_of_uploads") integerValue]; 
            [[self logView] setText: [NSString stringWithFormat: @"Uploaded %d of %d files", testnew, value]];
        }
    }
}

uploadQueue 填充工作如下:

   ...
   NSDictionary *iter;
        NSEnumerator *enumerator = [objects objectEnumerator];
        while (iter = [enumerator nextObject]) {
            Uploader *op = [[Uploader alloc] initWithFileName: [iter objectForKey: @"fileName"] 
                                                             FileID: [[iter objectForKey: @"fileID"] integerValue] 
                                                       AndSessionID: [self sess]];
            //Uploader *op = [[Uploader alloc] init];
            [[self uploadQueue] addOperation: op];
   ...

没有 if-else block ,一切正常:我收到关于队列中操作数量的 NSLog 消息,数字正常等等。 但是使用那个 if-else block ,我崩溃了,看起来像这样:

bool _WebTryThreadLock(bool), 0x10617fb0: 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 setText:]
3   -[SincViewController observeValueForKeyPath:ofObject:change:context:]
4   NSKeyValueNotifyObserver
5   NSKeyValueDidChange
6   -[NSObject(NSKeyValueObservingPrivate) _changeValueForKey:key:key:usingBlock:]
7   -[NSObject(NSKeyValueObservingPrivate) _changeValueForKey:usingBlock:]
8   ____NSOQDelayedFinishOperations_block_invoke_0
9   -[NSObject(NSKeyValueObservingPrivate) _changeValueForKey:key:key:usingBlock:]
10  -[NSObject(NSKeyValueObservingPrivate) _changeValueForKey:usingBlock:]
11  __NSOQDelayedFinishOperations
12  _dispatch_after_timer_callback
13  _dispatch_source_invoke
14  _dispatch_queue_invoke
15  _dispatch_worker_thread2
16  _pthread_wqthread
17  start_wqthread

它在 else block 中崩溃。 此外,我没有看到我的 logView 有任何变化。 感谢您以后的帮助和回复。

更新: performSelectorOnMainThread 设置文本时救了我。

最佳答案

更新用户界面时,请确保您处于主线程中。一个可能的解决方案如下:

dispatch_async(dispatch_get_main_queue(), ^{
    if (testnew > testold) {
        [[self logView] setText: [NSString stringWithFormat: @"Uploading %d files", testnew]];
        objc_setAssociatedObject([self logView], @"max_value_of_uploads", [change objectForKey: @"new"], OBJC_ASSOCIATION_COPY);
    } else {
        NSInteger value = [objc_getAssociatedObject([self logView], @"max_value_of_uploads") integerValue]; 
        [[self logView] setText: [NSString stringWithFormat: @"Uploaded %d of %d files", testnew, value]];
    }
}); 

请注意,使用 dispatch_asyncdispatch_sync 取决于您想要的实现,但在后一种情况下,除非您检查您所在的线程,否则您会面临死锁的风险。

另请参阅:NSOperation, observer and thread error 有人建议将您的 UI 代码移至单独的方法:

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

.. 这是一条很好的替代路线。

关于objective-c - 在附加到 NSOperationQueue operationsCount 的 observeValueForKeyPath 中崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11210219/

有关objective-c - 在附加到 NSOperationQueue operationsCount 的 observeValueForKeyPath 中崩溃的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  3. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

  4. Ruby Readline 在向上箭头上使控制台崩溃 - 2

    当我在Rails控制台中按向上或向左箭头时,出现此错误:irb(main):001:0>/Users/me/.rvm/gems/ruby-2.0.0-p247/gems/rb-readline-0.4.2/lib/rbreadline.rb:4269:in`blockin_rl_dispatch_subseq':invalidbytesequenceinUTF-8(ArgumentError)我使用rvm来管理我的ruby​​安装。我正在使用=>ruby-2.0.0-p247[x86_64]我使用bundle来管理我的gem,并且我有rb-readline(0.4.2)(人们推荐的最少

  5. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  6. ruby-on-rails - 简单的 Ruby on Rails 问题——如何将评论附加到用户和文章? - 2

    我意识到这可能是一个非常基本的问题,但我现在已经花了几天时间回过头来解决这个问题,但出于某种原因,Google就是没有帮助我。(我认为部分问题在于我是一个初学者,我不知道该问什么......)我也看过O'Reilly的RubyCookbook和RailsAPI,但我仍然停留在这个问题上.我找到了一些关于多态关系的信息,但它似乎不是我需要的(尽管如果我错了请告诉我)。我正在尝试调整MichaelHartl'stutorial创建一个包含用户、文章和评论的博客应用程序(不使用脚手架)。我希望评论既属于用户又属于文章。我的主要问题是:我不知道如何将当前文章的ID放入评论Controller。

  7. objective-c - 在设置 Cocoa Pods 和安装 Ruby 更新时出错 - 2

    我正在尝试为我的iOS应用程序设置cocoapods但是当我执行命令时:sudogemupdate--system我收到错误消息:当前已安装最新版本。中止。当我进入cocoapods的下一步时:sudogeminstallcocoapods我在MacOS10.8.5上遇到错误:ERROR:Errorinstallingcocoapods:cocoapods-trunkrequiresRubyversion>=2.0.0.我在MacOS10.9.4上尝试了同样的操作,但出现错误:ERROR:Couldnotfindavalidgem'cocoapods'(>=0),hereiswhy:U

  8. ruby - 你会如何在 Ruby 中表达成语 "with this object, if it exists, do this"? - 2

    在Ruby(尤其是Rails)中,您经常需要检查某物是否存在,然后对其执行操作,例如:if@objects.any?puts"Wehavetheseobjects:"@objects.each{|o|puts"hello:#{o}"end这是最短的,一切都很好,但是如果你有@objects.some_association.something.hit_database.process而不是@objects呢?我将不得不在if表达式中重复两次,如果我不知道实现细节并且方法调用很昂贵怎么办?显而易见的选择是创建一个变量,然后测试它,然后处理它,但是你必须想出一个变量名(呃),它也会在内存中

  9. ruby - 在 Ruby 中,为什么 Array.new(size, object) 创建一个由对同一对象的多个引用组成的数组? - 2

    如thisanswer中所述,Array.new(size,object)创建一个数组,其中size引用相同的object。hash=Hash.newa=Array.new(2,hash)a[0]['cat']='feline'a#=>[{"cat"=>"feline"},{"cat"=>"feline"}]a[1]['cat']='Felix'a#=>[{"cat"=>"Felix"},{"cat"=>"Felix"}]为什么Ruby会这样做,而不是对object进行dup或clone? 最佳答案 因为那是thedocumenta

  10. ruby object.hash - 2

    一个对象的散列值是什么意思?在什么情况下两个对象具有相同的哈希值??还有说Array|Hash不能是Hashkeys,这个跟对象的hash值有关系,为什么? 最佳答案 对于要存储在HashMap或哈希集中的对象,必须满足以下条件:如果认为两个对象相等,则它们的哈希值也必须相等。如果两个对象不被认为是相等的,那么它们的哈希值应该很可能不同(两个不同的对象具有相同哈希值的次数越多,对HashMap/集合的操作性能就越差)。因此,如果两个对象具有相同的哈希值,则很有可能(但不能保证)它们相等。上面“相等”的确切含义取决于散列方法的实现者。

随机推荐