I have been using protocol and delegate method to pass data back to the previous VC after dismissViewControll is called. Below is how I would normally do it as it is not way that most tutorial was written
protocol someVCDelegate {
func somefunction()
}
var delegate: someVCDelegate!
However, I came across this class/weak approach of writing it.
protocol someVCDelegate : class {
func somefunction()
}
weak var delegate: someVCDelegate!
I understand that weak is associated to ARC and avoiding retain cycle. However, I am not sure when I would need it as in all my cases, not doing weak delegate works find (VC does deinit). In what sort of situation would I need weak delegate? Also, why is it "!" after weak, normally it is "?" after weak right?
You say:
However, I am not sure when I would need it as in all my cases, not doing weak delegate works
You only need the weak protocol-delegate pattern when you have a potential for a strong reference cycle, i.e. a circular series of strong references. For example, consider:
an object (the "parent") that has a property (the "child"), i.e. the parent has a strong reference to the child;
the child has a delegate property; and
you set the child's delegate to refer to the parent object.
In that case, it's critical that the delegate be weak reference or else you'll have a strong reference cycle.
Note, this is a trivial example and sometimes the chain of strong references can be rather complicated. For example, consider a UIView subclass that has a delegate property. The potential strong reference cycle can be quite long, from the view controller to its root view, through a series of subviews of subviews, all the way down to the UIView with the delegate that might potentially reference back to the view controller. That will result in a strong reference cycle, too, and we'd be inclined to use a weak reference for that delegate for that reason.
But when you employ protocol-delegate pattern for passing data between view controllers, though, this generally isn't a problem (with the exception of view controller containment) because the presenting view controller doesn't own the presented view controller. The view controller hierarchy generally maintains the strong references to the view controllers. So, when you dismiss the presented view controller, it is deallocated and the potential strong reference cycle is resolved.
Often, we'll instinctually employ the weak protocol-delegate pattern (simply because it prevents strong reference cycles from occurring at all). But sometimes you will use strong references. The most common strong reference pattern is NSURLSession whose delegate is a strong reference. As the documentation for init(configuration:delegate:delegateQueue:) warns us:
The session object keeps a strong reference to the delegate until your app exits or explicitly invalidates the session. If you do not invalidate the session by calling the invalidateAndCancel() or finishTasksAndInvalidate() method, your app leaks memory until it exits.
While this might seem paradoxical, the advantage of this strong reference pattern is that the session knows that it can safely call its delegate methods without fear of the object having been deallocated. (As an aside, this strong delegate behavior of NSURLSession rarely rears its ugly head, because we often use the completion handler methods and don't employ the delegate methods at all, and when we do employ delegate methods, we often have some object other than a view controller as the delegate for the session.)
In short, you really have to evaluate each situation and determine whether the weak reference that we instinctually lean towards is better, or whether you have one of those cases where your protocol is better served with strong references.
Why it's weak: A weak reference is a reference that does not keep a strong hold on the instance it refers to, and so does not stop ARC from disposing of the referenced instance. This behavior prevents the reference from becoming part of a strong reference cycle. Or simply, You resolve strong reference cycles by defining some of the relationships between classes as weak or unowned references instead of as strong references.
And it's "!" after weak because it's implicitly unwrapped. It's gonna have a value.
Sometimes it is clear from a program’s structure that an optional will always have a value, after that value is first set. In these cases, it is useful to remove the need to check and unwrap the optional’s value every time it is accessed, because it can be safely assumed to have a value all of the time.
Related
I found something that I can't understand in UICollectionView header file. I found that the delegate has an assign property
#property (nonatomic, assign) id <UICollectionViewDelegate> delegate;
This question is only for my basic understanding as the rule says the delegate should have a weak property. And according to my personal knowledge, assign won't reference count the delegate object but it will surely still have a reference to a garbage value if the object is deallocated.
How can I understand this piece of code?
strong and weak were introduced alongside Automatic Reference Counting (ARC). UIKit moved to ARC with iOS 9, and if you look at the iOS 9 header (using Xcode 7) you will see that this property is now weak.
You are right: with the property as assign (which is equivalent to unsafe_unretained), if the delegate is deallocated while the collection view is alive, the collection view’s delegate property will point to where the deallocated object used to be and probably cause a crash when it is referenced. This is not usually a problem because the delegate is often the view controller owning the collection view so usually outlives the view. However, this is not a guarantee, which is why you should set assign delegates that point to you to nil in your dealloc.
Relevant Stack Overflow questions:
Objective-C ARC: strong vs retain and weak vs assign
Set delegates to nil under ARC?
ARC delegate memory management
I can't understand why it is correct to define a delegate with weak pointer :
#property (nonatomic,weak) id delegate;
I can't realize why isn't necessary to retain a reference to the delegate... i don't want the object that i use as the delegate to be deallocated... thus, i would prefer using a strong reference not a weak!
In many cases the delegate is the same object where the instance of my class will be created, in this case creating a weak reference would be a great solution to avoid retain cycle... but what if I choose a totally different object as the delegate ?
I searched for other questions on stack overflow but I can't find something that can help me to fully understand this situation.
The reason that objects weakly retain their delegates is to avoid retain cycles. Imagine the following scenario: object a creates b and retains it, then sets itself as b's delegate. a is released by its owner, leaving a retain cycle containing a and b. This is actually a very common scenario. Consider a view controller that owns a view and acts as that view's delegate. In this case, the view should not retain the controller—as a mater of proper MVC architecture and to prevent retain cycles.
Though retain cycles are a valid concern, the reasoning for a weak reference is more related to apple's perspective on how to use the delegation pattern with uikit and other elements out of the box which is explained here:
http://developer.apple.com/library/IOs/documentation/General/Conceptual/DevPedia-CocoaCore/Delegation.html
Specifically:
"The main value of delegation is that it allows you to easily customize the behavior of several objects in one central object."
If the delegate deals with managing the delegated tasks of several objects then those objects need not retain the delegate and should not bear the responsibility of dealllocating the delegate as it might be used by other objects. The weak reference enforces the concept that the management of the delegate is not the delegators responsibility.
An example in objective c is a one delegate being used for multiple table views, like when using a table view and a searchdisplaycontroller with a uisearchbar. Apples examples use the controller as the delegate, but reasoning still holds when using one custom delegate for both the main table view and the results table view for your search. That custom delegate would likely be retained by your controller in order to be provided to both table views.
This is fundamentally different from the basic delegation pattern that is referred to in other languages where the delegate is often created by the delegator and each instance may manage a its own delegate instance.
This is to avoid retain cycles. Apple offers an informative guide on advanced memory management explaining the situation and how best to deal with it. In ARC, they are now known as strong reference cycles, which are explained in the Transitioning to ARC Release Notes.
Previously you would define a property for a delegate like this,
#property (nonatomic, assign) id delegate;
But in ARC, you can define it thus,
#property (nonatomic, unsafe_unretained) id delegate;
Or, for example, if you have a protocol named <MyObjectDelegate>, you can also define the delegate in this way,
#property (nonatomic, weak) id <MyObjectDelegate> delegate;
In other words, in ARC if you have a protocol, you can declare a delegate weak. Otherwise, unsafe_unretained.
As a common practice, if we have two objects holding references with each other, we make the "child" object in a "parent-children" relationship a weak reference.
For delegation patters in iOS, the delegated object is the parent, because there is no need for the delegate caller to exist without the delegated object. For example, you have a sentence object with delegate object for method sentenceShouldEnd. Your paragraph object is the delegated object for your sentence object. Obviously the paragraph object is actually the parent, and in your sentence object you should keep your delegate as a weak reference.
To your point you assign the delegate to self, your understanding is wrong. We should never assign delegate to itself. Why you buy your ticket yourself if you feel it is necessary to hire an agent to buy the ticket for you? You are saying two completely different concepts. When you define a delegate object as property, it's used a weak reference in the object it is defined in(lets say A, i.e. the delegate object is a property of A). The delegate is assigned when you init A(let's say in B), then most likely you would assign A.delegate to self, which is acturally B. You see the parent-child relationship here?? You alloc memory for A in B. You hold A in B. A does not exist without B. You are not assigning the delegate to A!!!!
Have an interesting issue where there is a class that is referenced in an XIB layout (subclass of UIScrollView) and is not being de-allocated according to Instruments / Allocations and does not break in it's dealloc routine. Let's call it Sclass1.
There is a using class (let's call it Uclass) that has the XIB file and the outlet.
#property (nonatomic, weak) IBOutlet Sclass1* sclass1;
This is hooked properly to the XIB file layout.
Sclass1 is property allocated when the XIB for Uclass is loaded. Uclass does get deallocated and then recreated from time to time and thus we have another instance of Sclass1, but Sclass1 never goes away and can't find another reference to it.
Drill down in Instruments shows the one Malloc and that is it.
fyi, the class gets started with
[UIClassSwapper initWithCoder:]
If an object doesn't get deallocated under ARC, it means a strong reference to it exists. Since your property is weak the object must be owned strongly by something other than the Uclass object (Otherwise it would get deallocated immediately after the XIB has loaded). In the code you've provided it isn't clear what the actual strong owner of this object is, but I assume it could be one (or more) of the following:
Since the object's class is a UIView subclass, it may be (strongly) referenced by its superview if added as one of subviews. This happens automatically when a XIB file is loaded. If the superview doesn't get deallocated neither will the SClass object. You can remove this ownership by calling removeFromSuperview
A strong ownership cycle (retain-cycle) exists somewhere among ivars of the SClass1 object (i.e. one of the strongly-owned instance variables have a strong reference back to its owner - the SClass1). Beware that any block using self directly also keeps a strong reference. Having a strong reference to the block then often leads to a retain-cycle. Save self to a __weak var and pass that to the block instead unless you have a good reason not to.
A manually created strong reference exists by e.g. adding the object to a container or saving the pointer to a non-__weak variable.
Try finding and removing these strong ownerships. Only after all of them are removed the object can be deallocated.
Since your property is weak and it's still not deallocated, look for strong references to Sclass or it's owner, Uclass. Maybe you are using Uclass(or Sclass) in block directly, without __weak typeof(self) weakSelf dancing and this block creates retain cycle. Also watch for parent-child relations and delegates. Maybe there is delegate which is strong instead of weak or two controllers hold strong references to eachother.
Also, if you want to have more detailed answers, please post more relevant code.
I think your #property should be strong for a class :
#property (nonatomic, strong) IBOutlet Sclass1* sclass1;
Because strong is the equivalent to retain and ARC will manage the release for you.
You will have more information with the Apple Documentation about Transitioning to ARC Release Notes in the section on property attributes.
I recently had the same symptoms - To solve it in my case, my object was acting as delegate for a number of other objects, so had to release the object from all its delegate responsibilities before it would call dealloc
An application that I am working on, that uses ARC and needs to support iOS 4.3 and iOS 5, declares every outlet as #property (strong, nonatomic) IBOutlet in the .h file.
e.g.
// myClass.h
#property (strong, nonatomic) IBOutlet UITextView *myTextview;
I know that with ARC only properties which do not hold a strong reference to an object are released.
As a result, the App relies on - (void)viewDidUnload to set the property myTextview to nil.
i.e.
// myClass.m
- (void)viewDidUnload
{
[super viewDidUnload];
self.myTextview = nil;
}
I know, from Apple's Documentation, that Outlets should generally be weak except those from File's Owner ( i.e. A Runtime Object that owns the contents of the iOS Storyboard scene) to Top-Level Objects (my rule of thumb is to use anything that appears in the window with File's Owner, First Responder and View).
Anything I add to the view will be a subview and thus is retained by it's direct superview, meaning a weak reference should be used.
I am also aware that - (void)viewDidUnload is deprecated in iOS 6 and is not called.
1st Question : What are the issues with taking the approach of declaring every outlet as a strong property and setting it to nil in viewDidUnload, apart from the fact that viewDidUnload is deprecated in iOS 6?
My intuition tells me that it is because situations arise where you can set a pointer to nil, before viewDidUnload is called. So you should, to free up memory on the heap. Is there a noticable performance change if this is the case?
2nd Question : Should I go back throughout the project and change strong to weak? Why? Is it worth the time?
3rd Question : If I was to declare the property in a class extension, to 'hide' it, how does this affect my rule of thumb for deciding on when to use strong or weak.
I know there are many threads here that discuss this issue. But many I've found are out of date, and do not address this issue directly. Thanks.
First, a few of your presumptions need addressing:
I know that ARC only releases properties which do not hold a strong
reference to an object. As a result, the App relies on -
(void)viewDidUnload to set the property myTextview to nil.
Not quite. ARC never retained weak properties in the first place. As for strong properties, ARC still releases them, but not until dealloc is called.
viewDidUnload was never used to prevent leaks. It was essentially an optimization, and one that Apple decided was no longer worth the trouble. To understand, consider the standard lifecycle of a pre-iOS6 view controller:
1. Allocated
2a. View Loaded
2b. View Unloaded
3. Deallocated
Where 2a and 2b could be repeated any number of times. For example, a view controller at the bottom of a navigation stack (its view being hidden) could have its view unloaded in low memory situations. It would then be reloaded the next its view became visible.
The method was essentially saying "Hey view controller programmer, we're running low on memory, and nobody can see me anyways, so I'm releasing my view. If you could do the same for your strong properties, that would be great."
That process had subtleties and was generally confusing. As a result of the tediousness, Apple deprecated it. Views are no longer unloaded, so there's no point in implementing it. The key point is that all your strong properties will still be released in ARC's dealloc method.
I know that Outlets should generally be weak...
Why do you know that? There's nothing special about outlets. The 'IBOutlet' keyword is really just for Xcode's benefit when designing things with its visual tools. It has no effect on the compiled code. So, when thinking about strong vs weak outlets, use the same considerations that you do for any other property, namely "do I need this to exists, or am I okay with it disappearing on me?".
What are the issues with taking the approach of
declaring every outlet as a strong property and setting it to nil in
viewDidUnload, apart from the fact that viewDidUnload is deprecated in
iOS 6?
There are no issues with that. If you want your properties to exists as long as your controller, then use strong. viewDidUnload has nothing to do with this. On older iOS versions, you could release strong outlets in viewDidUnload if you want.
Should I go back throughout the project and change
strong to weak? Why? Is it worth the time?
Again, just use whichever qualifier makes sense for your use case. You're almost always safe using strong for you outlets.
If I was to declare the property in a class extension, to 'hide' it,
how does this affect my rule of thumb for deciding on when to use
strong or weak.
There's no difference.
1st question: The outlets are subviews of the main view which is a property of the view controller. If you declare them as weak, they have a retain count of 1, since they are subviews. If the view is released, they are also released. If you declare them as strong, they have a retain count of 2, since they are subviews, and strong properties of the view controller. So they are only released when the view controller is released (which releases also its view and its subviews). To my understanding, the difference is that when the view of a view controller is released, e.g. when it is not presented and memory is low, the outlets still allocate memory when they have been declared as strong.
2nd question: I believe in most circumstances it does not matter.
3rd question: I believe if you declare properties in a class extension, the simply belong to the class, and thus there is no difference in handling them compared to "real" class properties.
My approach would be to make sure not to declare properties as strong that could result in retain cycles, what happens, i.e., if you declare a delegate as strong.
I am a little confused about where to use strong and where to use weak. Are there any tools to monitor reference counts in ios ?
Strong reference is used when you want the class to keep ownership to an object and hence prevent the object from being deallocated until the class doesn't need it anymore. It is usually used for objects that cannot be cheaply reproduced (e.g. data downloaded from the server) or things that are crucial during the operation of the class.
Weak reference is used when you need a reference to the object. The object will be gone if it is deallocated by its owner. This is usually used to for cycle referencing without worrying about the object not deallocated.
Just to add to the other comments, while strong reference cycles (previously known as retain cycles) are important to understand, they're relatively uncommon unless you're passing around pointers to parent objects to their children. If you're doing that sort of thing, you should make sure you understand the discussion of strong reference cycles (a.k.a. retain cycles) as outlined in some Apple docs, specifically Acquire Basic Programming Skills, Advance Memory Management, and Transitioning to ARC. As a practical matter, the common example of retain cycles would be if you are passing pointers to parent controllers to a child controllers. In these cases, should generally make these pointers weak, otherwise strong is generally pretty safe.
The other common situation for weak references is IBOutlets for controls in a NIB or Storyboard, which should also generally be weak. (If you make the outlets by control dragging them from Interface Builder to your header file, it will take care of making them weak for you.) Anyway, I'll quote from the Resource Programming Guide, which says:
Outlets should generally be weak, except for those from File’s Owner
to top-level objects in a nib file (or, in iOS, a storyboard scene)
which should be strong. Outlets that you create should will therefore
typically be weak by default, because:
Outlets that you create to, for example, subviews of a view controller’s view or a window controller’s window, are arbitrary
references between objects that do not imply ownership.
The strong outlets are frequently specified by framework classes (for example, UIViewController’s view outlet, or NSWindowController’s
window outlet).
In general you don't have to use weak except to avoid a retain cycle. That is, as long as you don't have two objects with strong references to each other you will be fine.