In ObjectiveC, is it necessary to declare a strong copy vs for the readonly property?

In Objective-C, it is common to declare an NSString / NSArray / NSDictionary as a copy, does this need to be done for the readonly property or is there no difference? If the NSString is read-only, it will never be set, so declaring it strong or a copy will have the same effect?

// use a strong copy here and it will work the same since it will never be copied?

@property (non-atomic, read-only) NSString * string;

+3


source to share


3 answers


If it is indeed read-only, then you do not need to specify it. If you are going to do it privately to be readwrite

, then you want to point it out. It readonly

has no effect for properties , since the setter will not be created.



+5


source


You are correct, but there are some things to consider. This is good since your property is an immutable object. However, this is not always the case.

The first example I come across a lot is when you have an actually mutable object inside your implementation. As a property, the declared NSArray in the implementation can actually be an NSMutableArray. The strong reference getter property for it will return a pointer to this NSMutableArray. And at some point you will run into a situation when you request an NSArray from an object, work with it for a while and, boom !!! - does your NSArray have different elements of its quantity? What the heck? In this case it is better idea to copy your internal implementation used by NSMutableArray in getter.

Another example is some model object

@interface Person : NSObject <NSCopying>
@property NSString *name;
@property NSDate   *birthdate;
@end

      

And you have another interface with the property



@property (strong, readonly) Person *person;

      

Yes, you will not assign another object to this property. However, you will be able to change your fields, so it will represent a completely different face. If you don't want this behavior, make this property copy

. Or make it private with accessor methods to get its fields

- (id) getHiddenPersonPropertyValueForKey:(NSString *)personPropertyKey;

      

Or in any other way

0


source


If the property represents a truly immutable value ( NSArray

, NSIndexSet

etc.), then just readonly

fine, since it will be returned immutable as is.

But in case your private ivar is mutable ( NSMutableArray

ivar vs property NSArray

type), you must return a copy to prevent future internal changes from leaking to the caller state.

@interface MyObject : NSObject {
    NSMutableArray *_array;
}

@property(nonatomic, readonly) NSArray *array;
// -or-
- (NSArray *)array;

@end

      

and

@implementation

@dynamic array; // only if @property was declared in interface

- (NSArray *)array
{
    return [_array copy];
}

@end

      

The caller then stores the value of the property and expects it not to change even without an explicit copy:

self.array = [myObject array]; // e.g. 1 element
[myObject addElementToArray:@(42)];
NSLog(@"%@", self.array); // still 1 element

      

0


source







All Articles