views:

259

answers:

3

I am new to iPhone and objective c. I have spent hours and hours and hours reading documents and trying to understand how things work. I have RTFM or at least am in the process.

My main problem is that I want to understand how to specify where an event gets passed to and the only way I have been able to do it is by specifying delegates but I am certain there is an easier/quicker way in IB.

So, an example. Lets say I have 20 different views and view controllers and one MyAppDelegate. I want to be able to build all of these different Xib files in IB and add however many buttons and text fields and whatever and then specify that they all produce some event in the MyAppDelegate object. To do this I added a MyAppDelegate object in each view controller in IB's list view. Then I created an IBAction method in MyAppDelegate in XCode and went back to IB and linked all of the events to the MyAppDelegate object in each Xib file.

However when I tried running it it just crashed with a bad read exception.

My guess is that each Xib file is putting a MyAppDelegate object pointer that has nothing to do with the eventual MyAppDelegate adress that will actually be created at runtime.

So my question is...how can I do this?!!!

+1  A: 

If you create an instance of MyAppDelegate in each nib file then, yes, you do end up with a lot of different instances of the class when all the nibs load. The app delegate is not identified by class or even protocol but rather by being the object pointed to by the application instance's delegate property. To find the true app delegate, you have have to ask the application object itself for its delegate

You should have all your view controllers descend from a parent view controller class that has an appDelegate property. Implement something like this:

#import "MyAppDelegateClass.h"

@interface ViewControllerBaseClass :UIViewController {
    MyAppDelegateClass *appDelegate;
}
@property(nonatomic, retain)  *appDelegate;

@end

@implementation ViewControllerBaseClass
@synthesize appDelegate;

-(MyAppDelegateClass *) appDelegate{
    self.appDelegate=(MyAppDelegateClass *)[[UIApplication sharedInstance] delegate];
    return appDelegate;
}
@end

When the view controller needs the app delegate it just calls self.appDelegate. If you want to access an attribute of the app delegate use self.appDelegate.attributeName.

The important thing is that you ask the application for its specific delegate instance at runtime. You can't do that from a nib file.

TechZen
If I said @property (nonatomic,retain) IBOutlet MyAppDelegateClass *appDelegate and then subclassed each one of my viewcontrollers from this base Viewcontroller and then added the various IBAction methods in my AppDelegate itself then surely there is some way to connect those IBOutlets in Interface builder instead of in code? Up to now I have done it programmatically by just setting the appDelegate property to self when loadingthe view controllers from within the MyAppDelegateClass but i think the [UIApplication ...] line will be better. But isnt there a way in IB??
twerdster
An app delegate is a specific instance. You have to point to that specific instance or you don't reach the actual delegate. Simply giving a class an outlet does not let its subclasses point to a specific instances. Each of those outlets has to link to the specific app delegate instance that the app objects uses as its delegate.
TechZen
Nib files are intended to be modular and to have a restricted scope. By design, they do not depend upon and cannot see the entire app or even the application object. As such, only the nib owned by the application object itself (usually MainWindo.nib) can see the active delegate.
TechZen
If wanted to hook this up in IB, you could create a small utility class whose function is to find the active app delegate instance. Then you could add that class to any random nib and hook an outlet up to that. That would let you manage access to the app delegate in nibs without subclassing.
TechZen
Okay, great answer. Thank you very much for you time and efficient response.
twerdster
A: 

In general you should be making a view controller for each of the views you are building, and link events to those view controllers - not the app delegate. In fact usually no event ever is wired to the app delegate from any nib file, even in the sample projects you'll note that view controllers are created and held onto by the app delegate, but it does not receive events.

Kendall Helmstetter Gelner
+1  A: 

I'm not entirely clear what exactly you're trying to do, but it's probably a bad idea. There should only be one app delegate per application, and it should deal with behavior for the whole application. Typically, the app delegate initializes the root view controller(s) and displays them, but not much else (other than handling things like opening and saving data sources).

The view controllers (subclasses of UIViewController) should interact with the XIBs. Having the view-specific behavior in the view controllers makes the app much easier to manage and maintain. Typically, there should be 0 or 1 XIBs per view controller (more than that is complicated). You set up the interaction with the views using the Target/Action pattern with IBOutlets and IBActions (see here for a complete guide). It's generally a bad idea to make view controllers or XIBs dependent on the app delegate (since reducing dependencies again makes the code easier to manage).

eman
Okay, I will ask a slightly different question then. How do I create one view controller that controls a number of different views where each view is defined in separate nib files. Lets say I build 5 views in 5 different nibs with nothing else in the nib hierarchy except the views. Now I build a nib with a view controller but no views. How can I initialize the MyAppViewController with a run time specified view. Is there an option in UIView to do that? Do I then have to set the files owner of each nib-with-only-a-view to be of type MyAppViewController? Or how should it be done?
twerdster