when i load my viewController i used "viewDidLoad"method to init my view ,but this take much time to make the view appeared .So i had the idea to use "viewDidAppear" method to accelerate the appearance of my view but the load of the informations about my view are now loaded to the memory every time that i push my view (which is normal) or i pop to it(and there is my problem)
Have you an idea?
Create a background task that is started in viewDidLoad and just updates the GUI when it's finished. This should at least let you show the GUI, but possibly without valid data.
According to the View Controller Programming Guide, you are supposed to create your view in the loadView method :
If you prefer to create views programmatically, instead of using a nib file, you do so from your view controller’s loadView method. You must override this method if you plan to create your views programmatically.
Maybe you should create your view in the loadView method and then load extra data in the viewDidLoad as explained in Understanding the View Management Cycle, using a background task as suggested by willcodejavaforfood if necessary.
i did it with the method "ViewDidAppear:animated" and for the problem of loading data for every appearance i deal with it with a test on the top of the mehod:
if(data==nil){/*i do ...*/}
and for me data was an array that i am writing on when loading the view
Related
I need to create a class that will present a UIVIew and has a some code to initialize it before it is ready to show. I need to know when the view is ready, I mean, I need something like viewDidLoad or viewWillAppear, but as it is a UIVIew it lacks these protocols.
I cannot implement it as a UIViewController as I don't want to present it modal. It is really a rectangular view that needs to show on a screen side.
How do I declare this class? If the class is a UIView based I don't have the methods I mentioned.
thanks
Any reason to not do that kind of stuff inside the initWithFrame method on a UIView? Also, you can do additional stuff on layoutSubviews. A view controller has viewDidLoad because the view is lazy loaded (from a nib or otherwise - it also has a loadView). It has viewWillAppear and viewWillDisappear because it is managing the view (btw, even the view controller is managed by another view controller - these methods are called when you have the controller within a UINavigationController or UITabBarController or such classes which mange UIViewControllers. - the view itself is not really managing anything. All it knows about is how to draw itself. For that, you have layoutSubViews, drawRect, etc.
Doing some heavy stuff upon view's load will definitely kill the UI performance. You probably need to implement another kind of design pattern that will asynchrounously assign data values to the instance of your custom view - when that is done, you call layoutSubviews or setNeedsDisplay to update the view.
The scenario you described is no reason for not implementing a UIViewController. Assume you have a container view A and a subview B. Both have their own UIViewController AC and BC. Now on AC you add the View B managed by BC:
[self.view addSubview:BC.view];
You probably want to be using UIViewController.
You don't just have to present them modally. You can get your view controller's view with yourViewController.view, and add that as a subview of whatever view you want.
If you're targeting iOS 5, there are a few new methods (such as addChildViewController:) designed to make doing things like this easier. You can do it on iOS 4 too though, and it'll still work.
Implement a drawRect in youR UIView, plus an initialization flag. Just before the view is to be displayed the drawRect will be called. If the initialization flag isn't yet set, do your initialization and set the flag. This will only look good if your initialization can be done quickly (no long synchronous calls).
I need to create a class that will present a UIVIew and has a some code to initialize it before it is ready to show. I need to know when the view is ready, I mean, I need something like viewDidLoad or viewWillAppear, but as it is a UIVIew it lacks these protocols.
You might want to rethink how your view is being used. It sounds like you're trying to put too much controller-like logic into your view. That's why you're wanting your view to behave like a controller.
More specifically: What exactly are you trying to accomplish? If you're waiting for data to load before display the view, that might actually be something to put in the controller that is calling the view.
To illustrate my point, imagine you're putting some text in a UILabel that you read from disk. The reading from disk isn't really related to the view. The view only cares what text it displays, not how it received the text. Once it's read from disk, you can create a UILabel with that text that you read. This allows the UILabel to be more flexible.
That example might not be at all related to what you're doing, but I use it as an example of the difference between a view and a controller. Anything not related with the display and drawing of the view shouldn't belong there.
Suppose I have a navigation controller where the next action is to take a picture or select an image from the library.
If I initialize UIImagePickerController during didSelectRowAtIndexPath:, (I believe) the response will be a little slower as the controller needs to initialized. Also, if the user cancels and opens again, it would reinstantiate that controller every time.
However, if I create the controller during viewDidLoad: of the navigation controller, it takes up memory while the user is on that view. Side questions: Does this, however, slow down the loading time of the navigation?
Or should it be done in an NSOperation when the view is loaded?
Overall, what would be the best place to load the ImagePicker?
I'd lazy load the controller when it first gets called (in didSelectRowAtIndexPath) so it wouldn't have to be reloaded every time, and not worry about initialization time.
It seems that in your case you will always need an image picker on didSelectRowAtIndexPath. You can load it on the view and customize (camera, cameraroll, etc.) and present on the row selection. Probably it doesn't matter that much. UIImagePickerController presentation is very slow anyway, especially with the camera.
I don't recommend an NSOperation for this task.
I'm trying to figure out what logic should go into the different UIViewController methods like viewDidLoad, viewDidAppear, viewWillAppear, ...
The structure of my app is that I have a root view controller that doesn't really have a view of its own, rather it has a tab view controller and loads other view controllers into it. But in the future, it may have to load other view controllers instead of the tab bar controller depending on app logic.
My main question is, what do people usually put into the viewDidLoad, .... methods.
Currently I:
viewDidLoad - setup the tab bar controller and set its view to the view controller's own view
viewDidAppear - check if user has stored login info
if not - present with login
if so, login and get app data for first tab
I'm trying to figure out now if my logic for setting up my tab bar controller should go into loadView rather than viewDidLoad.
Any help would be great. Small examples found on the web are great, but they don't go into detail on how larger apps should be structured.
You should not implement both -viewDidLoad and -loadView; they are for different purposes. If you load a NIB, you should implement -viewDidLoad to perform any functions that need to be done after loading the NIB. Wiring up the tabbar is appropriate there if you haven't already done it in the NIB.
-loadView should be implemented if you do not use a NIB, and should construct the view.
-viewWillAppear is called immediately before you come onscreen. This is a good place to set up notification observations, update your data based on model classes that have changed since you were last on screen, and otherwise get your act together before the user sees you. You should not perform any animations here. You're not on the screen; you can't animate. I see a lot of animation glitches due to this mistake. It kind of works, but it looks weird.
-viewDidAppear is called after you come onscreen. This is where you do any entry animations (sliding up a modal, for instance; not that you should do that very often, but I was just looking at some code that did).
-viewWillDisappear is called right before you go offscreen. This is where you can do any leaving animations (including unselecting tableview cells and the like).
-viewDidDisappar is called after you're offscreen (and the animations have finished). Tear down any observations here, free up memory if possible, go to sleep as best you can.
I touch on setting up and tearing down observations here. I go into that in more depth in View controllers and notifications.
viewDidLoad will be called once per lifetime of each UIViewController's view. You put stuff in there that needs to be set up and working before the user starts interacting with the view.
viewDidAppear is called whenever the view has appeared to the user. It could potentially be called more than once. An example would be the root screen of an app using a UINavigationController to push and pop a hierarchy of views. Put stuff in there that you'd want done every time. For example, you might want to hide the UINavigationBar of the root screen, but show it for all subscreens, so you'd do the hiding of the bar here.
Therefore, you'd put your logic for setting up your UITabBarController in viewDidLoad, since it only should be done once.
Regarding your app, is there a reason why you don't just make the UITabViewController be the controller loaded by your app delegate? It seems that you have a level of indirection in your app that you may or may not need. It's probably better to simplify it now, and refactor later if you need something more complex.
I'm learning to develop for iPhone without Interface Builder (a personal preference), and I'm not sure which function of a view controller I should be setting up the view in: init, viewDidLoad, or loadView. I read somewhere to only use init for the view controller, if anything, and not setting up the view as it could cause problems. I also read that viewDidLoad is only for loading from nib files, but It worked when I tried using it.. so what stuff should I put in each of these 3 methods?
Thanks!!
Well each method has its own purpose
1) init
This method is intended to just initialize the ViewController , you are not required to override this method, but if you want to do some custom initialization BEFORE any views are loaded then this could be a place to do it. You have different flavors of the init methods, you can look at the in the docs at apple site.
2) loadView
this method here is used to programatically create your view. If this method is not overriden, the default w ill create an empty view for you, but if it is you MUSt initialize viewController.view property, this gets called when a UIViewController view gets pushed into a super view.
3) viewDidLoad
this method is called after you view has loaded on the screen (After loadView has been called and the view is pushed on the super view or window). Here you can do you can add subViews to your controllers views and also do other set up that you want to occur once your view loads. This method works regardless of making a view f rom a nib or programatically.
At the beginning of my app, I am initializing a UIViewController with a NIB.
At some point, I am removing the view from the screen, then releasing it, so it no longer takes up memory. (At this point I am also saving the state of the view in the UIViewController)
At a later point, I want to recreate the view and bring it back on screen. I will then restore its state. (Using the same UIViewController, not a new one, since it saved the state)
My question, is when I recreate the view, how do I do so from the NIB, or is this not possible?
To me, the obvious remedies are:
Don't save state in the UIViewcontroller (Where does convention dictate that I do save state?)
Don't release the view (maybe just release all of its subviews?)
Don't load my view from a NIB, create programmatically (seems to go against using IB for everything)
Note:
I am not using a UINavigationController, I am handling the swapping of the views myself, since thee are only 2 of them.
If you need that level of control, you dont really want to use IB. Because, as you noted, if remove the view and then later recreate it, you would have to do it in code then anyway. Just design most of the views in IB, then write some code that generates just this view. Then you can call that same method again later to recreate that view when you need it.
You may be able to archive it and later turn it back into an object, but that seems like an inelgant solution. IB does not allow for dynamic creation of controls at runtime, even if they used to exist but don't anymore. There is no shame in leaving IB out of loop for this. In fact it's probably a good idea.
OR
If its a complicated view with a lot of pieces, put the view in it's own nib, and make a view controller for it. Then you can simply instatiate the view controller with the nib name, and add the controllers view as a subview to you main view. Then your view controller handles loading of the nib, and you get to design it in IB. Nothing says the view of a view controller has to take up the entire screen either.
self.otherController = [[OtherController alloc] initWithNibName:#"Other" bundle:nil];
[self.view addSubview:otherController.view];
Don't create the view controller and the view in the same nib file; either create the controller in code or put the view in a separate nib file. If you later nil out your controller's view property, the controller should recreate the view.
But why are you so worried about this? There's already a mechanism to automatically free up the view if you're low on memory: the low memory warning. It will only destroy and recreate the view if you actually need to do so, and it's built in to the system so you don't have to do anything. Remember the saying about premature optimization?