ChatGPT解决这个技术问题 Extra ChatGPT

@property retain, assign, copy, nonatomic in Objective-C

As someone that's new to Objective-C can someone give me an overview of the retain, assign, copy and any others I'm missing, that follow the @property directive? What are they doing and why would I want to use one over another?

Apple's name for these is "attributes" or "property attributes"

l
liza

Before you know about the attributes of @property, you should know what is the use of @property.

@property offers a way to define the information that a class is intended to encapsulate. If you declare an object/variable using @property, then that object/variable will be accessible to other classes importing its class.

If you declare an object using @property in the header file, then you have to synthesize it using @synthesize in the implementation file. This makes the object KVC compliant. By default, compiler will synthesize accessor methods for this object.

accessor methods are : setter and getter.

Example: .h

@interface XYZClass : NSObject
@property (nonatomic, retain) NSString *name;
@end

.m

@implementation XYZClass
@synthesize name;
@end

Now the compiler will synthesize accessor methods for name.

XYZClass *obj=[[XYZClass alloc]init];
NSString *name1=[obj name]; // get 'name'
[obj setName:@"liza"]; // first letter of 'name' becomes capital in setter method

List of attributes of @property atomic, nonatomic, retain, copy, readonly, readwrite, assign, strong, getter=method, setter=method, unsafe_unretained

atomic is the default behavior. If an object is declared as atomic then it becomes thread-safe. Thread-safe means, at a time only one thread of a particular instance of that class can have the control over that object.

If the thread is performing getter method then other thread cannot perform setter method on that object. It is slow.

@property NSString *name; //by default atomic`
@property (atomic)NSString *name; // explicitly declared atomic`

nonatomic is not thread-safe. You can use the nonatomic property attribute to specify that synthesized accessors simply set or return a value directly, with no guarantees about what happens if that same value is accessed simultaneously from different threads.

For this reason, it’s faster to access a nonatomic property than an atomic one.

@property (nonatomic)NSString *name;   

retain is required when the attribute is a pointer to an object.

The setter method will increase retain count of the object, so that it will occupy memory in autorelease pool.

@property (retain)NSString *name;

copy If you use copy, you can't use retain. Using copy instance of the class will contain its own copy.

Even if a mutable string is set and subsequently changed, the instance captures whatever value it has at the time it is set. No setter and getter methods will be synthesized.

@property (copy) NSString *name;

now,

NSMutableString *nameString = [NSMutableString stringWithString:@"Liza"];    
xyzObj.name = nameString;    
[nameString appendString:@"Pizza"]; 

name will remain unaffected.

readonly If you don't want to allow the property to be changed via setter method, you can declare the property readonly.

Compiler will generate a getter, but not a setter.

@property (readonly) NSString *name;

readwrite is the default behavior. You don't need to specify readwrite attribute explicitly.

It is opposite of readonly.

@property (readwrite) NSString *name;

assign will generate a setter which assigns the value to the instance variable directly, rather than copying or retaining it. This is best for primitive types like NSInteger and CGFloat, or objects you don't directly own, such as delegates.

Keep in mind retain and assign are basically interchangeable when garbage collection is enabled.

@property (assign) NSInteger year;

strong is a replacement for retain.

It comes with ARC.

@property (nonatomic, strong) AVPlayer *player; 

getter=method If you want to use a different name for a getter method, it’s possible to specify a custom name by adding attributes to the property.

In the case of Boolean properties (properties that have a YES or NO value), it’s customary for the getter method to start with the word “is”

@property (getter=isFinished) BOOL finished;

setter=method If you want to use a different name for a setter method, it’s possible to specify a custom name by adding attributes to the property.

The method should end with a colon.

@property(setter = boolBool:) BOOL finished;

unsafe_unretained There are a few classes in Cocoa and Cocoa Touch that don’t yet support weak references, which means you can’t declare a weak property or weak local variable to keep track of them. These classes include NSTextView, NSFont and NSColorSpace,etc. If you need to use a weak reference to one of these classes, you must use an unsafe reference.

An unsafe reference is similar to a weak reference in that it doesn’t keep its related object alive, but it won’t be set to nil if the destination object is deallocated.

@property (unsafe_unretained) NSObject *unsafeProperty;

If you need to specify multiple attributes, simply include them as a comma-separated list, like this:

@property (readonly, getter=isFinished) BOOL finished;

Additionally, weak means that there is not a reference count to the referenced to the object, but that it is referenced at all, or not referenced at all. Kind of like "yep, something referenced me" vs. "9 references to me exist" (which is what strong is like).
Ignore the line in the answer regarding garbage collection, as garbage collection is deprecated in Mac OS X and non-existent in iOS per Apple documentation.
"Note: Property atomicity is not synonymous with an object’s thread safety." - from developer.apple.com/library/mac/documentation/Cocoa/Conceptual/…
"If you declare an object using @property in the header file, then you have to synthesize it using @synthesize in the implementation file." Not always. For example, "By default, a readwrite property will be backed by an instance variable, which will again be synthesized automatically by the compiler." From doc.
@liza This is an excellent answer. Why is this not the accepted answer. It conveys a far more knowledgeable explanation than the currently accepted answer. I do not understand StackOverflow sometimes?
B
Blamdarot

The article linked to by MrMage is no longer working. So, here is what I've learned in my (very) short time coding in Objective-C:

nonatomic vs. atomic - "atomic" is the default. Always use "nonatomic". I don't know why, but the book I read said there is "rarely a reason" to use "atomic". (BTW: The book I read is the BNR "iOS Programming" book.)

readwrite vs. readonly - "readwrite" is the default. When you @synthesize, both a getter and a setter will be created for you. If you use "readonly", no setter will be created. Use it for a value you don't want to ever change after the instantiation of the object.

retain vs. copy vs. assign

"assign" is the default. In the setter that is created by @synthesize, the value will simply be assigned to the attribute. My understanding is that "assign" should be used for non-pointer attributes.

"retain" is needed when the attribute is a pointer to an object. The setter generated by @synthesize will retain (aka add a retain count) the object. You will need to release the object when you are finished with it.

"copy" is needed when the object is mutable. Use this if you need the value of the object as it is at this moment, and you don't want that value to reflect any changes made by other owners of the object. You will need to release the object when you are finished with it because you are retaining the copy.


@Blamdarot - do I need to release it with ARC as well
@Odelya - No. If you release while using ARC, I believe you'll get a compiler error.
"Always use nonatomic" is bad advice. You should know what you're giving up when you use nonatomic.
Agreed. In particular, a lot of people don't seem to know that nonatomic values aren't retain-autoreleased by the getter. nonatomic is often appropriate, but cargo cult programming rarely is.
Advising to leave the default atomic is just as bad as advising nonatomic. Neither choice is the "correct" one, so the language designers opted for the safer of the two solutions. In fact nonatomic is generally the better choice as it omits extremely expensive thread locks. The only reason to use atomic is if your property might be set from multiple threads (in which case omitting it can lead to an over-release or a leak).
C
Community

After reading many articles I decided to put all the attributes information together:

atomic //default nonatomic strong=retain //default weak= unsafe_unretained retain assign //default unsafe_unretained copy readonly readwrite //default

Below is a link to the detailed article where you can find these attributes.

Many thanks to all the people who give best answers here!!

Variable property attributes or Modifiers in iOS

Here is the Sample Description from Article

atomic -Atomic means only one thread access the variable(static type). -Atomic is thread safe. -but it is slow in performance -atomic is default behavior -Atomic accessors in a non garbage collected environment (i.e. when using retain/release/autorelease) will use a lock to ensure that another thread doesn't interfere with the correct setting/getting of the value. -it is not actually a keyword.

Example :

@property (retain) NSString *name;

@synthesize name;

nonatomic -Nonatomic means multiple thread access the variable(dynamic type). -Nonatomic is thread unsafe. -but it is fast in performance -Nonatomic is NOT default behavior,we need to add nonatomic keyword in property attribute. -it may result in unexpected behavior, when two different process (threads) access the same variable at the same time.

Example:

@property (nonatomic, retain) NSString *name;

@synthesize name;

Explain:

Suppose there is an atomic string property called "name", and if you call [self setName:@"A"] from thread A, call [self setName:@"B"] from thread B, and call [self name] from thread C, then all operation on different thread will be performed serially which means if one thread is executing setter or getter, then other threads will wait. This makes property "name" read/write safe but if another thread D calls [name release] simultaneously then this operation might produce a crash because there is no setter/getter call involved here. Which means an object is read/write safe (ATOMIC) but not thread safe as another threads can simultaneously send any type of messages to the object. Developer should ensure thread safety for such objects.

If the property "name" was nonatomic, then all threads in above example - A,B, C and D will execute simultaneously producing any unpredictable result. In case of atomic, Either one of A, B or C will execute first but D can still execute in parallel.

strong (iOS4 = retain ) -it says "keep this in the heap until I don't point to it anymore" -in other words " I'am the owner, you cannot dealloc this before aim fine with that same as retain" -You use strong only if you need to retain the object. -By default all instance variables and local variables are strong pointers. -We generally use strong for UIViewControllers (UI item's parents) -strong is used with ARC and it basically helps you , by not having to worry about the retain count of an object. ARC automatically releases it for you when you are done with it.Using the keyword strong means that you own the object.

Example:

@property (strong, nonatomic) ViewController *viewController;

@synthesize viewController;

weak (iOS4 = unsafe_unretained ) -it says "keep this as long as someone else points to it strongly" -the same thing as assign, no retain or release -A "weak" reference is a reference that you do not retain. -We generally use weak for IBOutlets (UIViewController's Childs).This works because the child object only needs to exist as long as the parent object does. -a weak reference is a reference that does not protect the referenced object from collection by a garbage collector. -Weak is essentially assign, a unretained property. Except the when the object is deallocated the weak pointer is automatically set to nil

Example :

@property (weak, nonatomic) IBOutlet UIButton *myButton;

@synthesize myButton;

Strong & Weak Explanation, Thanks to BJ Homer:

Imagine our object is a dog, and that the dog wants to run away (be deallocated). Strong pointers are like a leash on the dog. As long as you have the leash attached to the dog, the dog will not run away. If five people attach their leash to one dog, (five strong pointers to one object), then the dog will not run away until all five leashes are detached. Weak pointers, on the other hand, are like little kids pointing at the dog and saying "Look! A dog!" As long as the dog is still on the leash, the little kids can still see the dog, and they'll still point to it. As soon as all the leashes are detached, though, the dog runs away no matter how many little kids are pointing to it. As soon as the last strong pointer (leash) no longer points to an object, the object will be deallocated, and all weak pointers will be zeroed out. When we use weak? The only time you would want to use weak, is if you wanted to avoid retain cycles (e.g. the parent retains the child and the child retains the parent so neither is ever released).

retain = strong -it is retained, old value is released and it is assigned -retain specifies the new value should be sent -retain on assignment and the old value sent -release -retain is the same as strong. -apple says if you write retain it will auto converted/work like strong only. -methods like "alloc" include an implicit "retain"

Example:

@property (nonatomic, retain) NSString *name;

@synthesize name;

assign -assign is the default and simply performs a variable assignment -assign is a property attribute that tells the compiler how to synthesize the property's setter implementation -I would use assign for C primitive properties and weak for weak references to Objective-C objects.

Example:

@property (nonatomic, assign) NSString *address;

@synthesize address;

unsafe_unretained -unsafe_unretained is an ownership qualifier that tells ARC how to insert retain/release calls -unsafe_unretained is the ARC version of assign.

Example:

@property (nonatomic, unsafe_unretained) NSString *nickName;

@synthesize nickName;

copy -copy is required when the object is mutable. -copy specifies the new value should be sent -copy on assignment and the old value sent -release. -copy is like retain returns an object which you must explicitly release (e.g., in dealloc) in non-garbage collected environments. -if you use copy then you still need to release that in dealloc. -Use this if you need the value of the object as it is at this moment, and you don't want that value to reflect any changes made by other owners of the object. You will need to release the object when you are finished with it because you are retaining the copy.

Example:

@property (nonatomic, copy) NSArray *myArray;

@synthesize myArray;

I think after arc, retain is not used anymore.
the full list misses 2 option items: setter and getter, which are also the only options need argument.
strong or retain is default for object type only. It can not be used to primitive types.
K
Kannan Prasad

Atomic property can be accessed by only one thread at a time. It is thread safe. Default is atomic .Please note that there is no keyword atomic

Nonatomic means multiple thread can access the item .It is thread unsafe

So one should be very careful while using atomic .As it affect the performance of your code


"Note: Property atomicity is not synonymous with an object’s thread safety." from developer.apple.com/library/mac/documentation/Cocoa/Conceptual/…
A
Ahmad Abbas

prefer this links about properties in objective-c in iOS...

https://techguy1996.blogspot.com/2020/02/properties-in-objective-c-ios.html