속성으로 선언 된 개인 직렬 큐가 있는데 아주 이상한 상황이 있습니다.dispatch_queue_t 속성에 getter를 호출하면 충돌이 발생합니다.
속성을 dispatch_async하면 충돌합니다 (EXC_BAD_ACCESS (code = EXC_i386_GPFLT)). 디버깅을 한 후에 getter가 호출 되었기 때문에 디버깅이 필요하다는 것을 알았습니다. getter가 호출되지 않으면 충돌이 발생하지 않습니다. 또한 self.queue가 호출 된 두 번째 시간은 항상 충돌합니다. 아래의 두 번째 예를 참조하십시오.
처음으로 합성 된 getter 호출이 어떻게 든 ivar이 과도하게 릴리스 된 것처럼 보입니다.
iOS 9 이상을 타겟팅하므로 OS_OBJECT_USE_OBJC을 (를) 확인하지 않습니다.
예 1)이 작동하지 않습니다
@interface Test()
@property (nonatomic, strong) dispatch_queue_t initQueue;
@end
- (instancetype)init {
self = [super init];
if (self) {
_initQueue = dispatch_queue_create("com.test.initQueue", DISPATCH_QUEUE_SERIAL);
}
return self;
}
- (void)onCompletion:(void (^)())completion {
// Crashes here - EXC_BAD_ACCESS (code=EXC_i386_GPFLT)
// the second time self.queue is accessed - either by subsequent call into
// this method, or by adding NSLog(@"%@", self.queue) before this line.
dispatch_async(self.initQueue, ^{
...
});
}
예 2) 이것은 또한 작동하지 않습니다
@interface Test()
@property (nonatomic, strong) dispatch_queue_t initQueue;
@end
- (instancetype)init {
self = [super init];
if (self) {
_initQueue = dispatch_queue_create("com.test.initQueue", DISPATCH_QUEUE_SERIAL);
}
return self;
}
- (void)onCompletion:(void (^)())completion {
NSLog(@"%@", self.initQueue);
// Crashes below - EXC_BAD_INSTRUCTION (code=EXC_i386_INVOP, subcode=0x0)
NSLog(@"%@", self.initQueue);
}
예 3) 그것은 작동 내가 게터를 사용하여 멀리있는 경우 :
@interface Test()
@property (nonatomic, strong) dispatch_queue_t initQueue;
@end
- (instancetype)init {
self = [super init];
if (self) {
_initQueue = dispatch_queue_create("com.test.initQueue", DISPATCH_QUEUE_SERIAL);
}
return self;
}
- (void)onCompletion:(void (^)())completion {
// Works fine
dispatch_async(_initQueue, ^{
...
});
}
예 4) 나는 게터 공급하는 경우에도 작동합니다
012,351을@interface Test()
@property (nonatomic, strong) dispatch_queue_t initQueue;
@end
- (instancetype)init {
self = [super init];
if (self) {
_initQueue = dispatch_queue_create("com.test.initQueue", DISPATCH_QUEUE_SERIAL);
}
return self;
}
- (dispatch_queue_t)initQueue {
return _initQueue;
}
- (void)onCompletion:(void (^)())completion {
// Works fine
dispatch_async(self.initQueue, ^{
...
});
}
예 5) 속성 대신 대기열에 ivar를 사용하거나 self.initQueue에 기본 대기열이 할당 된 경우에도 작동합니다.
이 동작의 이유는 무엇입니까?
다른 오픈 소스 라이브러리는 getter와 함께 dispatch_queue_t에 대한 속성을 사용하고 있으며 전혀 문제가 없습니다. 예 : 원래 재산 initQueue
라는 이름의 코멘트를 https://github.com/rs/SDWebImage/blob/7e0964f8d90dcd80d535c52dd9f6d5fa7432052b/SDWebImage/SDImageCache.m#L57
당신이 말한 것처럼 그것을 사용하여 라이브러리의 링크를 제공 할 수 있습니까? 왜 그 게터를 공급할 수 없습니까? –
예제 코드는 내 자신의 코드입니다. 비슷한 코드를 사용하는 다른 라이브러리를 보았지만 내 문제는 발생하지 않았습니다. – Boon
다음은 잘 동작하는 기존 코드 예제입니다. https://github.com/rs/SDWebImage/blob/7e0964f8d90dcd80d535c52dd9f6d5fa7432052b/SDWebImage/SDImageCache.m#L57 – Boon