Explicit getters/setters for @properties (MRC)

前端 未结 2 1954

I\'ve started programming on Objective-C language in the middle of 2012 in the time when ARC replaced MRC as a general practice making the latter almost unnecessary to learn

相关标签:
2条回答
  • 2020-12-15 01:06

    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];
                }
            }
        }
    

    Note: the Objective-C 2.0 specification, mentions that locks are used internally, but it doesn't specify exactly how. What you see above, is roughly what an atomic getter/setter would look like, but it might not be accurate.

    As you can read here, the retain/autorelease dance in the getter is meant to prevent a setter in another thread releasing the value before we can return it.

    4. @property (assign) NSNumber *count;

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

    Note: atomic is the default.

    Other possible modifiers for properties are readwrite/readonly, but they will just have the effect of synthesizing or not the setter.

    0 讨论(0)
  • 2020-12-15 01:17

    While @Gabriele answer is correct, I want to write my own answer containing:

    1. My research in linked topic: Immutable property for mutable ivar using MRC
    2. Comment by @robmayoff
    3. exploration of objc runtime

    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 (nonatomic, copy) NSNumber *count;

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

    Note: no need in if (count != _count) check since (copy) produces copies (objc runtime source also behaves this way).

    3) @property (atomic, retain) 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];
    }
    

    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. Recently I did some research for this back-to-the-past Manual Reference Counting, let me share with you the following links which I found to be the best on this topic:

    • Advanced Memory Management Programming Guide (this is the MUST)

    • An In-depth Look At Manual Memory Management In Objective-C (this one too!)

    • What clang taught us about Objective-C properties

    • Memory and thread-safe custom property methods

    • Source code of objc runtime.

    0 讨论(0)
提交回复
热议问题