I'm bit of a newbie and had a basic question regarding adhering to the MVC model in iPhone coding.
How do I setup a Model class that holds my data and connect it to different controllers in the following setup:
Using Interface Builder, I created a tab controller in which
- Tab #1 has a Nav Controller and a hierarchy of View Controllers.
- Tab #2 has a View Controller
So with what I have now, the View Controller under Tab #1 alloc init's the model class and I know how to pass the model from one ViewController to the next in the Navigation Hierarchy where it can pass the data and/or be updated with new data.
Question is how to pass it from Tab #1's View Controller to Tab #2 View Controller as there is no code linking the two???
Thanks in advance,
Hiren.
It really depends on your application's needs. There are a number of approaches. For what you've described, I'd probably (a) add a Model to your root view controller, then add/update the various view controllers when they're selected (a delegate here would be useful, too) or (b) create a Singleton for your data model.
I would suggest having the model owned by the application delegate. The controllers can get the delegate using [[UIApplication sharedApplication] delegate] and load data using properties or methods.
Related
I am currently working with Swift and I was learning about MVC - one question that popped out was this: I am trying to implement a WKWebView - and I already know how to do this within a ViewController.
My question is: should I create my own WebView class to place the WKWebView or should I only house it with in the ViewController? I am trying to follow the MVC structure.
It's a web view, so it should be placed in the view controller in the storyboard. This really has nothing to do with MVC, per se.
The view controller is your Controller.
The view controller's root view and the web view you're putting in it are the View.
The Model may or may not be relevant here since a model is usually just a data structure that the Controller uses to populate the View. It could just be the HTML that you pass to the web view.
My question is: should I create my own WebView class to place the WKWebView or should I only house it within the ViewController? I am trying to follow the MVC structure.
The view in Model View Controller really refers to a view and its entire graph of subviews. If a WKWebView instance is the view that contains everything that the controller will manage, then it's fine to make that "the" view; there's no need to put it inside another view just for the sake of containing it. On the other hand, if you want the same controller to manage other views not contained in the web view, then you can put the web view and the others all inside some other view and let the controller manage that.
How you organize your views really isn't determined by MVC -- just do what works. MVC really speaks to the way that the information your app operates on is owned and managed by a model, displayed in a view, and how the interactions between model and view are mediated by the controller.
This question is related to this.
I am using KLHorizontalSelect for showing tab bar with scroll option. I have dragged new 7 View Controller on storyboard. If I select Popular, popular view controller should get displayed.
Any idea/ suggestions on how to get this done?
This is a typical example of view controller containment (where you want one view controller to present other view controllers). Navigation controllers and tab bar controllers are example of built in container controllers. But effective iOS 5, Apple opened up containment for the rest of us.
Please see:
Implementing a Container View Controller in the UIViewController Class Reference.
Creating Custom Container View Controllers in the View Controller Programming Guide.
WWDC 2011 - Implementing UIViewController Containment
By the way, buried in the View Controller Programming Guide is subtle note about those four containment methods:
addChildViewController:
removeFromParentViewController
willMoveToParentViewController:
didMoveToParentViewController:
There are some strange interplay here. I would have thought that we, as application developers, would either just do the add... and/or remove... and that iOS would take care of all of the notifications for us, or that we would have to take care of the will... and did... notifications ourselves. But it's actually half-and-half. So read Adding and Removing a Child very carefully.
In an iPad application I have a tab Controller containing several view controllers. One of these view Controller (call it MainViewController) needs 2 table views side by side.
So I wrote 2 UITableViewController subclasses and from MainViewController, I alloc/init both subclasses of UITableViewController, and add the tableview from each to the MainViewController's view.
This means that UITableViewController subclasses's views are subviews of MainViewController's view.
This answer: https://stackoverflow.com/a/7684648/191463 says that doing that is incorrect and it seems Apple are starting to cut down on it.
I really do not want to have to put all the code from both UITableViewControllers in MainViewController, as it will make it much harder to read and in future could create duplicate code, if I want to use one of the tableview elsewhere in the app by itself.
Is this actually a problem, if it is how do I do it properly?
Apple isn't cutting down on it. This is the only way to create custom container view controllers prior to iOS 5. Apple actually listened to the developers and made it easier to do this sort of thing in iOS 5 with child and parent view controller methods, not to mention they made it so it worked hierarchically.
In most cases, this wouldn't actually be a problem in terms of applications crashing or performance or anything. It can be a problem in some cases, because let's say you have a child view controller. You add the view controller's view to your root view controller. Prior to iOS 5, child view controllers were things like navigation controller view controllers, tab bar controller view controllers, and modal view controllers. What happens when you have a button that calls [self.parentViewController dismissModalViewControllerAnimated:YES];? Technically, the view controller isn't being presented as a modal view controller, you added the view to the root view controller view.
In iOS5, you're able to add child view controllers to view controllers and are able to transition from one child view controller to another.
Now even if your view controller doesn't have a different parent, adding a "root" view controller to another root view controller isn't the best way to do it (especially since you don't get access to the parent view controller unless you explicitly create a parentViewController pointer in the child view controller). So in the end, Apple just made it easier and more decoupled.
It is OK to do it so long you take the responsibility of managing the viewController life cycle events
initWithNibName...
loadView:
viewDidLoad:...
.
.
viewDidUnload..
dealloc
memoryWarnings
orientation changes
So if you create a custom "container view controller" it becomes your responsibility to call all these methods on child viewControllers at the appropriate time. Think of it as "If you were to implement UITabBarController" what all will you have to manage regarding the children ??"
It quickly gets complex. Adding another viewController's view as subview is childs play.
iOS 5 does some of this stuff for you by specifying parent child relationship, however I still haven't seen any sample code anywhere yet to point to.
I'd say it is not incorrect or wrong to create view controller containers, especially when Apple engineers do that themselves. UITabBarController, UINavigationController or UISplitViewController - they are all view controller containers. More over many great apps with unique UX do that more common than you think. However the real issue is that it's quite hard to do it the right way, so e.g. view lifecycle, memory management and rotation handling is done properly along the hierarchy of views. Fortunately Apple guys did a decent job and iOS5 introduced lots of functionalities regarding controller containers:
UIViewController class reference
View Controller Programming Guide for iOS
If you're interested how above problems had to be addressed before iOS5, read these two very good blog posts:
Writing high-quality view controller containers
Using view controllers wisely
I am trying to develope an iPhone App for 3 months.
I found everything myself in books or the internet. Now I have a problem that I am not able to solve myself.
I would like to develope a tabbar application with 3 tabs.
In each tab is a navigation controller with a tableview.
The tableview loads the data from an XML file on the web. The difference between each tab is only the difference XML-url. The tableview and function should everywhere the same.
What have I done?
Created a tabbar application
Put 3 Navigation Controller in the Tab Bar Controller in the MainWindow.xib
Every View in each Navigation Controller points to the same "TableView" class
Now it loads on every tab the same tableview. But I just want to change the XML-URL which is loaded. But I dont know how to implementate this.
I hope that somebody can give me a hint? Thank you!
Are you sure you need a Tab Bar? You could just add an additional level of navigation on top for the sources. So your navigation controller stack would be like
UINavigationController -> SourceViewController -> ListViewController -> rest of your navigation stack.
ListViewController is a subclass of a UITableViewController which is passed the source url based on selection from SourceViewController which can be a subclass of UITableViewController too. This will save you of the repetition you are trying to avoid and is more likely a better option for the thing you need.
Now if you insist on using a Tab Bar, your stack will be more like –
UITabBarController which will have three instances of UINavigationController each with its own instance of ListViewController which like before will be initialized using a source url.
Now it may be smarter to reduce it to a single ListViewController and attaching all the navigation controllers to it. You can do this using the -tabBarController:didSelectViewController: method in the tab bar delegate. On every tab change/call, you clear the current cache that is providing data to the table view and load the appropriate cache based on the source XML of that tab.
Usually state is preserved on tab changes but using this structure you will have to do additional work to get that.
I am trying to write my first iPad app, and I have a problem.
I have my Main view controller with a button. Once the button is pressed, it requests a list of information from a web server, and returns the data. This data, I want to put into a table view in a popover.
I have the main view controller, and the data is received back and put into a dictionary, then that is looped through to get a couple of arrays of data.
I also have a Popover view controller that can display a static table view.
My question is, how do I get the data (either the dictionary, or the arrays) from the Main view controller to the Popover view controller?
I am really lost.
Thanks
James
There are two design patterns you have to keep in mind: delegation and notification. in a more general way also KVO is useful to update your view if the model changed. Of course the object listening for notifications or acting as a delegate is the controller of that view, NEVER the view itself.
There are two things you want to avoid at any time: storing stuff in global variables or in singletons and making "super objects" that act as let us say the model and the controller. Stick to the MVC paradigm and try to loose couple your objects and think about which object owns which other object. This is important for memory management and if you not implement it correctly it will come back to you later.
Check out session #116 - Model-View-Controller for iPhone OS from WWDC10 session videos and session #123 - iPhone View Controller Techniques from WWDC09.
The WWDC10 videos are available for free at apple's developer site.
Hey James, I suggest you first do your homework and try to get a taste on how so-called delegate structure works in most iOS apps.
To be more clear, your main view controller would become the delegate and your popover view controller would become the child of such a delegate. The delegate is responsible for presenting its child controller. At the same time, the child controller is responsible for asking for data from and reporting any changes to its delegate controller.
So in this way your popover controller can get the data it wants from your main view controller, and at the same time, when the user wants to dismiss the popover view, the popover view controller detects the user's instructions and informs the main view controller to dismiss it.
have described another possibility a few seconds ago:
Passing array between view controllers?