@properties(MRC)的显式getter/setter

Sta*_*ich 7 memory-management objective-c

我在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;
}
Run Code Online (Sandbox Code Playgroud)

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

- (NSNumber *)count {
    return _count;
}

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

    _count = [newCount copy];
}
Run Code Online (Sandbox Code Playgroud)

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

我很感谢能够向我展示如何使用手动引用计数(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)
Run Code Online (Sandbox Code Playgroud)

Gab*_*lla 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];
        }
    }
Run Code Online (Sandbox Code Playgroud)

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

    - (NSNumber *)count {
        return _count;
    }

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

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];
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

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

正如你在这里读到的那样,getter中的retain/ autoreleasedance旨在防止另一个线程中的setter在返回之前释放该值.

4. @property (assign) NSNumber *count;

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

    - (void)setCount:(NSNumber *)count {
        @synchronized(self) {
            _count = count;
        }
    }
Run Code Online (Sandbox Code Playgroud)

注意:atomic是默认值.

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


Sta*_*ich 5

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

  1. 我对链接主题的研究:使用 MRC 的可变 ivar 的不可变属性
  2. @robmayoff 的评论
  3. objc运行时探索

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];
    }
}
Run Code Online (Sandbox Code Playgroud)

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

- (NSNumber *)count {
    return _count;
}

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

注意:不需要if (count != _count)检查,因为(copy)生成副本(objc 运行时源也有这种行为)。

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

- (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];
}
Run Code Online (Sandbox Code Playgroud)

4) @property (分配) NSNumber *count;

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

- (void)setCount:(NSNumber *)count {
    @synchronized(self) {
        _count = count;
    }
}
Run Code Online (Sandbox Code Playgroud)

PS 最近我对这种回到过去的手动引用计数进行了一些研究,让我与您分享以下我发现在该主题上最好的链接: