The situation:
I'm writing my first iPhone app; it's an opengl game and I want to use separate views... The first view is the menu screen, a normal UIView/UIViewController with a high scores list and some buttons for configuring and starting a new game. The second view is a GLKView/GLKViewController combo, which will display the game.
I have a model, which includes the game state, player data, the high scores list, etc. I need to share this model between the two views. I've seen examples of this before, where the model is instantiated in the application delegate, and references to it are passed to each view controller that needs access to it. I'd do it that way, but I don't know how to access the view controllers in my storyboard.
My questions:
Is this the way I should be doing things? To reiterate, I want my model to be owned by the AppDelegate, and I will pass references to the view controllers from the application:didFinishLaunchingWithOptions: method. If there's a better way to solve this problem, please let me know.
Assuming the above is the right way to do things, how would I go about doing it? I'm not sure how to access the items in the storyboard.
Since the app delegate has references to the view controllers as well as the model, it should be able to update whichever view is currently active whenever the model changes.
Ideally, the model shouldn't be talking directly to the views: it should tell the app delegate that it has changed, and then the app delegate will tell the appropriate view to update.
I think this is the question you're asking; if it's not, let me know what I'm missing and I'll try answering again.
Related
I am just starting out on iOS(from Android) and I am having trouble figuring out how to pass data between views in tabs. I've included pictures to describe my question in a little more detail; how can I get the map type to change when one of the selectors is changed or the user location to appear/disappear when the boolean switch is ticked?
One tab is a map tab:
The Other is a selector:
The quick answer is that you have the view controllers talk to each other.
Edit: I knew I'd have to come back.
It depends on where you are starting from.
But This thread seems to be popular and has an example project. It might need tweaking to use a more modern iOS version - but it does provide the general idea.
One way to do it in your application, is to have properties on the view controller that shows the map as to the type of view it displays, and whether or not the current location is shown. Then, from your selector's view controller set those properties.
How do you get the map's view controller - pass it to the selector's controller at creation. Resist the temptation to have the map controller be a property of the Application delegate. It's an easy way of passing it around, but it breaks encapsulation IMO.
As an aside.
As you progress, you'll realise that the way to do this is to have the controls overlaid on the map view as subviews. Not only is that a better UI (all the changes can be made in place), but then as you are on the same view, you don't need to use a different view controller, and there is no need to be passing around object pointers. :)
You should check out this thread for a very detailed description of each possible method:
What's the best way to communicate between view controllers?
You will have to use NSNotifications or NSUserDefaults
Check objective-c updating data from a different view
For this type of "Settings" view, I'd create a custom protocol and set your map view as the delegate object in your settings view. Let me know if you need code.
Well, my first answer would be that a tabbed interface probably isn't appropriate here. Tab bars are to provide parallel modes of usage (e.g a watch app that shows either an alarm or a timer), not to provide subsidiary information. You should probably have a button on the mapview that pulls up a modal dialog to change the settings. That then uses a delegate pattern to send the changed information back to the parent. See apple's document on Modal View Controllers for sample code.
I'm diving into iOS development and am getting familiar with navigation view controllers. I'm trying to build a simple app with a table view that allows me to add objects to it. So far, I have a table view with an add "+" button in the nav bar that allows me to load my CreateObjectView and display it modally so the user can define the new object, but when they click the save button, I don't know how to send that object data back to the parent view that created the CreateObjectView that contains the object data.
When I create the child view (CreateObjectView), I could pass into it a pointer to the current view before I push it onto the nav stack, but this just feels dirty and circular.
I was reading about protocols and delegates and I could use that approach as well, but it also feels circular.
This question seems like it would be a common design issue to any tableview-based or nav-based app, how should I probably access the view that is one level up from my current view in a nav-based iOS app?
Thanks so much in advance for all your help!
It feels circular at first, but it is the right way. Before the UINavigationController pushes the new view controller you should set the delegate to the current view controller - assuming that's the object you wish to communicate with. Of course you could set it somewhere else instead, such as to a central Core Data handler. Then when you need to communicate call the delegate with the method you have defined. I've done several navigation apps like this after seeing Apple's cookbook example, and it really works well.
I'm learning how to develop my own iPhone apps but I'm having a tough time understanding certain concepts.
First, am i right to say that for every view, there must be a view controller for it? And for every view controller, must there be a delegate for it?
Also, what is the role of mainWindow.nib? Most of the tutorials that i've read don't seem to touch that nib at all. What always happens is the setting up of a NavigationController as the root controller, which pushes another ViewController onto the stack and this ViewController will have another nib associated with it.
So can i assume that i can safely ignore the main window nib?
It's all about MVC (Model View Controller), innit?
The Model, well that's up to you - what does your app do? Think of it as the backend, the engine of your app, free of the cruft of font size decisions and touch events.
The View, Apple pretty much wrote that for you. You use their Textfields and tables and imageViews. You assemble them together using Interface Builder into your GUI (packaged as a .nib). You rarely, if ever need to subclass the standard view elements (in a game you want a custom View to draw to, as all your drawing is probably custom). You can break different parts of your GUI into different .nib files if this helps you manage them. It's entirely up to you.
The Controller, so you have probably got some work todo to enable your GUI to represent your model. You need Some Controllers. How many? However many is manageable by you. If you had a view containing 2 subviews would they each need a view controller? Nah, probably not. How complicated is your code to hook up the view to the model?
Some GUI patterns are so common that Apple even wrote the Controller code for you. EG the controller for a UINavigationBar, UINavigationController. So, if your app has hierarchical views that you need to navigate around and you need to display a navigation bar you can use an instance of UINavigationController instead of writing your own class. Yay!
Surely tho, the UINavigationController code (or any other viewController) can't magically know how to integrate with our model, with our view, can it? NO, it can't. In general in Cocoa if there is some class of object that mostly works off the shelf but also has optionally configurable behavoir - allowing us to tailor it to our needs - it is done by Delegation. ie Instead of subclassing UINavigationController we tell the specific instance of it where to find (for want of a better term) it's custom behavoir.
Why? Let's say you have a navigationController, a tableView and a textfield. UINavigationController mostly take care of your navigation needs but you have to have a crazy QUACK sound play each time the user moves to a new view. UITableView is mostly exactly everything you need from a table, EXCEPT you really want the third row in the table on the front page be twice the height of the other rows. And the standard, off -the-shelf UITextField pretty much takes care of your textfield needs EXCEPT you need your textfield to only be editable when the user is facing North. One way to handle this would be to create 3 new classes, a custom UINavigationController, a custom tableView and a custom textfield, and to use these instead. With delegation we could use the classes as they are and have one object be the delegate of all 3 instances - much cleaner.
Delegation is mostly optional, the docs will tell you when, and it's down to you and whether you need that custom behavoir.
Here's another very basic question. Is there an easy way to rename the rootviewcontroler? Say I decided that I needed to add a page before the current rootview (splash page, mini data snippets from the main app, etc.) How hard would it be to create another rootviewcontroller? I guess you would just take the current one and edit out lots of stuff.
Thanks.
Make a new viewcontroller for any view or set of views that manage different user experiences or tasks. I have a root viewcontroller in most of my apps to handle transitions and provide a few global methods, and then a viewcontroller (VC) for my settings UI, another for my game, another for my high scores list, etc.
Adding new VCs are as simple as the first one you added. If you are a bit timid about VCs, there are other classes that can keep some of the VC handling hidden in their code, like the Navigation Controller.
Please read up on VCs to see how they are intended to be used. Here is one.
I'm starting out in iPhone development, and I'm trying to do a Contacts-style controller to add items to a table. I've got the two controllers designed, but I can't seem to figure out how to pass data between them. How can I get data from the modal controller to its parent?
Just trying to call methods on parentViewController won't work (and results in compiler warnings and crashes). I've considered moving the data out of the controller itself (which is going to happen anyway, I'm just trying to keep things as simple as possible for now), but even then I still have to somehow tell the parent view to refresh its data. Again, how can I do this?
I've considered moving the data out of the controller itself (which is going to happen anyway
I think now may be the time to follow that consideration and create a separate "ContactList" model object to store your data.
Your modal view controller just adds new "Contacts" into the "ContactList".
Your TableViewController should observe the same "ContactList". As items are added/removed to/from the "ContactList" your TableViewController will simply add and remove rows from its tableView.
In this way you will keep each ViewController independent, your code will be more flexible and adding/removing single rows will be much more efficient than reloading an entire tableView.
You either keep a link to the sub view you create and ask it for data that has changed on return, or else ad yourself as a delegate of a subview and have it call you back directly (which does work if you have a valid reference).
I had the same question and found this sample code: http://developer.apple.com/iphone/library/samplecode/LocateMe/Introduction/Intro.html
Helped me a ton and was pretty easy to figure out from the code.
In short, use delegate.
I would suggest you have a look at Lecture 11: Text input, Presenting content modally (May 6) - iPhone App Programming course offered by Stanford. Search for it on iTunes U.
Download this sample app if you want to know how to implement delegate: http://www.stanford.edu/class/cs193p/downloads/11-Pickers.zip