Re: Creating NSTableView programmatically
Re: Creating NSTableView programmatically
- Subject: Re: Creating NSTableView programmatically
- From: Jonathan Mitchell <email@hidden>
- Date: Mon, 11 Dec 2017 11:46:52 +0000
For NSTableCellView see
https://developer.apple.com/documentation/appkit/nstablecellview
objectValue is a property on NSTableCellView not on NStableView.
The NSTableViewDelegate method
- (NSView *)tableView:(NSTableView *)tableView
viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
provides the required NSTableView instances on demand.
You also need to bind the NSTableView's content object to the
NSArrayController’s arrangedObjects.
The nib makes all this easier though its still fiddly.
I would get it working in a nib first and then work backwards from there.
> On 11 Dec 2017, at 10:59, Eric Matecki <email@hidden> wrote:
>
>
> Hello,
>
> I'm trying to implement in Objective-C on macOS *programmatically* the "Real
> World Example" at the bottom of this page :
> https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CocoaBindings/Concepts/WhatAreBindings.html
>
> I want to do it programmatically instead of using IB to really understand
> what happens.
>
> Just creating the "Attacker" NSTableView causes me already a lot of trouble.
> My code is at the bottom of this message.
>
> I can't just bind "value" of the attacker tableview to the array controller's
> "arrangedObjects.name",
> I get a "this class is not key value coding-compliant for the key value"
> exception.
>
> So I create a column (I think this is mandatory anyway...).
> In my delegates tableView:viewForTableColumn:row: I create a text field
> (NSTextView).
> (I create a textfield for now, will probably be a NSButton in the final
> version).
>
> I now see a table with four rows (the number of entries in my array), each
> with a text field I can edit.
> But they start empty and don't change my array of combattants.
>
> How do I bind this text field to the right "thing" ?
>
> According to the last paragraph of this page:
> https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/TableView/PopulatingViewTablesWithBindings/PopulatingView-TablesWithBindings.html
> I have to :
> """
> When you make the connection to the table view’s Content binding, the
> objectValue property of the NSTableViewCell used as the cell for the table
> column is configured such that for each item in the model array, the table
> updates the objectValue property to the current row’s Person object.
> """
> But NSTableViewCell doesn't seem to exists (a search on Apple's dev doc gives
> 27 results... all about *UI*TableViewCell)
>
> So I need to bind "value" from the text field to "objectValue.name" from...
> something...
> Whatever I try I get either an exception for not KV compliance, or it doesn't
> seem to do anything.
>
> Please shed some light on this...
> Thanks.
>
> CODE:
>
> #include "Cocoa/Cocoa.h"
>
> //===============================================================================================================
> cCombattant
>
> @interface cCombattant : NSObject
>
> @property (copy) NSString* weapon1;
> @property (copy) NSString* weapon2;
> @property (copy) NSString* weapon3;
> @property (copy,readwrite) NSString* name;
> @property NSString** selectedWeapon;
>
> - (cCombattant*)initWithName: (NSString*) iName;
>
> //DEBUG
> - (void)addObserver: (NSObject *)observer
> forKeyPath: (NSString *)keyPath
> options: (NSKeyValueObservingOptions)options
> context: (void *)context;
>
> //DEBUG
> - (void)removeObserver: (NSObject *)observer
> forKeyPath: (NSString *)keyPath;
> @end
>
>
> @implementation cCombattant
>
> - (cCombattant*)initWithName: (NSString*) iName
> {
> self = [super init];
>
> [self setWeapon1: @"Dagger"];
> [self setWeapon2: @"Sword"];
> [self setWeapon3: @"Pike"];
> [self setSelectedWeapon: &_weapon1];
> [self setName: iName];
>
> return self;
> }
>
> //DEBUG
> - (void)addObserver: (NSObject *)observer
> forKeyPath: (NSString *)keyPath
> options: (NSKeyValueObservingOptions)options
> context: (void *)context
> {
> printf( "[%p addObserver: %p forKeyPath: %s options: XXX context: %p]\n",
> self, observer, [keyPath UTF8String], /*options,*/ context );
> int bkpt=bkpt;
> [super addObserver: observer forKeyPath: keyPath options: options
> context: context];
> }
>
> //DEBUG
> - (void)removeObserver: (NSObject *)observer
> forKeyPath: (NSString *)keyPath
> {
> printf( "[%p removeObserver: %p forKeyPath: %s]\n", self, observer,
> [keyPath UTF8String] );
> int bkpt=bkpt;
> [super removeObserver: observer forKeyPath: keyPath];
> }
>
> @end
>
> //===============================================================================================================
> cDelegate
>
> @interface cDelegate : NSObject < NSTableViewDelegate >
>
> - (cDelegate*)init;
>
> @end
>
>
> @implementation cDelegate
>
>
> - (cDelegate*)init
> {
> self = [super init];
> return self;
> }
>
> - (NSView *)tableView:(NSTableView *)tableView
> viewForTableColumn:(NSTableColumn *)tableColumn
> row:(NSInteger)row
> {
> NSTextView* view = [[NSTextView alloc] init];
> [view setRichText: NO];
> [view setFieldEditor: YES];
> [view bind: @"value" toObject: tableView withKeyPath:
> @"objectValue.name" options: 0];
> return view;
> }
>
> @end
>
> //===============================================================================================================
> JustDoIt2()
>
> void
> JustDoIt2()
> {
> @try{
> NSArray* combattants =
> [[NSArray alloc] initWithObjects:
> [[cCombattant alloc] initWithName: @"Atilla"],
> [[cCombattant alloc] initWithName: @"Vlad"],
> [[cCombattant alloc] initWithName: @"Doris"],
> [[cCombattant alloc] initWithName: @"Cthulhu"],
> nil
> ];
> printf("combattants = %p\n", combattants);
>
> NSArrayController* controller = [[NSArrayController alloc]
> initWithContent: combattants];
> [controller setSelectedObjects: combattants]; //TEST: select all, doesn't
> seem to change anything...
>
> printf("controller = %p\n", controller);
>
> NSTableView* table = [[NSTableView alloc] initWithFrame: NSMakeRect( 5,
> 5, 400, 400 )];
> [table setBackgroundColor: [NSColor redColor]]; // just to be sure to
> see it when empty...
> [table setDelegate: [[cDelegate alloc] init]];
>
> NSTableColumn* column = [[NSTableColumn alloc] initWithIdentifier:
> @"name"];
> [table addTableColumn: column];
>
> printf("Binding table to arrangedObjects\n");
> [table bind: @"content" toObject: controller withKeyPath:
> @"arrangedObjects" options: 0];
>
> NSWindow* window = [[NSWindow alloc]
> initWithContentRect: NSMakeRect( 50, 50, 500, 500 )
> styleMask: NSWindowStyleMaskTitled
> backing: NSBackingStoreBuffered
> defer: NO
> ];
>
> [[window contentView] addSubview: table];
>
> //TEST
> //printf("Changing controller's content\n");
> //[controller setContent: combattants2];
>
> [window makeKeyAndOrderFront: 0];
> }@catch(NSException*e){
> int bkpt=bkpt;
> }
> }
>
>
> --
> Keep intel OUTSIDE my Mac !
> Hiii !!! I can see Intel chips creeping around my G5 !
>
> Eric M.
> _______________________________________________
>
> Cocoa-dev mailing list (email@hidden)
>
> Please do not post admin requests or moderator comments to the list.
> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
>
> Help/Unsubscribe/Update your Subscription:
>
> This email sent to email@hidden
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden