Jef*_*bes 12 iphone cocoa multithreading
我正在编写一个将图像异步加载到屏幕上的应用程序.我把它设置为NOT并发(也就是说,它生成一个线程并一次执行一个),所以我只重写了[NSOperation main]
我的NSOperation子类中的函数.
无论如何,所以当我添加所有这些操作时,我希望以后能够访问排队的操作来改变它们的优先级.不幸的是,无论什么时候我打电话-[NSOperationQueue operations]
,我回来的都是一个空数组.最好的部分是,在放入一些控制台打印语句之后,尽管数组为空,但线程仍然在队列中并执行(由打印指示)!
是什么赋予了?我还看了一下这个帐户只是为了确保它们都不是一次性执行而且似乎并非如此.
有任何想法吗?把头发拉出来.
编辑:另外值得一提的是,相同的代码在模拟器中运行时提供了完整的数组:(
我走了进去-operations
,发现它基本上是这样做的:
[self->data->lock lock];
NSString* copy = [[self->data->operations copy] autorelease];
[self->data->lock unlock];
return copy;
Run Code Online (Sandbox Code Playgroud)
除了在调用之后-autorelease
,后续指令覆盖包含指向操作队列的新副本的唯一指针的寄存器.然后调用者只获得一个nil
返回值." data
"字段是名为的内部类的实例,_NSOperationQueueData
其中包含以下字段:
NSRecursiveLock* lock;
NSArray* operations;
Run Code Online (Sandbox Code Playgroud)
我的解决方案是-operations
按照相同的逻辑进行子类化和覆盖,但实际上返回了数组副本.如果内部NSOperationQueue
与此修复程序不兼容,我添加了一些健全性检查来挽救.只有在调用do [super operations]
确实返回时才会调用此重新实现nil
.
如果Apple要改变内部结构,这可能会在未来的操作系统版本中出现问题,但却以某种方式避免实际修复此错误.
#if TARGET_OS_IPHONE
#import <objc/runtime.h>
@interface _DLOperationQueueData : NSObject {
@public
id lock; // <NSLocking>
NSArray* operations;
}
@end
@implementation _DLOperationQueueData; @end
@interface _DLOperationQueueFix : NSObject {
@public
_DLOperationQueueData* data;
}
@end
@implementation _DLOperationQueueFix; @end
#endif
@implementation DLOperationQueue
#if TARGET_OS_IPHONE
-(NSArray*) operations
{
NSArray* operations = [super operations];
if (operations != nil) {
return operations;
}
_DLOperationQueueFix* fix = (_DLOperationQueueFix*) self;
_DLOperationQueueData* data = fix->data;
if (strcmp(class_getName([data class]), "_NSOperationQueueData") != 0) {
// this hack knows only the structure of _NSOperationQueueData
// anything else, bail
return operations;
}
if ([data->lock conformsToProtocol: @protocol(NSLocking)] == NO) {
return operations; // not a lock, bail
}
[data->lock lock];
operations = [[data->operations copy] autorelease];
[data->lock unlock];
return operations; // you forgot something, Apple.
}
#endif
@end
Run Code Online (Sandbox Code Playgroud)
头文件是:
@interface DLOperationQueue : NSOperationQueue {}
#if TARGET_OS_IPHONE
-(NSArray*) operations;
#endif
@end
Run Code Online (Sandbox Code Playgroud)