OK - newbie Objective-C question:
When declaring properties there are attributes such as below:
#property (weak, nonatomic)
I realize I need read up on this to fully understand it but most of what I found was reference material, so a link to a good article that could explain best practices / usage scenarios (when to use which attribute for primitives, reference types, outlets, etc) or a couple of examples would be appreciated.
Thanks!
Even though it is waaaay to late for an answer i've found this question while googleing the same issue and also found this article by apple which explains the whole thing perfectly.
Hope it helps to anyone who are researching the same thing,
http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html
From a recent class I gave on this (inspired by Paul Hegarty)
nonatomic - NOT thread safe see link Justin pointed out in the comments above.
strong (or retain) - keep this object allocated until I don’t point to it anymore (set it to nil). Compiler will also throw this out of the heap (deallocate it) if I am not pointed to strongly anymore (I get dealloc’d)
weak - keep this object allocated as long as something still points to it strongly. IBOutlets are usually declared as weak since they will be retained automatically by the view controller.
Primitive types are not allocated on the heap and don't use strong or weak
Atomicity has to do with threading, and is a pretty advanced topic for a newbie. The short answer, however, is that iOS properties are always declared as nonatomic. Here's some more detailed information about it.
The weak/strong keyword has to do with memory management with ARC and preventing what's called a retain cycle. This can also be a bit of a tough concept for a newbie, but the high-level overview is that a retain cycle happens when two objects have strong references to each other and thus neither object will be destroyed by ARC. This is a form of a memory leak, as you may have an object that's no longer in use but is still taking up memory. By declaring a property as weak, it will ensure that it's not automatically destroyed so long as something still has a strong reference to it. For instance, let's say you have an array with a couple of objects in it. Two of the objects have strong references to each other. Then, the array loses its owner and is destroyed. BUT, the two objects in that array that point to each other are NOT destroyed since they have strong references. Thus, you have two objects which you cannot access since the owning array is destroyed, but they're still taking up memory.
Related
For example, there is a class
#interface Person: NSObject {
#property (weak) NSString *str;
#end
#implementation
- (void) init {
str = #"XYZ";
}
#end
Is it safe to declare all properties to weak to avoid reference count
overhead?
If not safe then why it's not safe?
What will be the reference count of str?
Is it safe to declare all properties to weak to avoid reference count overhead?
This is problematic on two counts. First, weak doesn't avoid reference counting. It actually performs more bookkeeping than strong. See Lots of overhead for weak property? for a good discussion of that.
Next, this is wrong because weak and strong mean different things that cannot be interchanged. As MartinM notes, if you make your properties weak, they'll just disappear as soon as you assign them if nothing else is holding onto them.
If not safe then why it's not safe?
It is totally safe. It just won't work. Your program will have well defined behavior, and shouldn't crash due to marking all your properties weak. Most of your properties will just be nil. If you used unsafe_unretained instead of weak, then you would avoid some reference counting overhead, and your program would typically crash (because the objects would still be destroyed, the pointers would just become invalid).
What will be the reference count of str?
That is not a meaningful question, even though it feels like one. In this particular case the answer is 9,223,372,036,854,775,807 because that's always the retain count of a static string, because static strings cannot be destroyed and ignore retain/release calls. (That value is NSNotFound in ObjC. I believe this used to return 1,152,921,504,606,846,975, but my tests indicate it's changed.)
But in the general case, it could be anything at this point in time. And what it is at this point in time versus at the end of the event loop (when the autoreleasepool drains) could be dramatically different. Do not chase retain count values. They will always lie to you. Create strong references to things you care about. Create weak references only when you need them for their specialized purposes.
Retain counts are an internal implementation detail. Before ARC, they were misleading to the point of uselessness. Since ARC, they're like asking "what assembly instructions will this compile to." It's important, but it depends on everything else about the program and how it's compiled.
If you have a specific performance problem related to memory management, then there are techniques for dealing with that in a case-by-case basis, and StackOverflow can help you. But ARC is extremely good at optimizing memory management. Let it do its job.
You should know which properties should be weak and which strong. It is a common practice declaring for example all IBOutlets as weak because they are being retained by the view that comes from the storyboard, so it is not necessary to keep a strong reference in the viewcontroller.
Another example would be a delegate that should always be weak, or it will prevent the delegate (mostly another viewcontroller) from being deallocated because the delegate's holder is still alive.
In your case, str will be nil after init, because there are no other references to its content. You should actually get a compiler warning if you do this.
Take a look at this thread with more detailed explanation: Weak and strong property setter attributes in Objective-C
This is a purely theoretical question so please feel free to propose additional constraints or suggest alternative questions to discussion.
I know that in Objective-C almost any property that is mutable ought to be defined as (nonatomic, copy), but what if I want that property, say a mutable array, to be only just a list of weak pointers to objects already retained by some other class? For example, say I have a class called Concept and let's assume that all intended Concept instances have already been loaded and retained in memory somewhere by some class other than Concept. Say we add a nonatomic NSMutableArray property to each Concept instance called relatedConcepts that points to other Concept instances that are retained and already exist in memory.
What I know is that NSArrays are lists of strong referenced objects, but I want a list of weak referenced objects. How might I go about implementing this?
An NSArray ALWAYS keeps a strong reference to each of its items. This is by design as arrays are nil terminated and would become corrupted if one of the items ever became nil. The weak you are referring to would only apply to the array reference itself. Keeping "weak" items in an array is an advanced problem. My current solution involves using weak proxy objects which sounds kind of like what you were describing in your last paragraph. Whether you use copy or not isn't really relevant.
I have found some scenarios where keeping an array of weak references has come in handy. I've had to roll my own solution for that using weak proxies. Basically, you have an array of objects that then have a weak reference to the objects you actually care about. The weak proxy then needs to redirect all of the calls to it to the object it wraps.
You would use the strong specifier for your relatedConcepts property. That's to keep that instance from disappearing out from underneath you, regardless of the number or kind of references it contains.
There's no such thing as a mutable array that's a "list of weak pointers." NSMutableArray (as well as NSArray) maintains strong references to its members.
You're worrying far too much about what's retained (has a strong reference to it) and what isn't. That isn't your job. It's entirely possible that whatever is holding a strong reference to an object may choose to release it. Meanwhile, if nothing else is holding a strong reference to it, your weak reference falls to nil. Bad idea if you want to keep using it.
Today I read book about ARC. So there are two type points both strong and weak points.
I already searched the property about them and got it.
But I couldn't see or understand why we use weak point instead of strong?
This is simple question. Please let me know easily.
Thanks.
First of all its not weak points, its weak property. Lets say if you don't want owner ship of a particular object you can use weak property. If the actual owner of this reference release this and its retain count becomes zero, a weak reference will be automatically assigned to nil. Which will save you from crashes.
You can get more information here : https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html
This question has been answered very well on apple's page !
I will just link it in hope it really helped you to get the required info !
link is here :) arc
also I think this SO question is very helpful for understanding the things :[link]here (Objective-C ARC: strong vs retain and weak vs assign)
To be simple, you use "weak property" and or "weak variable" for following:
You do not want to take the ownership of object. Like delegate/dataSource are generally declared weak.
You may say you can also use "assign" instead of "weak". When the variable is freed from memory, using "weak" automatically sets it to nil, whereas "assign" now is referring to deallocated instance and code can crash if you try to do something on it.
To avoid retain cycles causing memory leaks. For example avoid passing "self" in blocks. use "__weak id weakSelf = self", and now pass weakSelf in blocks.
ARC is your friend, but can do potential harm if not taken care of things mentioned above.
I'm trying to learn/understand what happens and why when working with or creating various objects. (Hopefully to LEARN from the docs.)
I'm reading "Programming in Objective-C 2.0" (2nd edition, by Steven Kochan). On page 408, in the first paragraph is a discussion of retain counts:
Note that its reference count then goes to 2. The addObject: method does this automatically; if you check your documentation for the addObject: method, you will see this fact described there.
So I read the addObject: docs:
Inserts a given object at the end of the array.
There, the description is missing, while other items, like arrayByAddingObject:, state it:
Returns a new array that is a copy of the receiving array with a given object added to the end.
Where in the reference does it indicate that addObject: increases the retain count? Given the presence of ARC, I should still understand what these methods are doing to avoid bugs and issues. What does ARC bring to this? (Going to read that again...)
Great question, I'm glad to see someone actually reading the docs and trying to understand them!
Since you are looking for how to research answers using Apple's documentation more so than the actual answer itself, here is how I found the answer:
First I look at the class reference for addObject: which is a method of NSMutableArray and there is no mention of memory management.
Then I look at the Overview section at the top... Hmmm, still no luck.
Since the behavior might be inherited from a parent class, I look at the Inherits from section at the top of the class reference and see that NSArray is the most immediate parent. Let's check there:
Under the Overview There is one small section about retain's:
Special Considerations
In most cases your custom NSArray class should conform to Cocoa’s
object-ownership conventions. Thus you must send retain to each object
that you add to your collection and release to each object that you
remove from the collection. Of course, if the reason for subclassing
NSArray is to implement object-retention behavior different from the
norm (for example, a non-retaining array), then you can ignore this
requirement.
Okay, I'm still not happy... Where next? The parent class of NSArray is NSObject and I know that it won't be covered there in this case (from experience) so I won't bother checking that. (If the parent was another class or something that might be covered by NSObject, I would keep moving up the tree until I found something.)
The Companion Guides usually contains a lot of good information for these types of classes. Let's try the first one, Collections Programming Topics.
The first section (after Overview) is Accessing Indexes and Easily Enumerating Elements: Arrays. Sounds promising! Click on Relevant Chapters: “Arrays: Ordered Collections”
There it is under Array Fundamentals along with a link to even more information:
And when you add an object to an NSMutableArray object, the object
isn’t copied, (unless you pass YES as the argument to
initWithArray:copyItems:). Rather, an object is added directly to an
array. In a managed memory environment, an object receives a retain
message when it’s added; in a garbage collected environment, it is
strongly referenced. When an array is deallocated in a managed memory
environment, each element is sent a release message. For more
information on copying and memory management, see “Copying
Collections.”
The book must be referring to out of date documentation because you are correct it doesn't mention anything about the retain count. It does in fact retain the object though. The way you need to think of it is not in terms of retain counts (which are useless) but rather ownership. Especially so when using ARC.
When you add an object to an NSMutableArray, it is taking ownership of that object (in ARC terminology it has a strong reference to it).
"What does ARC bring to this?"
ARC does nothing different. All ARC does (besides some optimization) is add the same release, retain, and autorelease statements that you would add yourself without using ARC. All you need to care about is that once you add an object to the array, it will live at least as long as the array.
And the arrayByAddingObject: method creates a new NSArray (or NSMutableArray) containing the object you're passing, and keeps a strong reference to the passed object. The actual array object that it creates has no references yet unless you assign it to either an ivar, property, or local variable. What you assign it to determines it's lifespan.
Basically even without ARC, it's best to think of object life-cycles in terms of ownership, ARC just formalizes that. So because of that, when using the frameworks, it doesn't matter when retains happen or don't happen, you are only responsible for your objects until you pass ownership to another object and you can trust that the framework will keep the object alive as long as it needs it.
Now of course you have to intuit what constitutes ownership. For instance delegate properties are often assign, or in ARC unsafe_unretained or weak, to prevent circular retains cycles (where two objects each retain each other), though are sometimes retained/strong so you need to look into those on a case by case basis.
And also in cases like key value observing and NSNotification observing the object you are observing does not retain the observer.
But those are really exceptions to the rule. Generally you can assume a strong reference.
Regarding this sentence above: "The actual array object that it creates has no references yet unless you assign it to either an ivar, property, or local variable. What you assign it to determines it's lifespan." I'll try to explain:
When you run this piece of code: [someArray arrayByAddingObject:someObject]; you've instantiated a new NSArray or NSMutableArray object (depending on which object type someArray is) but you haven't actually assigned it to any reference. That means that if you're using ARC, it may be immediately released afterwards, or if not using ARC, it will be released when it's autoreleasepool is drained (probably on the next iteration of that thread's runloop).
Now if instead you did this: NSArray *someOtherArray = [someArray arrayByAddingObject:someObject]; you now have a reference to the newly created array, called someOtherArray. In this case, this is a local variable who's scope is only within whichever set of { } it resides (so it could be inside an if statement, a loop, or a method. Now if you do nothing else with it, it will die sometime after it's scope ends (it isn't guaranteed to die right away, but that isn't important, you just can't assume it lives longer).
Now if in your class you have an iVar (instance variable) declared in the header like NSArray *someOtherArray; (which is strong by default in ARC) and you run someOtherArray = [someArray arrayByAddingObject:someObject]; somewhere in your class, the object will live until you either remove the reference (someOtherArray = nil), you overwrite the reference (someOtherArray = someThirdArray), or the class is deallocated. If you were not using ARC, you would have to make sure to retain that to achieve the same effect (someOtherArray = [[someArray arrayByAddingObject:someObject] retain]; which is essentially what ARC is doing behind the scenes).
Or you may have a property declared instead like #property (nonatomic, strong) NSArray *someOtherArray in which self.someOtherArray = [someArray arrayByAddingObject:someObject]; would achieve the same effect but would use the proprety accessor (setSomeOtherArray:) or you could still use someOtherArray = [someArray arrayByAddingObject:someObject]; to set the iVar directly (assuming you #synthesized it).
Or assuming non-ARC, you might have declared the property like #property (nonatomic, retain) NSArray *someOtherArray in which self.someOtherArray = [someArray arrayByAddingObject:someObject]; would behave exactly as ARC would, but when setting the iVar directly you would still need to add that retain manually.
I hope that clears things up a bit, please let me know if there's anything I glossed over or left out.
As you mentioned in your comment, the key here is intuitively knowing when an object would be considered owned by another one or not. Luckily, the Cocoa frameworks follow a pretty strict set of conventions that allow you to make safe assumptions:
When setting an NSString property of a framework object (say the text property of a UILabel for example) it is always copied (if anyone knows of a counter-example, please comment or edit). So you don't have to worry about your string once you pass it. Strings are copied to prevent a mutable string from being changed after it's passed.
When setting any other property other than delegate, it's (almost?) always retained (or strong reference in ARC)
When setting delegate properties, it's (almost?) always an assign (or weak reference) to prevent circular retain cycles. (For instance, object a has a property b that is strong referenced and b has a strong referenced delegate property. You set a as the delegate for b. Now a and b are both strongly referencing each other, and neither object will ever reach a retain count of 0 and will never reach it's dealloc method to dealloc the other object. NSURLConnection is a counter-example that does strongly reference it's delegate, because it's delegate is set via a method -- see that convention below -- and it's convention to nil out or release an NSURLConnection after it completes rather than in dealloc, which will remove the circular retain)
When adding to an array or dictionary, it's always retained (or strong reference).
When calling a method and passing block(s), they are always copied to move them from the stack (where they are initially created for performance purposes) into the heap.
Methods that take in object parameters and don't return a result immediately are (always? I can't think of any that don't) either copying or retaining (strong referencing) the parameters that you pass to ensure that the method can do what it needs to with them. For instance, NSURLConnection even retains it's delegate because it's passed in via a method, whereas when setting the delegate property of other objects will not retain, as that is the convention.
It's suggested that you follow these same conventions in your own classes as well for consistency.
Also, don't forget that the headers of all classes are available to you, so you can easily see whether a property is retain or assign (or strong or weak). You can't check what methods do with their parameters, but there's no need because of the convention that parameters are owned by the receiver.
In general, you should look in the "most global" spot for information about anything in the Cocoa APIs. Since memory management is pervasive across the system APIs and the APIs are consistent in their implementation of the Cocoa memory management policy, you simply need to read and understand the Cocoa memory management guide.
Once understood, you can safely assume that all system APIs implement to that memory management policy unless explicitly documented otherwise.
Thus, for NSMutableArray's addObject: method, it would have to retain the object added to the array or else it would be in violation of that standard policy.
You'll see this throughout the documentation. This prevents every method's documentation from being a page or more long and it makes it obvious when the rare method or class implements something that is, for whatever reason (sometimes not so good), an exception to the rule.
In the "Basic Memory Management Rules" section of the memory management guide:
You can take ownership of an object using retain.
A received object is normally guaranteed to remain valid within the
method it was received in, and that method may also safely return the
object to its invoker. You use retain in two situations: (1) In the
implementation of an accessor method or an init method, to take
ownership of an object you want to store as a property value; and (2)
To prevent an object from being invalidated as a side-effect of some
other operation (as explained in “Avoid Causing Deallocation of
Objects You’re Using”).
(2) is the key; an NS{Mutable}Array must retain any added object(s) exactly because it needs to prevent the added object(s) from being invalidated due to some side-effect. To not do so would be divergent from the above rule and, thus, would be explicitly documented.
I'm studying ARC. And now about zeroing weak pointer.
OK I understood all the features. The semantic of weak reference is just same with weak reference of GC system, but you know, Objective-C doesn't use GC (except special case) so I can't understand how this works.
I'm a little complicated guy, so I need to know underlying implementation principal to accept the feature to use. But the problem is it's very hard to find document which describes the principal of zeroing-weak pointer :(
IMO, the only way to make this work is tracking and keeping all pointers referencing itself at runtime, and setting them all nil when its referencing count becomes 0. But this looks too heavy and stupid. I believe a lot better solution used in actual ARC implementation.
Can you help me to find the documentation? Or direct description would be more great!
It's explained here:
http://mikeash.com/pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html
Spoiler:
It works pretty much how you'd think. Every class maintains a set of addresses of weak pointers that are pointing to it, and when its dealloc is called it sets them all to zero.
It may seem dumb, but it's fast because there's no "tracking" involved, ARC just inserts the code to add a pointer to that set every time the object is assigned to a new weak reference.
It's actually much more efficient than the trickery involved in Garbage collection, which basically involves wading through the heap on a background thread looking for pointers and keeping stock of what they're pointing to.
Implemented by a global hash table in runtime.
Apple source: https://opensource.apple.com/source/objc4/objc4-647/runtime/objc-weak.mm