我正在尝试创建一个DownloadOperation子类NSOperation,以便异步下载数据。在我试图加入取消支持之前,一切似乎都很顺利。基本上,操作的NSURLSessionDownloadTask的完成处理程序似乎是在操作发布后调用的。它将与EXC_BAD_ACCESS在行weakSelf.state = kFinished上崩溃。
完整的示例项目如下:https://github.com/angstsmurf/DownloadOperationQueue。按Command+.在跑去撞车之后。
#import "DownloadOperation.h"
typedef enum OperationState : NSUInteger {
kReady,
kExecuting,
kFinished
} OperationState;
@interface DownloadOperation ()
@property NSURLSessionDownloadTask *task;
@property OperationState state;
@end
@implementation DownloadOperation
// default state is ready (when the operation is created)
@synthesize state = _state;
- (void)setState:(OperationState)state {
@synchronized(self) {
if (_state != state) {
[self willChangeValueForKey:@"isExecuting"];
[self willChangeValueForKey:@"isFinished"];
_state = state;
[self didChangeValueForKey: @"isExecuting"];
[self didChangeValueForKey: @"isFinished"];
}
}
}
- (OperationState)state {
@synchronized (self) {
return _state;
}
}
- (BOOL)isReady { return (self.state == kReady); }
- (BOOL)isExecuting { return (self.state == kExecuting); }
- (BOOL)isFinished { return (self.state == kFinished); }
- (BOOL)isAsynchronous {
return YES;
}
- (instancetype)initWithSession:(NSURLSession *)session downloadTaskURL:(NSURL *)downloadTaskURL completionHandler:(nullable void (^)(NSURL * _Nullable, NSURLResponse * _Nullable, NSError * _Nullable))completionHandler {
self = [super init];
if (self) {
__unsafe_unretained DownloadOperation *weakSelf = self;
// use weak self to prevent retain cycle
_task = [[NSURLSession sharedSession] downloadTaskWithURL:downloadTaskURL
completionHandler:^(NSURL * _Nullable localURL, NSURLResponse * _Nullable response, NSError * _Nullable error) {
/*
if there is a custom completionHandler defined,
pass the result gotten in downloadTask's completionHandler to the
custom completionHandler
*/
if (completionHandler) {
completionHandler(localURL, response, error);
}
/*
set the operation state to finished once
the download task is completed or have error
*/
weakSelf.state = kFinished;
}];
}
return self;
}
- (void)start {
/*
if the operation or queue got cancelled even
before the operation has started, set the
operation state to finished and return
*/
if (self.cancelled) {
self.state = kFinished;
return;
}
// set the state to executing
self.state = kExecuting;
NSLog(@"downloading %@", self.task.originalRequest.URL.absoluteString);
// start the downloading
[self.task resume];
}
-(void)cancel {
[super cancel];
// cancel the downloading
[self.task cancel];
}
@end发布于 2021-11-27 06:52:34
正如Scott在注释中指出的那样,weakSelf变量使用的正确关键字是__weak,而不是__unsafe_unretained。
https://stackoverflow.com/questions/69712151
复制相似问题