How to communicate between objects - iphone

Still having trouble with this language.
Ok, let's say I have two objects. The first is my application delegate, the second is a custom view containing the various buttons that make up the main menu. When a button is clicked, it is the menu that responds. However, I need to make use of certain instance variables in the application delegate (such as the Window) in order to implement the appropriate changes. In this case, I want the main menu to be removed and replaced with a new view. In other words, the main menu needs to trigger a method held in the application delegate.
So, how should I go about this?

I did a blog post on my web site a ways back that distills the process down into the simplest way I could come up with to describe setting up a delegate.
http://www.dosomethinghere.com/2009/07/18/setting-up-a-delegate-in-the-iphone-sdk/

The preferred way is to create a delegate protocol for your view controller. Your application delegate can then implement this protocol and act on behalf of your view controller.
Check out the part about Delegation in the Cocoa Fundamentals Guide. Also read through the docs about Modal View Controllers, as this is quite similar to what you're trying to do. There are some code examples there as well.

Related

Pass data between views in tabs iOS

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.

How do I set up several custom UIViewControllers under one central view controller programmatically?

Being new to Xcode and Objective-C I find it hard to get my head around the Interface builder and Objective-C when doing things that are following the basic pattern. I have created a subclass of UIViewController that I want to instantiate several times to make a grid with each row being controlled by an instance of this class. So there will be one root view controller (with navigation etc) that should include/genereate all the instances of the custom sub-viewcontroller.
Now what would be the best way to do this? All examples I can find are about navigation, where one view should replace another, but I want to have all the viewcontrollers visible on the same "page". Do I need to create a nib file for the custom controller at all? I have also been thinking about using the UITableView somehow but inserting my custom viewcontroller in every row.
Any help greatly appreciated!
Apple's documentation recommends using one view controller per screen. It is possible to decompose your interface and use multiple view controllers on one screen if you have a good reason to do it, but Apple hasn't really designed their frameworks to support this, so you'll run into pitfalls if you don't know what you're doing.
In this case, I question whether each row of your grid really needs its own view controller. I find it hard to imagine a case where this would be the best choice, although it's hard to say for sure without knowing more about your app. Some things to consider:
What is your custom controller doing? Is it mostly changing the visual appearance of its corresponding grid row? If so, perhaps it would be more appropriate to subclass the UIView itself.
If this object is really behaving as a controller and not a view, consider implementing it as a subclass of NSObject rather than subclassing UIViewController. The UIViewController for your screen can capture events and delegate them to the appropriate custom controller object, or your custom views can capture their own events and notify their associated controllers of those events directly using a delegate pattern.
If you're sure you have a valid reason to implement these objects as UIViewController subclasses, check out my answer to this question.

How do I access the view that is one level up from my current view in a navigation-based iOS app?

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.

Invoke a method from a different view controller. iPhone SDK

So I have an application with two view controllers one is the main controller that launches when the app launches. This view controller Has two buttons on opens a uiwebview to google.com the other opens that same uiwebview but loads a different page.
How can I change the nsurl that is loaded in the other view controller from the original view controller.
I'm not completely sure of what you're asking, but generally, if you ever need to communicate between related views (or even views and modal views), most of the time your best bet is to set up a protocol in one view and become a delegate in another by conforming to that protocol. You'll then be able to fire off methods in the first view which your second view can customize.
If you've ever created a table view then you're already loosely familiar with the delegate pattern. For a nice and simple introduction to delegates and protocols, I found this blog post to be one of the best out there.

Must a view controller always have a delegate in iPhone apps?

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.