NSString property: copy or retain?
For attributes whose type is an immutable value class that conforms to the NSCopying
protocol, you almost always should specify copy
in your @property
declaration. Specifying retain
is something you almost never want in such a situation.
Here's why you want to do that:
NSMutableString *someName = [NSMutableString stringWithString:@"Chris"];
Person *p = [[[Person alloc] init] autorelease];
p.name = someName;
[someName setString:@"Debajit"];
The current value of the Person.name
property will be different depending on whether the property is declared retain
or copy
— it will be @"Debajit"
if the property is marked retain
, but @"Chris"
if the property is marked copy
.
Since in almost all cases you want to prevent mutating an object's attributes behind its back, you should mark the properties representing them copy
. (And if you write the setter yourself instead of using @synthesize
you should remember to actually use copy
instead of retain
in it.)
Should I use retain for a NSString to be output via a reference to a NSString pointer?
TL;DR
Do not return owned object values by reference.
Explanation:
By convention, objects returned by reference (or even by value) are not owned unless the method specifically states this. If the method name contains copy
or new
then it is expected to provide an owned reference, otherwise the reference count is considered to be irrelevant.
For instance, Cocoa methods that return an NSError
by reference return an autoreleased NSError
which you are not expected to release.
What this means is, you can do either, as long as you indicate what you are doing via the method name. You probably just want to return an autoreleased reference and let the caller decide whether they want to keep holding on to it or not.
Apparently, Apple feels you should not return owned values by reference, according to this document:
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html
When should i use assign in Objective c?
You should assign things that aren't objects. Any C type (such as int, float, char, double, struct, and enum) should be assigned.
What is the difference between copy and retain?
In a general setting, retaining an object will increase its retain count by one. This will help keep the object in memory and prevent it from being blown away. What this means is that if you only hold a retained version of it, you share that copy with whomever passed it to you.
Copying an object, however you do it, should create another object with duplicate values. Think of this as a clone. You do NOT share the clone with whomever passed it to you.
When dealing with NSString
s in particular, you may not be able to assume that whoever is giving you an NSString
is truly giving you an NSString
. Someone could be handing you a subclass (NSMutableString
, in this case) which means that they could potentially modify the values under the covers. If your application depends on the value passed in, and someone changes it on you, you can run into trouble.
Objective-C with ARC: Custom setter does not retain
This looks like a bug to me; your code should be fine. If you haven't yet done so, file a bug at http:// bugreport.apple.com, and attach your sample project.
Edit: On further examination of your sample project, this is not a bug.
The overreleased object in your sample project is not the NSDate
instance. You can comment out the tc.date = now
call in your sample project entirely, and you'll still see the same crash. In fact, you can take out the NSDate stuff entirely. The over-released object is actually the TestVC
object itself.
Here's what's happening.
In iOS 4.0, UIWindow
got a rootViewController
property. Where previously you would just call [self.window addSubview:myRootcontroller.view]
upon launching the app, this change now meant that the window would actually have a reference to the root view controller. This is important for the sake of passing on rotation notifications, etc. In the past, I believe UIWindow would automatically try to set the rootViewController when the first subview was added (if it was not already set), but in your sample project that is clearly not happening. That may be due to the way you're creating the view, or may be due to a change in iOS 5.0. Either way, it wasn't ever documented behavior, so you can't rely on it happening.
In most cases, your app delegate will have an ivar pointing to the root view controller. It's not strictly required, but it's usually what happens. However, in the sample project you presented, the view controller is not owned by the app delegate. Nor did you set it as the window's root view controller. As a result, at the end of the -application:didFinishLaunchingWithOptions:
method, there is nothing left with a strong reference to the view controller. Your app delegate isn't holding on to it, and the window itself isn't holding on to it. As such, ARC treats it as a local variable (which it is), and releases it at the end of the method.
Of course, that doesn't the change the fact that your UIButton
still has an action method targeted at your controller. But as noted in the documentation, -addTarget:action:forControlEvents:
does not retain the target. So the UIButton
has a dangling reference to your view controller, which has now been deallocated since nobody has a strong reference to it. Hence the crash.
The fix for this is to change this line in your app delegate:
[self.window addSubview:tc.view];
to this:
self.window.rootViewController = tc;
With that single change, everything now works just fine.
Edit: Also make sure the "Precheck code for ARC migration" setting is not on, as this would cause the compiler to treat the code as manually managed, and this would not insert the proper retain/release calls.
Which attribute to use as property for class
Since it's a pointer to a class object, and class objects live for the lifetime of the app, memory management actions like retain
and release
have no effect on it. So it shouldn't matter whether you use assign
or release
. It would be simpler to use assign
.
Are @property(nonatomic)ivar @property(nonatomic,assign)ivar the same or different?
As stated in the docs:
assign -
Specifies that the setter uses simple assignment. This attribute is the default.
So no, as far as I know they are the same.
Related Topics
How to Attach Debugger to iOS App After Launch
Uitapgesturerecognizer Tap on Self.View But Ignore Subviews
Mkmapview Mkpointannotation Tap Event
Screenshot for Avplayer and Video
Adding Google Maps as Subview Crashes iOS App with Exc_Bad
Cocoa-Touch: How to See If Two Nsdates Are in the Same Day
Launchscreen.Xib Not Displaying My Custom Font
Easiest Way to Force a Crash in Swift
Make Segue Programmatically in Swift
Uipangesturerecognizer - Only Vertical or Horizontal
Change Color of Back Button in Navigation Bar
Custom Font Sizing in Xcode 6 Size Classes Not Working Properly with Custom Fonts
How to Get Uiscrollview Vertical Direction in Swift
Disabling Automatic Scrolling of Uitableview When Editing Uitextfield Inside Uitableviewcell
Module Compiled with Swift 4.2.1 Cannot Be Imported by the Swift 5.0 Compiler