1

我的基于文档的应用程序有一个带有表格视图的窗口。tableview 有一个指向 NSObject 类型的类(称为 HopBill)的数据源,其中包括 NSMutableArray (aHopBill) 和所需的 tableview 方法。到目前为止,一切都很好。

为了向 tableview 添加行,我添加了一个由 NSWindowController(称为 HopBillSheetController)控制的工作表。当按下工作表中的 OK 按钮时。我实际上需要做两个 IBActions(这是不可能的):将行添加到 tableview 的数组并关闭工作表。我可以将工作表中的 OK 按钮连接到 NSWindowController(关闭工作表)或将其连接到 NSObject(将行添加到数组中)。但我想要两个:-)

是否可以从 NSObject 调用 NSWindowController 中的 IBAction?还是有其他方法可以做到这一点?

我是 Cocoo 和 Objective-C 的初学者,所以请温柔:-)

4

2 回答 2

1

如果您的工作表是带有 NSPanel 的 nib/xib,则关闭它的调用只是 [panel close];假设您的窗口控制器具有面板属性,您可以将关闭代码放在其添加行的 IBAction 的末尾。或者,如果您愿意,也可以让 IBAction 本身调用另一个方法。

如果您的面板正在运行模式,您可能也需要 stopModal。(如果面板关闭后一切都保持冻结状态,这就是所需要的;否则没关系。)

假设您的数据源 hopBill 是窗口控制器的一个属性,那么您在窗口控制器中编写的任何 IBAction 也可以访问 hopBill;它可以做你需要的一切。

因此,将单个 IBAction 添加到窗口控制器并将面板的 OK 按钮连接到它。那应该行得通。

至于从笔尖中的控件以外的其他地方调用 IBAction,是的,您可以这样做。使用对控件的引用作为发送方 arg,如果 IBAction 不使用发送方 arg,则使用 nil。

您还可以通过编程方式创建面板,或使用 NSAlert。但听起来您当前的设置更简单 - 因此更好。


查看应用程序控制器的这个 h 文件:Apple 的 ClockControl 示例

NSMutableArray *appointments 属性是 NSTableViewDataSource 协议方法将使用的实际数据源。IBAction“addAppointment”可以直接访问“appointments”:[self.appointments addObject:whatever atIndex:whatever];

可以修改 ClockControl 示例以使用 HopBill。您将在顶部导入它的声明:#import "HopBill.h" 然后它会声明 HopBill *hopBill; 而不是 "appointments" 属性。“addApointment”会像这样访问 HopBill 的可变数组 (aHopBill): [self.hopBill.aHopBill addObject:whatever atIndex:whatever];

于 2011-06-10T20:19:41.117 回答
0

为什么不能向 hopBill 发送消息:

首先,因为虽然你声明了它,但你从不初始化它。你有:

HopBill *hopBill;
[self.hopBill.aHopBill addObject: bHopAdditionAtInit];

它应该是:

HopBill *hopBill = [[HopBill alloc] init];
[hopBill.aHopBill addObject: bHopAdditionAtInit]; // “self” won’t work here

其次,您在 IBAction 方法 (doneHopBillSheet:) 中声明它因此它是一个局部变量,只能在该方法中访问。如果 HopBill 保存了表的数据源缓存,它应该是实现 NSTableViewDataSourceProtocol 方法的控制器的属性。

在您的 HopBill 接口中,您将 aHopBill 数组声明为一个属性,并在 HopBill 的 init 方法中对其进行初始化(您还应该在 HopBill 的 dealloc 方法中将其释放)。您需要为控制器做同样的事情——它应该有一个 HopBill 实例作为属性,并且该实例应该在控制器的 init 方法中初始化。

如果你想让 HopBillController 管理 tableview,它的接口声明应该是这样的:

@interface HopBillSheetController : NSWindowController <NSTableViewDelegate, NSTableViewDataSource> {
…
}

然后,当然,你必须实现相关的 NSTableViewDelegate 和 NSTableViewDataSource 方法。

此外,控制器必须具有表视图本身的 IBOutlet 属性,并且在控制器的 awakeFromNib 方法中,它必须将自己分配为委托和数据源:

[self.tableview setDelegate:self];
[self.tableview setDataSource:self];

(self-dot 语法假定您已经为 tableview 设置了 @property 和 @synthesize 代码。)

将项目添加到表中的 IBAction 方法必须在该控制器类中,或者在具有作为控制器类实例的属性的类中。然后 IBAction 方法将访问 aHopBill 数组并可以将新对象添加到数组中,之后它将调用 [tableView reloadData],这将依次触发 tableview 协议方法并更新表。

现在,这意味着包含 tableview 的 xib 必须将控制器作为其文件的所有者。由于您使用的是 NSDocument,因此我怀疑您会将 tableview 插座放在 NSDocument 子类中。你会给那个文档子类一个属性,它是控制器的一个实例。IBAction 方法也将在 doc 子类中,因此它们可以访问控制器及其 HopBill 属性。或者,您可能只是将 doc 子类设置为控制器,而不是使用单独的 HopBillSheetController 类。我不确定 NSDocument 的东西。但是,请记住,IBAction 方法本身可以调用其他方法,只要它可以访问声明这些方法的类的实例。

Apple 有一个同时使用 tableview 委托和数据源协议方法的示例。转到此链接并下载示例代码:tableview 示例

它看起来像一个不错的应用程序。祝你好运。

于 2011-06-12T15:29:02.033 回答