我想知道如果仍有一些操作正在运行,那么解除一个ivar NSOperationQueue的正确方法是什么,这通常会在用户突然退出应用程序时发生.在一些例子中,我看到使用了waitUntilAllOperationsAreFinished,如下所示:
- (void)dealloc {
[_queue cancelAllOperations];
[_queue waitUntilAllOperationsAreFinished];
[_queue release];
...
然而,许多人建议避免这样做,因为它会挂起运行循环.那么发布的正确方法是_queue什么?如果我不等待操作完成并继续发布,会发生什么?
在我当前的项目中,几个视图控制器(如vc)生成operation在静态NSOperationQueue上执行的NSOperation对象(如).当操作正在等待或运行时,它将通过委托(报告operation.delegate = vc未保留)向视图控制器报告.
这些操作可能需要一段时间,同时应用程序可以取消分配视图控制器(通过弹出导航控制器的堆栈).
到目前为止,一切都是故意的.包含静态NSOperationQueue的类有一种方法可以返回操作,因此视图控制器不会保留它们.它们只是alloc/init/autoreleased并放入队列.
现在这也导致了这个问题.在视图控制器解除分配后,对NSOperation的激烈委托的任何调用都将导致错误的访问冲突.根据我的理解,无法检查指针上的对象是否已被解除分配,如本问题所述.
我能想到的一个修复是保留操作并在dealloc上将operation.delegate设置为nil.但这是我最不受欢迎的解决方案,因为它会引入许多额外的ivars /属性来跟踪.
因此,我的问题是,有没有其他方法可以解决这个问题,如果是这样,你能在这里草拟一个吗?
干杯,
EP.
解决方案:对我来说最好的方法是对Guiliano的回答略有不同:
在队列管理器中实现每个委托协议是不可行的(20多种不同的协议,使用50多种方法),因此我保留了直接委托分配.我改变的是进行分配呼叫的班级.这曾经是创建请求的类(和委托),但现在它被卸载到队列管理器.
除了将委托分配给操作之外,队列管理器还拥有辅助可变字典以跟踪委托/操作对.
每个委托实例都会调用一个[QueueManager invalidateDelegate:self]deallocation方法,然后查找属于该委托的请求并将其取消.然后还删除字典操作/委托对以允许适当地重新分配操作.
最后,当KVO观察isFinished每个操作的属性时,可变dict保持清洁,以确保所有操作保留计数在它们完成后实际解除分配.
感谢Guiliano提供使用KVO破解这一点的提示!
exc-bad-access delegation objective-c nsoperation nsoperationqueue
Apple的Grand Central Dispatch(GCD)非常棒,但仅适用于iOS 4.0或更高版本.Apple的文档说,"[A]序列化操作队列不提供与Grand Central Dispatch中的串行调度队列完全相同的行为"(因为队列不是FIFO,但顺序由依赖关系和优先级决定).
在GCD发布之前支持操作系统版本的同时,实现与GCD的串行调度队列相同效果的正确方法是什么?或者换句话说,在想要支持低于4.0的版本的iOS应用程序中处理简单后台处理(执行Web服务请求等)的推荐方法是什么?
objective-c nsoperationqueue grand-central-dispatch ios serial-processing
在什么情况下你更喜欢使用NSOperationQueueGCD?
根据我对这两者的有限经验,我认为NSOperationQueue你基本上可以控制有多少并发操作.
使用GCD,您无法执行此操作,因为您正在使用队列.除了你可以用多核处理器以某种方式模拟这个,虽然我仍然认为没有办法控制它.
multithreading cocoa-touch nsoperationqueue grand-central-dispatch ios
我已经创建了一个测试项目,我正在测试我的假设,NSOperation并NSOperationQueue在我的主项目中使用它们之前.
我的代码非常简单,所以我将在这里包含所有内容.这是在启用ARC的情况下使用命令行Foundation项目.
#import <Foundation/Foundation.h>
@interface Operation : NSOperation
@property (readwrite, strong) NSString *label;
- (id)initWithLabel: (NSString *)label;
@end
Run Code Online (Sandbox Code Playgroud)
#import "Operation.h"
@implementation Operation
- (void)main
{
NSLog( @"Operation %@", _label);
}
- (id)initWithLabel: (NSString *)label
{
if (( self = [super init] )) {
_label = label;
}
return self;
}
@end
Run Code Online (Sandbox Code Playgroud)
#import <Foundation/Foundation.h>
#import "Operation.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = …Run Code Online (Sandbox Code Playgroud) 新的Cloud Kit框架广泛使用NSOperation进行CRUD.这些操作的结果以块为单位返回.例如:
let fetchOperation = CKFetchRecordsOperation(recordIDs: [recordID1, recordId2])
fetchOperation.fetchRecordsCompletionBlock = {(dict: NSDictionary!, error: NSError!) -> Void in
// dict contains RecordId -> Record
// do something with the records here (if no error)
}
Run Code Online (Sandbox Code Playgroud)
我想链接其中的一些操作(依赖项),并将操作的结果传递给链中的下一个操作.简化示例来说明这一点(伪代码!):
let fetchOperation1 = CKFetchRecordsOperation(recordIDs: [recordID1, recordId2])
fetchOperation1.fetchRecordsCompletionBlock = {(dict: NSDictionary!, error: NSError!) -> Void in
if error {
// handle error
} else {
// dict contains RecordId -> Record
// let's pretend our records contain references to other records
// that we want to …Run Code Online (Sandbox Code Playgroud) 两个月前我开始编写一个新的iPhone应用程序,因此我创建了一个通用的RESTFul Web服务,它允许我拥有许多这些必要的功能,如用户身份验证,用户配置文件,友谊系统,媒体处理,消息传递系统等.在我看来,有几个用例可以将这个web服务重用于未来的iPhone应用程序.
有了这种心态,我决定为这个应用程序(以及所有未来的应用程序)编写一个静态库,处理所有繁重的工作,如媒体(图像,视频,声音)设置和处理,与Web服务通信,解析和映射的结果,处理CoreData等.
鉴于我的应用程序,有许多并行任务正在运行的情况(最坏的情况),例如用户当前更改他/她的个人资料图片,而应用程序将用户位置发送到服务器(在后台),并且新的推送通知是接收.
因此决定在NSOperation中封装每个逻辑操作(如SendUserLocation或GetCurrentFriendList)并将它们添加到serviceQueue(NSOperationQueue).
当操作成功从Web服务获得结果并且现在应该处理它时,每个操作都能够生成子任务.

典型的ServiceManager方法如下所示
- (void)activateFriendsSync:(id)observer onSuccess:(SEL)selector {
ELOSyncFriends *opSyncFriends = [[ELOSyncFriends alloc] initWithSM:self];
[self ELServiceLogger:opSyncFriends];
[serviceQueue addOperation:opSyncFriends];
if(observer) {
[self registerObserver:observer selector:selector name:opSyncFriends.notificationName];
}
}
Run Code Online (Sandbox Code Playgroud)
每个操作,请求(到服务器)和subTask都使用GUID作为notificationName,以在完成处理时通知父对象.如果操作中的所有内容都已完成,它会将通知发送回用户界面.
也就是说,添加和删除子任务的代码看起来像这样
- (void)removeSubTask:(NSNotification*)notification {
ELRequest *request = (ELRequest*)[notification object];
[subTasks removeObjectIdenticalTo:request.notificationName];
if([subTasks count] == 0) {
// all SubTaks done, send notification to parent
[serviceManager.notificationCenter postNotificationName:self.notificationName object:request];
}
}
- (NSString*)addSubTask {
NSString* newName = [self GetUUID];
[subTasks addObject:[newName retain]];
[serviceManager.notificationCenter addObserver:self selector:@selector(removeSubTask:) name:newName object:nil];
return newName;
}
- (NSString …Run Code Online (Sandbox Code Playgroud) architecture iphone objective-c nsoperation nsoperationqueue
我似乎dispatch_queue_t和NSOperationQueue队列之间有一些混淆.
默认情况下,AFNetworking AFImageRequestOperation将在应用程序的主线程上执行成功回调块.要更改此设置,请使用允许您选择运行回调的队列AFHTTPRequestOperation的属性successCallbackQueue.
我正在尝试在已经执行HTTP请求的相同后台队列/后台线程上执行成功回调.NSOperationQueue运行HTTP请求的主要线程也应该运行回调,而不是返回主线程,因为我需要使用一些返回的图像进行一些繁重的计算.
我的第一次尝试是设置successCallbackQueue为运行的NSOperationQueue实例AFImageRequestOperation.但是,successCallbackQueue属性是类型的dispatch_queue_t,所以我需要一种方法来获取我的实例的底层dispatch_queue_tNSOperation,如果有这样的事情.
这是可能的,还是我需要创建一个单独的dispatch_queue_t?
我问的原因:AFNetworking继承的有些奇怪NSOperation,但我们希望我们使用dispatch_queue_t队列进行回调.混合两种范式dispatch_queue_t和NSOperationQueue.
谢谢你的任何提示!
我很喜欢,NSOperationQueue但我有一些问题需要了解它的某些部分.
在objc.io的第二期中,他们回顾了NSOperationQueue,并提到它有两种队列,即主线程上运行的主队列和后台队列.他们提到你可以访问主队列,[NSOperation mainQueue]然后添加操作它.
它还提到你可以通过创建NSOperation的实例(潜在的子类)来添加到后台队列(我理解会更好?).
mainQueue,那么如何管理向后台队列添加任务呢?它还提到您可以控制与maxConcurrentOperationCount属性同时运行的操作量.
NSOperationQueueDefaultMaxConcurrentOperationCount,但如果我手动将它设置为一个特定的数字,它是否对应于一次可以运行的最大线程数?例如,如果iPhone上的处理器可以同时运行4个线程并且我将该属性设置为8,会发生什么?根据Apple关于NSOperation的文档,我们必须覆盖main非并发操作的start方法和并发操作的方法.但为什么?
nsoperationqueue ×10
nsoperation ×6
ios ×4
objective-c ×4
cocoa-touch ×2
iphone ×2
afnetworking ×1
architecture ×1
cloudkit ×1
cocoa ×1
concurrency ×1
dealloc ×1
delegation ×1
icloud ×1
ios8 ×1