我在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)
答案 0 :(得分:12)
@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];
}
}
@property (nonatomic, copy) NSNumber *count;
- (NSNumber *)count {
return _count;
}
- (void)setCount:(NSNumber *)count {
NSNumber *oldCount = _count;
_count = [count copy];
[_oldCount release];
}
@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在返回之前释放该值。
@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) @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。最近我对这个回到过去的手动参考计数做了一些研究,让我与大家分享以下链接,我发现这个链接是最好的: