标签: nsoperationqueue

正确释放NSOperationQueue

我想知道如果仍有一些操作正在运行,那么解除一个ivar NSOperationQueue的正确方法是什么,这通常会在用户突然退出应用程序时发生.在一些例子中,我看到使用了waitUntilAllOperationsAreFinished,如下所示:


- (void)dealloc {
    [_queue cancelAllOperations];
    [_queue waitUntilAllOperationsAreFinished];
    [_queue release];
    ...

然而,许多人建议避免这样做,因为它会挂起运行循环.那么发布的正确方法是_queue什么?如果我不等待操作完成并继续发布,会发生什么?

iphone dealloc nsoperation nsoperationqueue

11
推荐指数
1
解决办法
2333
查看次数

如何正确处理排队的nsoperation的解除分配代理

在我当前的项目中,几个视图控制器(如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

11
推荐指数
1
解决办法
2147
查看次数

iOS 3.x中等效的GCD串行调度队列

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

11
推荐指数
1
解决办法
2385
查看次数

NSOperationQueue与GCD

在什么情况下你更喜欢使用NSOperationQueueGCD?

根据我对这两者的有限经验,我认为NSOperationQueue你基本上可以控制有多少并发操作.

使用GCD,您无法执行此操作,因为您正在使用队列.除了你可以用多核处理器以某种方式模拟这个,虽然我仍然认为没有办法控制它.

multithreading cocoa-touch nsoperationqueue grand-central-dispatch ios

11
推荐指数
2
解决办法
6093
查看次数

NSOperationQueue何时开始其第一次操作?

我已经创建了一个测试项目,我正在测试我的假设,NSOperationNSOperationQueue在我的主项目中使用它们之前.

我的代码非常简单,所以我将在这里包含所有内容.这是在启用ARC的情况下使用命令行Foundation项目.

Operation.h

#import <Foundation/Foundation.h>

@interface Operation : NSOperation

@property (readwrite, strong) NSString *label;

- (id)initWithLabel: (NSString *)label;

@end
Run Code Online (Sandbox Code Playgroud)

Operation.m

#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)

的main.m

#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)

cocoa cocoa-touch nsoperationqueue

11
推荐指数
1
解决办法
8896
查看次数

如何在NSOperation依赖关系之间传递结果?

新的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)

nsoperation nsoperationqueue icloud ios8 cloudkit

11
推荐指数
1
解决办法
1626
查看次数

具有NSOperations的iOS应用程序架构

两个月前我开始编写一个新的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

10
推荐指数
1
解决办法
2438
查看次数

从NSOperationQueue获取底层dispatch_queue_t

我似乎dispatch_queue_tNSOperationQueue队列之间有一些混淆.

默认情况下,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_tNSOperationQueue.

谢谢你的任何提示!

nsoperationqueue grand-central-dispatch ios afnetworking

10
推荐指数
2
解决办法
6023
查看次数

使用NSOperationQueue,如何添加到后台队列而不是main,以及控制操作量如何工作?

我很喜欢,NSOperationQueue但我有一些问题需要了解它的某些部分.

objc.io的第二期中,他们回顾了NSOperationQueue,并提到它有两种队列,即主线程上运行的主队列和后台队列.他们提到你可以访问主队列,[NSOperation mainQueue]然后添加操作它.

  • 你通常不想这样做,对吗?如果它在主线程上运行,它是否会阻止主线程执行其他任务?它不会与其他任务同时运行吗?

它还提到你可以通过创建NSOperation的实例(潜在的子类)来添加到后台队列(我理解会更好?).

  • 我是否保存了为操作创建的NSOperationQueue的引用,以便创建更多操作?我假设没有像背景队列那样的单例mainQueue,那么如何管理向后台队列添加任务呢?

它还提到您可以控制与maxConcurrentOperationCount属性同时运行的操作量.

  • 我知道你通常把它设置为NSOperationQueueDefaultMaxConcurrentOperationCount,但如果我手动将它设置为一个特定的数字,它是否对应于一次可以运行的最大线程数?例如,如果iPhone上的处理器可以同时运行4个线程并且我将该属性设置为8,会发生什么?

concurrency objective-c nsoperation nsoperationqueue ios

10
推荐指数
1
解决办法
6482
查看次数

NSOperation,start vs main

根据Apple关于NSOperation的文档,我们必须覆盖main非并发操作的start方法和并发操作的方法.但为什么?

nsoperation nsoperationqueue

10
推荐指数
2
解决办法
2516
查看次数