I want to recall awakeFromNib when the tableView reload it's cells, to re-execuse the code I am executing there and newly load a pageViewController who is inside the cell, is that possible?
I believe awakeFromNib is called on an object when it is initialized from a nib file. So you can not call it manually.
Read this thread for object loading process from nib file.
See the documentation from apple about awakeFromNIb method
After all objects have been instantiated and initialized, the
nib-loading code reestablishes the outlet and action connections for
all of those objects. It then calls the awakeFromNib method of the
objects.
So, calling it manually looks not possible. Moreover I suggest you to put the lines of code in awakeFromNib into a seperate method and call that method. It will work for you.
As the other respondents point out, you should not call any of the "lifecycle" methods yourself. However, there is no reason on earth why you can't do something like:
override func awakeFromNib() {
super.awakeFromNib()
self.doSetupStuffINeedToRepeat()
}
func doSetupStuffINeedToRepeat() {
//...
}
Then you can simply call doSetupStuffINeedToRepeat() anytime you want. The reason that you shouldn't call awakeFromNib yourself is that, if done properly, it should call super.awakeFromNib, and doing this in the middle of execution may (will) really mess things up...
Related
I am subclassing UIButton and want my custom button to appear in Storyboard. I made all my changes in awakeFromNib() (called its super) and added #IBDesignable.
override func awakeFromNib(){
super.awakeFromNib()
... // customization stuff
}
And in prepareForInterfaceBuilder() i need to use what i did in awakeFromNib(), so if i call awakeFromNib() directly, will it cause any bad stuff to happen? If yes, what will it cause? Or it is totally fine? Like this:
override func prepareForInterfaceBuilder(){
...
self.awakeFromNib()
}
Or do i have to create a setup() function with all my customization inside, and then call it from both awake and prepare functions?
Thanks.
You should combine code in a method (as you mentioned setup() let's say) and call it in both awakeFromNib() and prepareForInterfaceBuilder() instead of calling awakeFromNib() manually.
awakeFromNib is one of the view life cycle methods, meaning that it should get called by the system at a particular status. Avoid call such a method by yourself; What you should do is to provide the needed functionality to be performed when awakeFromNib get called but not calling it by yourself.
in Apple documentation about awakeFromNib() it says "Although the
default implementation of this method does nothing, many UIKit classes
provide non-empty implementations.". So if it does nothing, what can
calling it cause?
First, you should take a look for the second part of the sentence:
many UIKit classes provide non-empty implementations.
Which means that there is a specific code should get run (in super. awakeFromNib):
You must call the super implementation of awakeFromNib to give parent
classes the opportunity to perform any additional initialization they
require.
Second, even if there is no harm from doing it, you should not do it, you should not follow the approach of calling a method that gets called by the system.
I have been searching around for this particular method:didMoveToWindow() however I haven't found any concrete information.
Could someone explain why and when should someone use this method and when is it called?
This method is called by iOS when a UIView is added to the Window object.
You are supposed to override it to make your app do something at the same that.
The default implementation of this method does nothing. Subclasses can
override it to perform additional actions whenever the window changes.
The window property may be nil by the time that this method is called,
indicating that the receiver does not currently reside in any window.
This occurs when the receiver has just been removed from its superview
or when the receiver has just been added to a superview that is not
attached to a window. Overrides of this method may choose to ignore
such cases if they are not of interest.
https://developer.apple.com/reference/uikit/uiview/1622527-didmovetowindow
In the .h file of UICollectionView a comment says:
// If a class is registered, it will be instantiated via alloc/initWithFrame:
Is there a way that I can have it call a custom init method?
How about [cell configureForData:data] right after you dequeue it? You probably need to re-configure the data on dequeued cells, anyway.
Suppose there is a way that you can have it call a custom init method, you wouldn't pass anything to the custom init method by dequeueReusableCellWithReuseIdentifier:forIndexPath:, so setting up the data should be separate from the init method.
Is there an easy way to know when all the subivews have loaded?
Right now I'm doing:
if([[self subviews] count] == 10) {
//do stuff
}
If there isn't an event/method for this, is there at least a way to dynamically know what the child count is GOING to be?
edit
I re-read this just now and realize it's a bit asinine. Let me clarify:
I'm loading this UIView from a XIB file and I wanted to know when the NIB has officially loaded (with all of it's children). So I dare say the correct answer would be awakeFromNib
If you're calling this from a viewController, just use
-(void)viewDidLoad;
Which is called after the view and all its subviews are loaded. If you're doing it from one of the views inside the nib, use:
-(void)awakeFromNib;
Which is called after the view's subviews have been loaded.
If you are adding subviews programmatically (e.g. [myView addSubview:anotherView]), then of course there is no way to know; the program could add more subviews at any time, if you write it that way.
If you are loading the view from a nib, you are probably looking for the awakeFromNib method. From the NSObject UIKit Additions Reference:
The nib-loading infrastructure sends an awakeFromNib message to each object recreated from a nib archive, but only after all the objects in the archive have been loaded and initialized. When an object receives an awakeFromNib message, it is guaranteed to have all its outlet and action connections already established.
I am converting an iPhone app to a Universal app. I have a NIB view which I want to use on the iPad as is but resized and positioned. On the iPhone I am initializing normally with initWithNibName...
EventEditViewController *eventEditViewController = [[EventEditViewController alloc] initWithNibName:#"EventEditViewController" bundle:nil];
I found that this did not work well for me on the iPad for various reasons. So I created my own initialization method to call instead when running on the iPad...
EventEditViewController *eventEditViewControllerForIPad = [[EventEditViewController alloc] initWithFrame:iPadFrame eventDate:longDate event:eventName delegate:self];
This solved a couple of problems. One how to resize and position the view where I wanted it and how to properly initialize certain variables. I am actually passing more variables than you see here.
It works really well, but I just now noticed that, unlike initWithNibName viewDidLoad fires before my initWithFrame method. I only found this out because a variable I was trying to access in viewDidLoad was showing up as a zombie and I thought I was initializing it in my initWithFrame method.
I was surprised by this behavior. Is it normal? It doesn't make sense to me that the view would be loaded before the named initMethod in the alloc/init call.
I am now wondering if what I am doing might not be a good thing. Like I said it works really well, but should I not use my own initialization method here?
If it's ok to do it this way, maybe someone can explain why the view loads before the init method.
Thanks,
John
If your -initWithFrame:... method is accessing the view controller's view property, -viewDidLoad will be called before the init method completes because the view accessor will cause the view to be loaded.
As for whether it's okay to use your own method, it should be fine provided that your init method calls the designated initializer for the class.
Initializing member variables should be done in viewDidLoad or awakeFromNib.
awakeFromNib is the first method that gets called when a view comes to life from a Xib.
It's preferred to use viewDidLoad for allocating memory for huge arrays since you can deallocate them in viewDidUnload.
Both navigation controller and tab bar controller uses view loading methods to unload views when other views demand more memory.
Allocating in anyother methods should be avoided as far as possible.
From Apple's PageControl source code
// load the view nib and initialize the pageNumber ivar
- (id)initWithPageNumber:(int)page
{
if (self = [super initWithNibName:#"MyView" bundle:nil])
{
pageNumber = page;
}
return self;
}
You can have your own custom init method defined in that EventEditViewController and you can use a custom method like above to initialize your viewController and set as many member variables as you want like iPadFrame, longDate, eventName etc in your case.
Just make sure you call it exactly as above as it's important to call super implementation in such custom init methods.
Also just to shed more light on where you should release arrays you created in viewDidLoad method, it's the dealloc method first in addition to viewDidUnload. The reason behind this is viewDidUnload method doesn't always get called. It gets called only when application starts receiving memory warnings. As compared to this, the method dealloc gets automatically called always when you release the initialized viewController and it's retain count reaches 0. You should release the arrays you initialized viewDidLoad method and your other retain properties in dealloc method.
Also keep in mind that when the app receives memory warning, it's actually a chance to free up additional memory. Also the viewDidUnload method gets called for all the viewControllers in memory except visible one at that time.