gpt4 book ai didi

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

转载 作者:塔克拉玛干 更新时间:2023-11-01 21:23:44 24 4
gpt4 key购买 nike

我的 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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com