@properties(MRC)的显式getter / setter

时间:2014-02-15 18:52:14

标签: objective-c memory-management

我在2012年中期开始使用Objective-C语言进行编程,当时ARC取代MRC作为一般做法,使后者几乎不需要学习。

现在我正在尝试了解MRC的一些基础知识,以加深我对Objective-C中内存管理的了解。

我现在感兴趣的是如何用手明确地为声明的getters/setters@properties

此时我发现的唯一合理的例子来自Apple的“高级内存管理编程指南”:

@interface Counter : NSObject {
    NSNumber *_count;
}
@property (nonatomic, retain) NSNumber *count;
@end;

- (NSNumber *)count {
    return _count;
}

- (void)setCount:(NSNumber *)newCount {
    [newCount retain];

    [_count release];

    _count = newCount;
}

我的猜测是,为了(非原子,复制),我应该写一些类似的东西:

- (NSNumber *)count {
    return _count;
}

- (void)setCount:(NSNumber *)newCount {
    [_count release];

    _count = [newCount copy];
}

所以问题是我不确定的其他组合:

我很感谢能够向我展示如何使用手动引用计数(MRC)为以下@property声明编写显式getter / setter的示例:

1. @property (nonatomic, retain) NSNumber *count;
2. @property (nonatomic, copy) NSNumber *count;
3. @property (atomic, retain) NSNumber *count;
4. @property (assign) NSNumber *count;
5. What else is used often under MRC? (please share, if any other combinations exist)

2 个答案:

答案 0 :(得分:12)

1。 @property (nonatomic, retain) NSNumber *count;

    - (NSNumber *)count {
        return _count;
    }

    - (void)setCount:(NSNumber *)count {
        if (count != _count) {
            NSNumber *oldCount = _count;
            // retain before releasing the old one, in order to avoid other threads to
            // ever accessing a released object through the `_count` pointer.
            _count = [count retain];
            // safely release the old one.
            [_oldCount release];
        }
    }

2。 @property (nonatomic, copy) NSNumber *count;

    - (NSNumber *)count {
        return _count;
    }

    - (void)setCount:(NSNumber *)count {
        NSNumber *oldCount = _count;
        _count = [count copy];
        [_oldCount release];
    }

3。 @property (atomic, retain) NSNumber *count;

    - (NSNumber *)count {
        @synchronized(self) {
            NSNumber *tmpCount = [_count retain];
        }
        return [tmpCount autorelease];
    }

    - (void)setCount:(NSNumber *)count {

        @synchronized(self) {
            if (count != _count) {
                [_count release];
                _count = [count retain];
            }
        }
    }

注意:Objective-C 2.0规范提到锁是在内部使用的,但它没有具体说明。你在上面看到的,大致是原子吸气剂/设定器的样子,但它可能不准确。

正如您可以阅读here,getter中的retain / autorelease舞蹈是为了防止另一个线程中的setter在返回之前释放该值。

4。 @property (assign) NSNumber *count;

    - (NSNumber *)count {
        @synchronized(self) {
            NSNumber *tmpCount = _count;
        }
        return tmpCount;
    }

    - (void)setCount:(NSNumber *)count {
        @synchronized(self) {
            _count = count;
        }
    }

注意:atomic是默认值。

属性的其他可能修饰符是readwrite / readonly,但它们只会产生合成或不合成的效果。

答案 1 :(得分:3)

虽然@Gabriele答案是正确的,但我想写自己的答案,其中包含:

  1. 我对相关主题的研究:Immutable property for mutable ivar using MRC
  2. @robmayoff的评论
  3. 探索objc runtime

  4. 1) @property (nonatomic, retain) NSNumber *count;

    - (NSNumber *)count {
        return _count;
    }
    
    - (void)setCount:(NSNumber *)count {
        if (count != _count) {
            id oldValue = _count;
            _count = [count retain];
            [oldValue release];
        }
    }
    

    2) @property(非原子,复制)NSNumber *计数;

    - (NSNumber *)count {
        return _count;
    }
    
    - (void)setCount:(NSNumber *)count {
        id oldValue = _count;
        _count = [count copy]; // retains (+1)
        [oldValue release];
    }
    

    注意:if (count != _count)检查不需要检查,因为(复制)会产生副本(objc运行时源也会这样)。

    3) @property(原子,保留)NSNumber *计数;

    - (NSNumber *)count {
        NSNumber *count;
        @synchronized(self) {
            count = [_count retain]; // +1
        }
        return [count autorelease]; // delayed -1
    }
    
    - (void)setCount:(NSNumber *)count {
        id oldValue;
        @synchronized(self) {
            oldValue = _count;
            _count = [count retain];
        }
        [oldValue release];
    }
    

    4) @property(assign)NSNumber * count;

    - (NSNumber *)count {
        NSNumber *count;
        @synchronized(self) {
            count = _count;
        }
        return count;
    }
    
    - (void)setCount:(NSNumber *)count {
        @synchronized(self) {
            _count = count;
        }
    }
    

    P.S。最近我对这个回到过去的手动参考计数做了一些研究,让我与大家分享以下链接,我发现这个链接是最好的: