Я обнаружил, что количество сохраненных объектов, созданных внутри блока @synchronized
, будет отличаться от тех, которые созданы за пределами блока @synchronized
.
Случай 1: создать внутри блока @synchronized
, количество сохранений наблюдателя равно 2:
- (NSUInteger)mv_observeKeyPath:(NSString *)keyPath
withBlock:(MVKVOBlock)block
options:(NSKeyValueObservingOptions)options {
@synchronized (lock) {
MVKVOProxy *observer = [MVKVOProxy observerWithTarget:self keyPath:keyPath block:block];
// po [observer performSelector:@selector(retainCount)] is 2
[self addObserver:observer forKeyPath:keyPath options:options context:NULL];
return observer.observerID;
}
}
Случай 2: создать вне блока @synchronized
, сохранить счет наблюдателяравно 1:
- (NSUInteger)mv_observeKeyPath:(NSString *)keyPath
withBlock:(MVKVOBlock)block
options:(NSKeyValueObservingOptions)options {
MVKVOProxy *observer = [MVKVOProxy observerWithTarget:self keyPath:keyPath block:block];
@synchronized (lock) {
// po [observer performSelector:@selector(retainCount)] is 1
[self addObserver:observer forKeyPath:keyPath options:options context:NULL];
return observer.observerID;
}
}
Я знаю, что объект, возвращаемый методом, будет заключен в objc_retainAutoreleasedReturnValue
и objc_autoreleaseReturnValue
.Он используется для оптимизации, чтобы исключить бесполезные вызовы функций: [[obj autorelase] retain]
.
Определение метода objc_retainAutoreleasedReturnValue
:
id objc_retainAutoreleasedReturnValue(id obj)
{
if (acceptOptimizedReturn() == ReturnAtPlus1) return obj;
return objc_retain(obj);
}
Я отладил и вошел в код сборки и обнаружил, что, только в случае 2, objc_retain
вызываться не будет.
Метод objc_autoreleaseReturnValue
of:
id objc_autoreleaseReturnValue(id obj)
{
if (prepareOptimizedReturn(ReturnAtPlus1)) return obj;
return objc_autorelease(obj);
}
В обоих случаях будет вызываться objc_autorelease
.
Следовательно, в случае 1 стек вызовов методов равен [[observer autorelaase] retain]
, в случае 2 - стек вызовов методов [observer autorelaase]
.
Разве это не странно?Почему @synchronized
влияет на ARC?