This is why I wrote a lightweight UIViewController subclass, called HLSViewController, which implements very small additions making my life easier every day.
Separate object cleanup
In a view controller dealloc method, you must release any strong references to instance variables, in particular to view outlets. These outlets must also be released in the viewDidUnload implementation method to cope with memory warnings. If you care about maintainability, you most probably always factor out the outlet cleanup code into a separate hidden method which you call from both your dealloc and viewDidUnload methods:// MyViewController.h @class MyViewController : UIViewController { } // ... @end // MyViewController.m @interface MyViewController () - (void)releaseViews; @end @implementation MyViewController - (void)releaseViews { self.nameLabel = nil; self.ageLabel = nil; self.closeButton = nil; } - (void)dealloc { [self releaseViews]; // Other cleanup code [super dealloc]; } - (void)viewDidUnload { [super viewDidUnload]; [self releaseViews]; } // ... @endOnce I got tired of writing this kind of code (which happened pretty early), I moved it to the HLSViewController class:
// HLSViewController.h @class HLSViewController : UIViewController { } // ... @end // HLSViewController.m @interface HLSViewController () - (void)releaseViews; @end @implementation HLSViewController - (void)releaseViews {} - (void)dealloc { [self releaseViews]; [super dealloc]; } - (void)viewDidUnload { [super viewDidUnload]; [self releaseViews]; } // ... @endNow implementing a view controller is much cleaner if we subclass HLSViewController instead of UIViewController:
// MyViewController.h @interface MyViewController : HLSViewController { } // ... @end // MyViewController.m @implementation MyViewController - (void)releaseViews { [super releaseViews]; self.nameLabel = nil; self.ageLabel = nil; self.closeButton = nil; } - (void)dealloc { // Other cleanup code [super dealloc]; } // ... @endThis cleanly separates the cleanup code into two groups:
In general, I now hardly ever need to implement the viewDidUnload method in my view controller classes. Note that I call [super releaseViews] in my subclass implementation even if it is not strictly necessary here (the HLSViewController implementation is empty), but after all you cannot know how the method implementation might change in the future.
Let us discuss calling super methods a little bit more in the next section.
Making inheritance cleaner
When subclassing a view controller class, I was often asking myself whether or not I had to call a super method when overriding it in the subclass, most notably with lifecycle and orientation methods. While this is very well documented for UIViewController, this might get obscure as soon you inherit from some custom view controller provided by a library or a framework.Consider the shouldAutorotateToInterfaceOrientation: method: The UIViewController implementation returns YES for portrait orientation only, locking any view controller in portrait mode by default. If you were to call the super implementation of this method first in a direct subclass, i.e.
// MyViewController.h @class MyViewController : UIViewController { } // ... @end // MyViewController.m @implementation MyViewController - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation { if (! [super shouldAutorotateToInterfaceOrientation:toInterfaceOrientation]) { return NO; } // ... } // ... @endyou would always end up getting a view controller in portrait mode. This is of course not what you want in general. The solution is obvious: Do not call the super shouldAutorotateToInterfaceOrientation: method when directly subclassing UIViewController. The problem is, this is not what you usually should do when inheriting from a class: In general, you namely want to call the parent implementation when overriding a method. Wouldn't it be nice if calling the super method was the rule for all methods overridden by a view controller subclass? Well, the solution for shouldAutorotateToInterfaceOrientation: is simple: Allow all orientations in HLSViewController implementation. This is moreover consistent with what you expect from an iPad application (after all, this is how the default plist is configured):
// HLSViewController.m @implementation HLSViewController - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation { // We do NOT call the super implementation here, we replace it return YES; } // ... @endIt is now easy to know what to do when subclassing view controllers ultimately inheriting from HLSViewController: For such view controllers, The super method must always be called for lifecycle, rotation, orientation and cleanup methods in any subclass implementation.
Getting the view lifecycle
There is surprisingly no way to ask a view controller which kind of lifecycle state it is currently in. Fortunately this is easy to fix by implementing all view lifecycle methods in HLSViewController, setting an internal status variable to one of the following values in each of them:typedef enum { HLSViewControllerLifeCyclePhaseInitialized = 0, HLSViewControllerLifeCyclePhaseViewDidLoad, HLSViewControllerLifeCyclePhaseViewWillAppear, HLSViewControllerLifeCyclePhaseViewDidAppear, HLSViewControllerLifeCyclePhaseViewWillDisappear, HLSViewControllerLifeCyclePhaseViewDidDisappear, HLSViewControllerLifeCyclePhaseViewDidUnload } HLSViewControllerLifeCyclePhase;An accessor then allows to retrieve this information at any time, which can be very useful when implementing non-trivial view controllers (e.g. a container view controller).
mmm... two problems with this approach, you tell me if I'm wrong:
ReplyDelete1. Your trick relies on the fact that you can call virtual methods during dealloc. Is it safe to do so?
2. Calling self.prop usually triggers KVO notifications, is it safe to do so during dealloc?
1. In -[HLSViewController dealloc], releaseViews is called before [super dealloc]. I cannot see any reason why this should not be safe.
ReplyDelete2. I try to avoid KVO as much as possible in my own code. It is too easy to couple to private implementation details using it, or to write code which is difficult to understand. I agree this could be dangerous in some cases, and especially if you do not stick to the same rules. The sample code above was written under the assumption that KVO is not used. Of course, other programmers might implement dealloc differently by calling release on each retained ivar directly. This creates a different problem since you bypass the encapsulation provided by an explicit setter implementation. This could be dangerous as well. In my own code, I often implement setters, I never use KVO. That's why self.prop = nil; is safe in my case. But depending on your rules, what you might need is [prop_ivar release]
Reach us for the professional writers like Assignment help online canada
ReplyDeletecanada Essay help online
canada Dissertation help online
Online Homework help Canada
Online Coursework help canada
Online Thesis help
ReplyDeleteบริการเกมสล็อตออนไลน์ปี 2022 เกมให้เลือกเล่นมากกว่า 1,000 เกมsuperslot โปรสมาชิกใหม่ สล็อตออนไลน์ ซุปเปอร์สล็อต ซุปเปอร์สล็อต78
I tried my best to learn about coding language and coding development through HTML CSS but I lost 1st time I tried in intermediate but its too much difficult and at the end I raised my hand from this language .
ReplyDelete