gpt4 book ai didi

ios - 取消后 NSOperation 保留在 NSOperationQueue 中

转载 作者:行者123 更新时间:2023-11-29 10:45:30 32 4
gpt4 key购买 nike

我使用 NSOperation 和 NSOperationQueue 执行下载图像。每个操作都保留一个 StoreThumbRequest 对象,封装所有请求特定数据,包括目标 View ,等待图像。同时,该 View 保留了一个 NSOperation 对象,用于在重用或释放期间取消操作。这个保留循环在适当的时候在“取消”和“主要”方法中被小心地打破。

我发现在为其 maxConcurrentOperationsCount 设置限制时,NSOperation 保留在 NSOperationQueue 中。达到此限制会阻止调用新 NSOperations 的“main”方法。 NSOperation 只有在被取消时才会保留在队列中。如果它设法完成了它的任务,它就会从它的 NSOperationQueue 中优雅地移除。

我的 NSOperations 是非并发的,没有依赖性。

有什么建议吗?提前致谢

#import "StoreThumbLoadOperation.h"
#import "StoreThumbCache.h"

@interface StoreThumbLoadOperation () <NSURLConnectionDelegate> {
StoreThumbRequest *_request;
NSMutableData *_downloadedData;
NSURLConnection *_connection;
NSPort *_port;
}

@end

@implementation StoreThumbLoadOperation

-(id)initWithRequest: (StoreThumbRequest *)request
{
NSParameterAssert(request);
self = [super init];
if (self) {
_request = request;
}
return self;
}

-(void)main
{
NSURL *url = ...;

NSURLRequest *request = [NSURLRequest requestWithURL: url];
_connection = [[NSURLConnection alloc] initWithRequest: request delegate: self startImmediately: NO];

NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
_port = [NSMachPort port];
[runLoop addPort: _port forMode: NSDefaultRunLoopMode];
[_connection scheduleInRunLoop: runLoop forMode: NSDefaultRunLoopMode];
[_connection start];
[runLoop run];
}

-(void)cancel
{
[super cancel];

[_connection unscheduleFromRunLoop: [NSRunLoop currentRunLoop] forMode: NSDefaultRunLoopMode];
[_connection cancel];
_request.thumbView.operation = nil; //break retain loop
[[NSRunLoop currentRunLoop] removePort: _port forMode: NSDefaultRunLoopMode];
}

#pragma mark - NSURLConnectionDelegate

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
_downloadedData = [NSMutableData new];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[_downloadedData appendData: data];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
if (_connection == connection) {
NSFileManager *fileManager = [NSFileManager new];
NSString *pathForDownloadedThumb = [[StoreThumbCache sharedCache] thumbPathOnRequest: _request];
NSString *pathForContainigDirectory = [pathForDownloadedThumb stringByDeletingLastPathComponent];
if (! [fileManager fileExistsAtPath: pathForContainigDirectory]) {
//create a directory if required
[fileManager createDirectoryAtPath: pathForContainigDirectory withIntermediateDirectories: YES attributes: nil error: nil];
}

if (! self.isCancelled) {
[_downloadedData writeToFile: pathForDownloadedThumb atomically: YES];
UIImage *image = [UIImage imageWithContentsOfFile: pathForDownloadedThumb];

//an image may be empty
if (image) {
if (! self.isCancelled) {
[[StoreThumbCache sharedCache] setThumbImage: image forKey: _request.cacheKey];

if (_request.targetTag == _request.thumbView.tag) {
dispatch_async(dispatch_get_main_queue(), ^{
_request.thumbView.image = image;
});
}
}
}
_request.thumbView.operation = nil; //break retain loop
[[NSRunLoop currentRunLoop] removePort: _port forMode: NSDefaultRunLoopMode];
}
}
}


- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
if (error.code != NSURLErrorCancelled) {
#ifdef DEBUG
NSLog(@"failed downloading thumb for name: %@ with error %@", _request.thumbName, error.localizedDescription);
#endif

_request.thumbView.operation = nil;
[[NSRunLoop currentRunLoop] removePort: _port forMode: NSDefaultRunLoopMode];
}
}

@end

我明白,一个 NSOperation 不应该立即从它的 NSOperationQueue 中移除。但它会无限期地保留在那里

来自 NSOperation 取消方法文档

This method does not force your operation code to stop. Instead, it updates the object’s internal flags to reflect the change in state.

最佳答案

我相信这是因为运行循环(当您打算结束操作时没有删除它)使操作保持事件状态。

替换以下行的所有实例:

[[NSRunLoop currentRunLoop] removePort: _port forMode: NSDefaultRunLoopMode];

用这个:

[[NSRunLoop currentRunLoop] removePort: _port forMode: NSDefaultRunLoopMode];
CFRunLoopStop(CFRunLoopGetCurrent());

关于ios - 取消后 NSOperation 保留在 NSOperationQueue 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22556220/

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