无法从代理访问UI?

时间:2010-05-27 23:44:12

标签: objective-c cocoa

我收到了这段代码:

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

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

它在带有UI控件出口的委托类中开始下载。但由于某些原因,控件不响应代表的直接消息。

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

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

有什么想法吗?

这是我开发Mac的第四天,所以我对这个平台了解不多。

编辑: 2010-05-28 01:03:41.486 GrooveOnLite [3303:a0f]下载按钮=(null)

编辑2:

alt text http://i47.tinypic.com/ermqdx.png

编辑3: 我想念Windows .....

编辑4 在Win32中,您向该按钮发送一个窗口消息。一切都由WndProc循环处理。这很简单。在Mac中你有这个神奇的界面构建器,它以某种方式获得所有垃圾工作。代表被一些魔法师召唤。其余的课程由一些“魔法”力量联系在一起。在Windows中有一个 tmain 函数,它是入口点。而已!没有迟钝的网点和这样的狗屎。

2 个答案:

答案 0 :(得分:3)

我知道这听起来很明显,但在Interface Builder中是否所有内容都正确连接?

修改

如果下载是在一个单独的线程上,那么fbrereto是正确的,你需要在主线程上执行选择。您的代码需要更改为:

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

一些注意事项:在Objective-C中,使用关键字NO代替FALSE。它是一种原始类型,所以为了在这里使用它,我们必须在NSNumber对象中将它包装起来。 waitUntilDone参数完全符合您的预期,如果您不想等待,可以将其更改为NO

修改2

这是一个更完整的代码示例,介绍如何完成我认为您想要的内容,即从您的应用委托重用单个GrooveOnDownload实例。我假设您的app委托类名为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

鉴于您的应用代理中的代码,您将在IB中有一个插座,您可以连接到IB中的GrooveOnDownload对象。如果你这样做,那么grooveOnDownload将是指向该对象的指针。

答案 1 :(得分:3)

所有UI调用都必须在主线程上进行;如果下载发生在后台,您的代理可能会在主要线程以外的线程上收到通知,在这种情况下,必须通过-[NSObject performSelectorOnMainThread:withObject:waitUntilDone:modes:或其他相关API等方式调用UI元素。