views:

59

answers:

2

I got this code:

GrooveOnDownload *dlg = [[GrooveOnDownload alloc] init];

NSURLDownload *dw = [[NSURLDownload alloc] initWithRequest:request delegate:dlg];

It starts the download in a delegate class with outlets for UI controls. But for some reason controls don't respond to direct messages from the delegate.

//Header of the delegate
@interface GrooveOnDownload : NSObject {
IBOutlet id downloadButton;
//...

//Implementation 
//...
[downloadButton setEnabled:FALSE]; // Doesn't work
//...

Any ideas?

It is my fourth day of Mac development so I don't know much about the platform.

Edit : 2010-05-28 01:03:41.486 GrooveOnLite[3303:a0f] Download button = (null)

Edit 2 :

alt text

Edit 3 : I miss Windows .....

Edit 4 In Win32 you send one window message to the button. Everything is handled by WndProc loop. It is damn simple. In Mac you have this magical interface builder which somehow gets all that crap working. The delegate gets called by some withcraft magic. The rest of the classes are connected by some 'magical' force. In windows there is an tmain function which is the entry point. That's it! No retarded outlets and such shit.

+3  A: 

I know it sounds obvious, but is everything connected correctly in Interface Builder?

Edit

If the download is on a separate thread, then fbrereto is correct and you'll need to perform the selector on the main thread. Your code would need to be changed to look like this:

[downloadButton performSelectorOnMainThread:@selector(setEnabled:)
    withObject:[NSNumber numberWithBool:NO]
    waitUntilDone:YES];

A few notes: in Objective-C the keyword NO is used instead of FALSE. It's a primitive type, so in order to use it here we had to box it in a NSNumber object. The waitUntilDone argument does exactly what you would expect, and you can change that to NO if you'd rather not wait.

Edit 2

Here's a more complete code example about how to accomplish what I think you want, which is to reuse a single instance of GrooveOnDownload from your app delegate. I'm assuming that your app delegate class is called GrooveOnLiteAppDelegate.

// GrooveOnLiteAppDelegate.h
@interface GrooveOnLiteAppDelegate : NSObject
{
    IBOutlet GrooveOnDownload *grooveOnDownload;
    // other properties go here
}

// your method signatures go here
@end

// GrooveOnLiteAppDelegate.m
@implementation GrooveOnLiteAppDelegate

- (void)mySuperAwesomeMethod
{
    // it's up to you to figure out what method to put this in and
    // how to call it
    NSURLDownload *dw = [[NSURLDownload alloc] initWithRequest:request delegate:grooveOnDownload];
}

@end

Given that code in your app delegate, you'll have an outlet in IB that you can connect to your GrooveOnDownload object in IB. If you do that, then grooveOnDownload will be a pointer to that object.

Justin Voss
Two outlets are set up in the interface builder. One for the progress bar and one for the button. I'm pretty sure everything is correct.
Nick Brooks
Doesn't work ... the button remains enabled
Nick Brooks
Add a line like `NSLog(@"Download button = %@", downloadButton);` If it comes out as `(null)`, then downloadButton isn't set correctly.
Justin Voss
2010-05-28 01:03:41.486 GrooveOnLite[3303:a0f] Download button = (null)
Nick Brooks
Yep, there you go. downloadButton isn't connected to anything, so any messages you send to it will be ignored. You probably haven't connected the actual button in Interface Builder to your outlet.
Justin Voss
I have - downloadButton -> Round Rect Button
Nick Brooks
I'm not sure what you mean by that. Here's what you need to do: in Interface Builder, select your GrooveOnDownload object and in the inspector, choose the 'Connections' tab. Drag from the circle next to 'downloadButton' onto the actual button in your view. That should make the connection.
Justin Voss
I deleted the old outlet and remade it just to be sure. It made no difference
Nick Brooks
My code is located in a different class which doesn't interact with the delegate. The delegate is empty. If that method is in delegate it is virtually useless.
Nick Brooks
Creating an outlet in GrooveOnSearch (Which is the class which has all the code in it) didn't help ...
Nick Brooks
Or how do I even call 'superAwesomeMethod' ?
Nick Brooks
+3  A: 

All UI calls have to be made on the main thread; if the download is happening in the background your delegate may be getting notified on a thread other than the main one, in which case a call to a UI element would have to be done through something like -[NSObject performSelectorOnMainThread:withObject:waitUntilDone:modes: or another related API.

fbrereto
Can I have an example of accessing my button that way?
Nick Brooks
[downloadButton performSelectorOnMainThread:@selector(setEnabled:) withObject:[NSNumber numberWithBool:NO] waitUntilDone:NO]
Squeegy
Neither does that :(
Nick Brooks