lab12
lab12

Reputation: 6448

Update UI from another Class Method - Cocoa

I would like to update the UI in my application from the AppDelegate, but whenever I call it as so:

Controller *object = [[Controller alloc] init];
[object methodHere];

It doesn't seem to update the UI. What am I doing wrong here? I have put in a NSLog to see if it was being called, and it is. Here is a sample project that shows the error.

Edit: Can someone just show me what to change to the project I provided. I just don't know what to type into my project so that I can change the value of a simple NSTextField from another class.

Upvotes: 3

Views: 3065

Answers (3)

jscs
jscs

Reputation: 64002

This is really simple, and Chuck's comments basically explain what you need to do, but I will lay out the code explicitly for you. In testAppDelegate.h:

@interface testAppDelegate : NSObject <NSApplicationDelegate> {
    NSWindow *window;
    // You can make an IBOutlet to any kind of object you
    // want; it's just a way for you to get a reference
    // in code to an object that has been alloc'd and
    // init'd already by the xib mechanism.
    IBOutlet Controller *controller;

}

Then go into your xib in InterfaceBuilder and hook up that outlet from your Test App Delegate object to your Controller object (these objects are already present in the xib).

In testAppDelegate.m:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    // This is the key:
    // _Don't_ alloc/init a new controller object. The 
    // objects in your xib are allocated and initialized 
    // by virtue of being in that file. You just need to 
    // give your AppDelegate a pointer to it, as above.
    [controller setTextValue:@"hello"];
}

Upvotes: 4

Nicholas1024
Nicholas1024

Reputation: 890

It's being called all right, but it's not connected to the interface. There should be a view controller of some sort defined in your appDelegate.h file, call the method on that object instead.

Update for more detail: One way you could pull this off would be to simply save the Controller when you originally create it (and not release it until later.)

Simply put your own controller object into your .h file

Controller* myController;

And when you create the new view controller you want to flip to, simply set myController to reference that object, and later when you want to update the UI, simply call

[myController methodHere];

A bit clumsy, but it works. Just don't forget to release myController when you're done with that view.

The other idea I'd suggest looking into would be to alter the method you're passing to your delegate. That is, instead of having the method as

-(returnType)callDelegateToDoSomething;

put it in as

-(returnType)callDelegateToDoSomething:(id) sender;

You call the new method the same way, but your controller should automatically pass itself as an argument. Then, inside the method, simply use

[sender methodHere];

and it should hopefully work. (You may need to play around with it a little. I'm not an expert on delegates or the sender argument, but it's worth a shot.)

Upvotes: 3

Chuck
Chuck

Reputation: 237060

When you write [[Controller alloc] init], you are not accessing the Controller object that is in your nib. You are creating a new Controller object that is unconnected to anything else in your application.

Remember, every Controller object is not the same any more than every NSArray is the same. Just because you made one Controller in your nib that's connected to an NSTextField does not mean some random Controller that you just created shares that controller's connections.

What you need to do is give the delegate a reference to the Controller that's in the nib.

Upvotes: 9

Related Questions