How do I reload a bound NSTableView after adding a record?
-
In the past, using the Connections approach, after I added a record to
the Data Source of an NSTableView
I would do a [myTableView reload]; in the addNewRecord method.
This was possible because in MyDocument I had an instance variable for
myTableView and the Connection was made in IB.
But things are different in using Bindings and I'm still on the
learning curve.
So far I have bound the add_a_record Button's target to the MyDocument
a.k.a. Files' Owner (thank you mmalc).
As I debug, my data source shows that there are now two objects (having
started off with only one).
If I Save the document, close it, and then re-open it the second record
shows up.
So that part of it seems to be working as hoped for.
However the tableview is not redrawn to show the second record when I
add it.
I searched the archives and googled but didn't find anything relevant (
using NSTableView binding reload).
So how does one get the view updated using bindings?
TIA for your help...
respect....
Peter
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
On Aug 24, 2004, at 11:28 AM, Peter.Teeson wrote:> So how does one get the view updated using bindings?<http://homepage.mac.com/mmalc/CocoaExamples/controllers.html>
>
See section "Programmatic modifications to arrays not noticed by table
view."
mmalc
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
Best (eaisest) way I found is the following...
willChangeValueForKey:
// do you work here
// add, remove, whatever you want
didChangeValueForKey:
just set the key to whatever your using for your table and the table
will display itself as needed
- lee> On Aug 24, 2004, at 11:28 AM, Peter.Teeson wrote:_______________________________________________
>
> So how does one get the view updated using bindings?
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
Lee Thank you very much!!
I changed my code from this
- (void)addClientAccount {
[clientList addUserAccountsRecord];
}
to this
- (void)addClientAccount {
[self willChangeValueForKey:@"clientList"];
[clientList addUserAccountsRecord];
[self didChangeValueForKey:@"clientList"];
}
Presto changeo it worked. Wow!
I also re-read the docn on KVO and they show just what you suggested.
Boy this bindings stuff does take a while to get an understanding. But
it's pretty neat really (when it works).
(mmalc thanks for your web note; do you think adding such an example
would be helpful in that section?
Although I read what you wrote I didn't understand it without seeing
sample code.)
On Aug 24, 2004, at 18:46, Lee Morgan wrote:> Best (eaisest) way I found is the following..._______________________________________________
>
> willChangeValueForKey:
> // do you work here
> // add, remove, whatever you want
> didChangeValueForKey:
>
> just set the key to whatever your using for your table and the table
> will display itself as needed
>
> - lee
>
>> On Aug 24, 2004, at 11:28 AM, Peter.Teeson wrote:
>>
>> So how does one get the view updated using bindings?
> _______________________________________________
> cocoa-dev mailing list | <cocoa-dev...>
> Help/Unsubscribe/Archives:
> http://www.lists.apple.com/mailman/listinfo/cocoa-dev
> Do not post admin requests to the list. They will be ignored.
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
Always glad to be of assistance. Besides mmalc helped me solve this
problem a matter of days ago :-)
- lee
On Aug 24, 2004, at 8:43 PM, Peter.Teeson wrote:> Presto changeo it worked. Wow!_______________________________________________
> I also re-read the docn on KVO and they show just what you suggested.
> Boy this bindings stuff does take a while to get an understanding. But
> it's pretty neat really (when it works).
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
On Aug 24, 2004, at 5:43 PM, Peter.Teeson wrote:> I changed my code from thisI do have an example of manual notifications, right at the end, but it
> - (void)addClientAccount {
> [clientList addUserAccountsRecord];
> }
> to this
> - (void)addClientAccount {
> [self willChangeValueForKey:@"clientList"];
> [clientList addUserAccountsRecord];
> [self didChangeValueForKey:@"clientList"];
> }
> Presto changeo it worked. Wow!
> I also re-read the docn on KVO and they show just what you suggested.
> Boy this bindings stuff does take a while to get an understanding. But
> it's pretty neat really (when it works).
>
> (mmalc thanks for your web note; do you think adding such an example
> would be helpful in that section?
> Although I read what you wrote I didn't understand it without seeing
> sample code.)
>
illustrates a slightly different situation...
I'm not sure that I would recommend the approach you've taken.
If I understand correctly, you're adding a new record to an object that
represents a client list, so that object itself has a to-many
relationship to userAccountsRecords?
What the notification you're sending says is that your clientList
reference has changed. Whilst it'll work, this is inefficient and
strictly speaking incorrect. You should probably (modulo my
understanding of your design) instead implement a method in the
ClientList class that adds a record itself, either calling a suitable
indexed accessor (e.g. insertObject:inUserAccountsRecordsAtIndex:) or
something more like that shown at the end of my page but for a single
object.
mmalc
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
BTW, I'm sorry but I used a different method.
I used the
willChange:<#(NSKeyValueChange)change#> valuesAtIndexes:<#(NSIndexSet
*)indexes#> forKey:<#(NSString *)key#>
didChange:<#(NSKeyValueChange)change#> valuesAtIndexes:<#(NSIndexSet
*)indexes#> forKey:<#(NSString *)key#>
I while the other ones that I posted earlier work fine...as mmalc
pointed out (this time and before to me) they are very inefficient, as
they force the entire contents to be updated instead of only the ones
that need updating.
Even better would be using mmalc's method mentioned, as it conforms
better to bindings and Cocoa's overall structure.
But at any rate it works.
- lee
On Aug 24, 2004, at 9:17 PM, mmalcolm crawford wrote:> On Aug 24, 2004, at 5:43 PM, Peter.Teeson wrote:_______________________________________________
>> I changed my code from this
>> - (void)addClientAccount {
>> [clientList addUserAccountsRecord];
>> }
>> to this
>> - (void)addClientAccount {
>> [self willChangeValueForKey:@"clientList"];
>> [clientList addUserAccountsRecord];
>> [self didChangeValueForKey:@"clientList"];
>> }
>> Presto changeo it worked. Wow!
>> I also re-read the docn on KVO and they show just what you suggested.
>> Boy this bindings stuff does take a while to get an understanding. But
>> it's pretty neat really (when it works).
>>
>> (mmalc thanks for your web note; do you think adding such an example
>> would be helpful in that section?
>> Although I read what you wrote I didn't understand it without seeing
>> sample code.)
>>
> I do have an example of manual notifications, right at the end, but it
> illustrates a slightly different situation...
>
> I'm not sure that I would recommend the approach you've taken.
> If I understand correctly, you're adding a new record to an object
> that represents a client list, so that object itself has a to-many
> relationship to userAccountsRecords?
>
> What the notification you're sending says is that your clientList
> reference has changed. Whilst it'll work, this is inefficient and
> strictly speaking incorrect. You should probably (modulo my
> understanding of your design) instead implement a method in the
> ClientList class that adds a record itself, either calling a suitable
> indexed accessor (e.g. insertObject:inUserAccountsRecordsAtIndex:) or
> something more like that shown at the end of my page but for a single
> object.
>
> mmalc
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
Thank you Malcom for your time on this.
On Aug 24, 2004, at 21:17, mmalcolm crawford wrote:> On Aug 24, 2004, at 5:43 PM, Peter.Teeson wrote:Yes I saw that under the batch load. But I am only adding a single
>> I changed my code from this
>> - (void)addClientAccount {
>> [clientList addUserAccountsRecord];
>> }
>> to this
>> - (void)addClientAccount {
>> [self willChangeValueForKey:@"clientList"];
>> [clientList addUserAccountsRecord];
>> [self didChangeValueForKey:@"clientList"];
>> }
> I do have an example of manual notifications, right at the end, but it
> illustrates a slightly different situation...
record.> I'm not sure that I would recommend the approach you've taken.I don't think it's a to-many but maybe my understand is not correct.
> If I understand correctly, you're adding a new record to an object
> that represents a client list, so that object itself has a to-many
> relationship to userAccountsRecords?
FWIW here is the interface:
#import <Cocoa/Cocoa.h>
#import "UserAccountsData.h"
@interface ClientList : NSDocument {
UserAccountsData *clientList;
}
// Acceessor methods
- (UserAccountsData *)clientList;
- (void)setClientList:(UserAccountsData *)newUserAccountsData;
// Action methods
- (void)addClientAccount;
@end
and here is part of the interface for UserAccountsData:
#import <Cocoa/Cocoa.h>
@interface UserAccountsData : NSObject {
NSMutableArray *userAccountsRecords; // collection of
UserAccountRecords
}
-(id)initWithCoder:(NSCoder *)coder; // designated initialiser
// Accessor methods
- (NSMutableArray *)userAccountsRecords;
- (void)setUserAccountsRecords:(NSMutableArray *)newUserAccountsRecords;
// Action methods
- (void)addUserAccountsRecord;
@end
// Following are the constituents of a single UserAccountRecord
// Forward declarations
@class UserAccountAddress, UserAccountPhonesEtc;
@interface UserAccountRecord : NSObject {
NSString *accountID;
NSString *listingName;
NSString *billingName;
UserAccountAddress *mainAddress;
UserAccountPhonesEtc *mainPhonesEtc;
UserAccountAddress *secondaryAddress;
UserAccountPhonesEtc *secondaryPhonesEtc;
}
etc.......> What the notification you're sending says is that your clientListI was hoping that it was saying that the mutable arrray of
> reference has changed.
userAccountsRecords has changed because I added a record. Am I wrong
here?> Whilst it'll work, this is inefficient and strictly speaking incorrect.
> You should probably (modulo my understanding of your design) instead
> implement a method in the ClientList class that adds a record itself,
> either calling a suitable indexed accessor (e.g.
> insertObject:inUserAccountsRecordsAtIndex:) or something more like
> that shown at the end of my page but for a single object.
I expect to be able to re-use the UserAccountsData as a base class
since it's pretty generic. That's why I made ClientList inherit from
it.
There will be some other properties of ClientList that are unique to it
and I'll add them later once I get the fundamental structure working.
Later on I might make, for example ContactList, also using
UserAccountsData as the base class, and it too would have unique
properties of it's own.
Does this elucidate the design some more? If so does that change your
advice given above?
If not I ask you to explain, if you would be so kind and patient, just
why it is not efficient, and why it is incorrect?
TIA and
respect....
Peter
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored. -
On Aug 25, 2004, at 1:55 PM, Peter.Teeson wrote:> Thank you Malcom for your time on this.The same general principle (of calling change methods) applies.
>
> On Aug 24, 2004, at 21:17, mmalcolm crawford wrote:
>> On Aug 24, 2004, at 5:43 PM, Peter.Teeson wrote:
>>> I changed my code from this
>>> - (void)addClientAccount {
>>> [clientList addUserAccountsRecord];
>>> }
>>> to this
>>> - (void)addClientAccount {
>>> [self willChangeValueForKey:@"clientList"];
>>> [clientList addUserAccountsRecord];
>>> [self didChangeValueForKey:@"clientList"];
>>> }
>> I do have an example of manual notifications, right at the end, but
>> it illustrates a slightly different situation...
> Yes I saw that under the batch load. But I am only adding a single
> record.
>>> I'm not sure that I would recommend the approach you've taken.If I'm following things through correctly, then I would suggest:
>> If I understand correctly, you're adding a new record to an object
>> that represents a client list, so that object itself has a to-many
>> relationship to userAccountsRecords?
> I don't think it's a to-many but maybe my understand is not correct.
>
In UserAccountsData:
@interface UserAccountsData : NSObject {
NSMutableArray *userAccountsRecords; // collection of
UserAccountRecords
}
// Accessor methods
- (NSMutableArray *)userAccountsRecords;
- (void)setUserAccountsRecords:(NSMutableArray *)newUserAccountsRecords;
Add suitable indexed accessors (probably also remove the standard
accessors):
<http://developer.apple.com/documentation/Cocoa/Conceptual/
KeyValueCoding/Concepts/AccessorConventions.html>
- (unsigned int)countOfUserAccountsRecords;
- (id)objectInUserAccountsRecordsAtIndex:(unsigned int)index;
- (void)insertObject:(id)anObject
inUserAccountsRecordsAtIndex:(unsigned int)index;
- (void)removeObjectFromUserAccountsRecordsAtIndex:(unsigned int)index;
// - (void)replaceObjectInUserAccountsRecordsAtIndex:withObject: (This
is optional, but provides performance enhancements, and may be required
if you make any modifications to objects in insertObject: inKeyAtIndex:
that you want to avoid in a replacement.)
Reimplement:
- (void)addClientAccount {
[self willChangeValueForKey:@"clientList"];
[clientList addUserAccountsRecord];
[self didChangeValueForKey:@"clientList"];
}
back to:
- (void)addClientAccount {
[clientList addUserAccountsRecord];
}
Implement addUserAccountsRecord something like:
- (void)addUserAccountsRecord
{
UserAccountRecord *newRecord = [[UserAccountRecord alloc] init];
// do any other initialisation
[self insertObject: newRecord
inUserAccountsRecordsAtIndex:[userAccountsRecords count]];
[newRecord release];
}
Note there are no manual KVO notifications -- these are handled
automatically by the indexed accessor methods.
(If the client list is managed by an array controller, there may not
even be any need for addUserAccountsRecord -- leave it to the array
controller to add a new record using its add: method.)> -(id)initWithCoder:(NSCoder *)coder; // designated initialiserAn aside: This should almost certainly not be the designated
>
initialiser for the class.>> What the notification you're sending says is that your clientListYes, you're saying that the whole of the UserAccountsData object
>> reference has changed.
> I was hoping that it was saying that the mutable arrray of
> userAccountsRecords has changed because I added a record. Am I wrong
> here?
>
(called 'clientList') has changed, not that that object's
userAccountsRecords array has been modified. This is inefficient as
more updates will be made than is necessary.
mmalc
_______________________________________________
cocoa-dev mailing list | <cocoa-dev...>
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.


