如何通过NSArrayController从Core Data填充NSTableView?

时间:2022-04-27 20:06:05

Originally I was populating my NSTableView via an outlet and had set the dataSource of the table to my controller class. I'm trying to switch to using an NSArrayController so I can enable sorting by column in my app.

最初我通过插座填充我的NSTableView并将表的dataSource设置为我的控制器类。我正在尝试切换到使用NSArrayController,以便我可以在我的应用程序中按列进行排序。

In IB, I've added an Array Controller object. I have the Sort Descriptors binding connected to Shared User Defaults Controller so that the sorted column can be persisted between launches of my app. I have each column of my table bound to the Array Controller, the controller key is set to 'arrangedObjects' and the Model Key Path is set to the name of the field that should be rendered.

在IB中,我添加了一个Array Controller对象。我将Sort Descriptors绑定连接到共享用户默认值控制器,以便可以在我的应用程序启动之间保留已排序的列。我将表的每一列绑定到Array Controller,控制器键设置为'arrangeObjects',Model Key Path设置为应该呈现的字段的名称。

My data is coming from Core Data, and the entity I am trying to display has a relationship to another entity. An attribute on the 2nd entity needs to be displayed as the value for one of the table columns. Anyone have any thoughts/suggestions for me on what I'm missing here?

我的数据来自Core Data,我试图显示的实体与另一个实体有关系。第二个实体上的属性需要显示为其中一个表列的值。对于我在这里缺少的东西,任何人都有任何想法/建议吗?

MainWindowController.h

MainWindowController.h

#import <Cocoa/Cocoa.h>
#import "Notification.h"

@class AppDelegate;

@interface MainWindowController : NSWindowController <NSTableViewDataSource, NSTableViewDelegate> {
    AppDelegate <NSApplicationDelegate> *appDelegate;
}

//@property NSMutableArray *userNotifications;

@property (weak) IBOutlet NSTableView *notificationsTable;
@property (weak) IBOutlet NSArrayController *notificationsController;

@end

MainWindowController.m

MainWindowController.m

#import "AppDelegate.h"
#import "MainWindowController.h"
#import "Utils.h"

@implementation MainWindowController

//@synthesize userNotifications;

@synthesize notificationsTable;
@synthesize notificationsController;

- (void) doubleClick:(id)sender
{
    NSInteger row = [notificationsTable clickedRow];

//  Notification *clickedNotification = [userNotifications objectAtIndex:row];
//  Notification *clickedNotification = 

//  [appDelegate redirectToBrowser:clickedNotification];
}

- (id) initWithWindowNibName:(NSString *)windowNibName
{
    self = [super initWithWindowNibName:windowNibName];
    if (self) {
//      userNotifications = [[NSMutableArray alloc] init];
        appDelegate = (AppDelegate *) [[NSApplication sharedApplication] delegate];
        [notificationsController setManagedObjectContext:[appDelegate managedObjectContext]];
        [notificationsController setEntityName:@"Notification"];
        [notificationsController setAutomaticallyPreparesContent:YES];

        [notificationsController fetch:self];
        [notificationsTable reloadData];
    }
    return self;
}

- (void)windowDidLoad
{
    [super windowDidLoad];

    // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.

    [notificationsTable reloadData];
}

- (void)awakeFromNib
{
    [notificationsTable setTarget:self];
    [notificationsTable setDoubleAction:@selector(doubleClick:)];
}

1 个解决方案

#1


1  

There are two solutions to this issue:

这个问题有两种解决方案:

  1. Add an App Delegate object to IB by adding a new object and setting the class to AppDelegate.
  2. 通过添加新对象并将类设置为AppDelegate,将App Delegate对象添加到IB。
  3. Assign the App Delegate as an instance variable appDelegate of the controller rendering your window by adding the below code to your .h and .m files:
  4. 将App Delegate指定为控制器的实例变量appDelegate,通过将以下代码添加到.h和.m文件中来呈现窗口:

Controller.h

或者Controller.h

@class AppDelegate;

@interface Controller : NSWindowController {
    AppDelegate <NSApplicationDelegate> *appDelegate;
}

Controller.m

Controller.m或者

#import "AppDelegate.h"

- (id) initWithWindowNibName:(NSString *)windowNibName
{
    self = [super initWithWindowNibName:windowNibName];
    if (self) {
        appDelegate = (AppDelegate *) [[NSApplication sharedApplication] delegate];
    }
    return self;
}

In either case, you'll need to add a new binding for the Array Controller. Navigate to the Binding pane in the Inspector and set the Managed Object Context (under Parameters) to Bind to (1) the App Delegate or (2) the File's Owner, then set the Model Key Path to (1) self.managedObjectContext or (2) self.appDelegate.managedObjectContext

在任何一种情况下,您都需要为Array Controller添加新的绑定。导航到Inspector中的Binding窗格,并将Managed Object Context(在Parameters下)绑定到(1)App Delegate或(2)File的Owner,然后将Model Key Path设置为(1)self.managedObjectContext或( 2)self.appDelegate.managedObjectContext

#1


1  

There are two solutions to this issue:

这个问题有两种解决方案:

  1. Add an App Delegate object to IB by adding a new object and setting the class to AppDelegate.
  2. 通过添加新对象并将类设置为AppDelegate,将App Delegate对象添加到IB。
  3. Assign the App Delegate as an instance variable appDelegate of the controller rendering your window by adding the below code to your .h and .m files:
  4. 将App Delegate指定为控制器的实例变量appDelegate,通过将以下代码添加到.h和.m文件中来呈现窗口:

Controller.h

或者Controller.h

@class AppDelegate;

@interface Controller : NSWindowController {
    AppDelegate <NSApplicationDelegate> *appDelegate;
}

Controller.m

Controller.m或者

#import "AppDelegate.h"

- (id) initWithWindowNibName:(NSString *)windowNibName
{
    self = [super initWithWindowNibName:windowNibName];
    if (self) {
        appDelegate = (AppDelegate *) [[NSApplication sharedApplication] delegate];
    }
    return self;
}

In either case, you'll need to add a new binding for the Array Controller. Navigate to the Binding pane in the Inspector and set the Managed Object Context (under Parameters) to Bind to (1) the App Delegate or (2) the File's Owner, then set the Model Key Path to (1) self.managedObjectContext or (2) self.appDelegate.managedObjectContext

在任何一种情况下,您都需要为Array Controller添加新的绑定。导航到Inspector中的Binding窗格,并将Managed Object Context(在Parameters下)绑定到(1)App Delegate或(2)File的Owner,然后将Model Key Path设置为(1)self.managedObjectContext或( 2)self.appDelegate.managedObjectContext