Re: Issue with -[NSOutlineView autosaveExpandedItems] - SOLVED

2014-07-13 Thread Bill Cheeseman

On Jul 12, 2014, at 5:57 PM, Ken Thomases k...@codeweavers.com wrote:

 You could do it this way:
   __block void (^__unsafe_unretained 
 innerFindItemForIdentifierInArray)(NSArray *);

Thanks. I had gotten as far as thinking that I needed a second block variable 
for the recursive call, but the proper placement of __unsafe_unretained didn't 
come to me.

 This still has a problem.  It doesn't stop when you intend it to.  Any given 
 -enumerate... call will stop if it directly finds the match, but an outer 
 call won't.  You could add if (returnItem) *stop = YES; after the recursive 
 call.  Or, you could pass the stop variable into the recursive call so that 
 an inner call can set it.


Thank you for catching that! I was so focused on getting the block syntax right 
that I completely overlooked the recursion issue.

Here's the final method. I should mention that my datasource is a property list 
(hence my use of dictionaries). The root array does not have an identifier. 
That's why I start right out with -enumerateObjectsUsingBlock:. I chose to use 
blocks instead of recursive method calls partly to force myself to become more 
familiar with block syntax, and partly because I understand that blocks 
executing on the stack are likely to be faster. This method may have to 
enumerate the datasource many times, depending on how many of the outline rows 
are expanded.

- (id)outlineView:(NSOutlineView *)outlineView 
itemForPersistentObject:(id)object {
// Datasource method per NSOutlineViewDataSource formal protocol. Required 
if using autosaveExpandedItems. Called when application launches, once for each 
item in the autosaved array in the user defaults preferences file. AppKit calls 
this before -awakeFromNib, so the source list data source must be populated in 
the designated initializer.

NSString *identifier = [NSKeyedUnarchiver unarchiveObjectWithData:object];

__block id returnItem = nil;
__block void (^__unsafe_unretained 
innerFindItemForIdentifierInArray)(NSArray *);
__block void (^findItemForIdentifierInArray)(NSArray *) = ^(NSArray 
*contents) {
[contents enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL 
*stop) {
if ([[obj objectForKey:ID_KEY] isEqualToString:identifier]) {
returnItem = obj;
*stop = YES;
}
id subarray = [obj objectForKey:CONTENTS_KEY];
if (subarray) {
innerFindItemForIdentifierInArray(subarray); // recursive
if (returnItem) {
*stop = YES;
}
}
}];
};
innerFindItemForIdentifierInArray = findItemForIdentifierInArray;

findItemForIdentifierInArray([self sourceListContents]);
return returnItem;
}

-- 

Bill Cheeseman - b...@cheeseman.name

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: KVC, binding multiple properties, top level object

2014-07-13 Thread Trygve Inda
 
 On 12 Jul 2014, at 10:05 pm, Trygve Inda cocoa...@xericdesign.com wrote:
 
 ---someProperty (Custom NSObject)
 --propertyA (NSNumber)
 --propertyB (NSNumber)
 --propertyC (NSNumber)
 
 Properties A, B and C use a binding to connect them to a user interface item
 with something like:
 
 Bind to MyObject with key path someProperty.propertyA
 
 
 Just as a matter of interest, why do you decalre these subproperties as
 NSNumber types? Is there a reason you can't just make them the native scalar
 types they wrap (e.g. integer, float)? KVC/KVO automatically wraps scalar
 values with NSNumber or NSValue to pass them around through bindings, so you
 don't have to concern yourself with it. Usually, code is clearer if properties
 are declared as the native types. If you make them NSNumbers, how will you
 detect or prevent a value of the wrong type being passed?
 
 --Graham
 
 
 

Would using NSInteger (instead of NSNumber) still work right when doing KVC
in something like:


-(void)encodeWithCoder:(NSCoder *)coder;
{
for (NSString* key in [self propertyKeys])
[coder encodeObject:[self valueForKey:key] forKey:key];
}


What gets returned from [self valueForKey:key]? I guess the system wrapes
the NSInteger in an NSNumber?




___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

-[NSOutlineView autosaveExpandedItems] bug?

2014-07-13 Thread Bill Cheeseman
I have encountered what I consider a bug, or at least a design error, in the 
NSOutlineView autosaveExpandedItems mechanism.

Normally, when you expand or collapse an outline row, AppKit calls the 
NSOutlineViewDataSource method -outineView:persistentObjectForItem:, if it is 
implemented, to autosave an archive of the expanded or collapsed item. After 
you quit and relaunch the application, AppKit calls 
-outlineView:itemForPersistentObject: to read the archive and expand or 
collapse rows just as you left them when you quit.

Here's the bug: When you expand or collapse an empty outline row, AppKit does 
not call -outineView:persistentObjectForItem:. As a result, after quit and 
relaunch the row is always in the collapsed state (the triangle points sideways 
instead of down), even if it was left in the expanded state at the previous 
quit. I suspect that Apple considers this to be correct behavior, since the 
NSOutlineViewItemDidExpandeNotification and 
NSOutlineViewItemDidCollapseNotification are correctly posted even when an 
empty row is expanded or collapsed. It therefore looks like Apple coded the 
autosave behavior deliberately.

You might argue that this is proper behavior because it doesn't mean much to 
call an empty row expanded. But the Finder, for one example, honors the 
expanded state of empty rows across relaunches, and I find it useful so that I 
can monitor at a glance whether files have been added to particular folders 
behind my back (in my Public Folder's Drop Box, for example). I like to leave 
some empty folders expanded across relaunches.

But the bug really bites when you expand an empty row and then add a child row 
to it. AppKit did not call -outineView:persistentObjectForItem: when you 
expanded the empty row, and it does not call it when you add a new child row, 
either. As a result, after quit and relaunch the row is collapsed, even though 
when you quit you left it expanded and non-empty.

I can fix this with a hack. When I add a child row, my application checks 
whether the newly added row has any siblings and, if not, collapses and 
re-expands the row programmatically. Because the parent row now has a child, 
AppKit calls -outineView:persistentObjectForItem: and all is well. On my fast 
Mac Pro Late-2013, I don't see a flicker. I haven't tried it on a slower 
machine yet.

A more dubious fix is to archive the expanded row in user defaults myself. I 
took a stab at coding that, and it wasn't hard, but I didn't carry it all the 
way through because I realized that I can't be sure I am capturing all the 
wrinkles of Apple's implementation. I consider this fix inappropriate for a 
released product because it depends on the implementation details of AppKit's 
autosaveExpandedItems mechanism, which is mostly hidden behind the scenes.

Before I report this to Apple, does anybody have any other thoughts or 
workarounds?

-- 

Bill Cheeseman - b...@cheeseman.name

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Getting bound object

2014-07-13 Thread Daniel Santos
Hello,

I have a collection view in which I have subclassed the collection view item.
In the awake from nib method I want to get the represented object but it is 
returning nil

How can I get the bound object ?


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Getting bound object

2014-07-13 Thread Kyle Sluder
On Jul 13, 2014, at 11:24 AM, Daniel Santos daniel.d...@gmail.com wrote:
 
 Hello,
 
 I have a collection view in which I have subclassed the collection view item.
 In the awake from nib method I want to get the represented object but it is 
 returning nil
 
 How can I get the bound object ?

You have to wait until after -awakeFromNib. Bindings aren't hooked up and 
propagated until the entire object graph has been awoken.

One option is to override -loadView to call super and then do your magic.

--Kyle Sluder
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: KVC, binding multiple properties, top level object

2014-07-13 Thread Trygve Inda
 
 On 12 Jul 2014, at 10:05 pm, Trygve Inda cocoa...@xericdesign.com wrote:
 
 ---someProperty (Custom NSObject)
 --propertyA (NSNumber)
 --propertyB (NSNumber)
 --propertyC (NSNumber)
 
 Properties A, B and C use a binding to connect them to a user interface item
 with something like:
 
 Bind to MyObject with key path someProperty.propertyA
 
 
 Just as a matter of interest, why do you decalre these subproperties as
 NSNumber types? Is there a reason you can't just make them the native scalar
 types they wrap (e.g. integer, float)? KVC/KVO automatically wraps scalar
 values with NSNumber or NSValue to pass them around through bindings, so you
 don't have to concern yourself with it. Usually, code is clearer if properties
 are declared as the native types. If you make them NSNumbers, how will you
 detect or prevent a value of the wrong type being passed?
 
 --Graham
 
 
 

Is NSInteger treated the same way? This page does not mention it:

https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/KeyVa
lueCoding/Articles/DataTypes.html

NSNumber just seem a bit more flexible since they can be added to
dictionaries (such as in the userInfo of a Notification).

T.



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Getting bound object

2014-07-13 Thread Daniel Luis dos Santos

On 13 Jul 2014, at 21:10, Kyle Sluder k...@ksluder.com wrote:

 On Jul 13, 2014, at 11:24 AM, Daniel Santos daniel.d...@gmail.com wrote:
 
 Hello,
 
 I have a collection view in which I have subclassed the collection view item.
 In the awake from nib method I want to get the represented object but it is 
 returning nil
 
 How can I get the bound object ?
 
 You have to wait until after -awakeFromNib. Bindings aren't hooked up and 
 propagated until the entire object graph has been awoken.
 
 One option is to override -loadView to call super and then do your magic.
 
 --Kyle Sluder

I just tried that. But [self representedObject] returns nil when called in the 
subclassed NSCollectionViewItem. Any idea why ?
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Getting bound object

2014-07-13 Thread Ken Thomases
On Jul 13, 2014, at 5:24 PM, Daniel Luis dos Santos daniel.d...@gmail.com 
wrote:

 On 13 Jul 2014, at 21:10, Kyle Sluder k...@ksluder.com wrote:
 
 On Jul 13, 2014, at 11:24 AM, Daniel Santos daniel.d...@gmail.com wrote:
 
 Hello,
 
 I have a collection view in which I have subclassed the collection view 
 item.
 In the awake from nib method I want to get the represented object but it is 
 returning nil
 
 How can I get the bound object ?
 
 You have to wait until after -awakeFromNib. Bindings aren't hooked up and 
 propagated until the entire object graph has been awoken.
 
 One option is to override -loadView to call super and then do your magic.
 
 I just tried that. But [self representedObject] returns nil when called in 
 the subclassed NSCollectionViewItem. Any idea why ?

The collection view creates an item.  Then it assigns that item the object it 
will represent.  It can't do that until after the item has been created.  That 
means after -awakeFromNib and after -loadView.  The item's representedObject is 
not an inherent value that it can be expected to have at creation/load time.

I don't know what you're trying to achieve.  It may make sense to override the 
setter (-setRepresentedObject:) to have an opportunity to do something when the 
represented object is assigned to the item.  Of course, call through to super.

Regards,
Ken


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: KVC, binding multiple properties, top level object

2014-07-13 Thread Graham Cox

On 14 Jul 2014, at 7:29 am, Trygve Inda cocoa...@xericdesign.com wrote:

 Is NSInteger treated the same way? This page does not mention it:

NSInteger is a typedef for 'long', which size depends on the platform (32/64 
bit), so valueForKey: will wrap it as a NSNumber using type 'long'. That's safe 
across archives that are used in both 32 and 64 bit ISAs, though with loss of 
precision if a 64-bit archive was dearchived on 32-bit (and this might become a 
permanent loss if the data is reachived and then opened in 64-bit). Scalar 
properties that explicitly declare 'long long' would be always 64-bit. I doubt 
if this is an issue in practice.

 NSNumber just seem a bit more flexible since they can be added to
 dictionaries (such as in the userInfo of a Notification).

Since - valueForKey: always returns an object, they too can be added to 
dictionaries.

I guess it's as broad as it's long, though my view would be that it's generally 
a better idea to take advantage of a framework feature where it exists (in this 
case, the auto wrapping and unwrapping of scalars) than roll your own solution 
which won't be as thoroughly debugged, take into account any corner cases, and 
so on. In this case it's also much less type safe. The auto-wrapping generally 
preserves type, or at least preserves precision (NSNumbers don't actually 
guarantee that a value's type won't change, e.g. a float that can be expressed 
as an integer will probably end up as an integer, but the point is there's no 
loss of precision).

--Graham



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: KVC, binding multiple properties, top level object

2014-07-13 Thread Trygve Inda
 
 On 14 Jul 2014, at 7:29 am, Trygve Inda cocoa...@xericdesign.com wrote:
 
 Is NSInteger treated the same way? This page does not mention it:
 
 NSInteger is a typedef for 'long', which size depends on the platform (32/64
 bit), so valueForKey: will wrap it as a NSNumber using type 'long'. That's
 safe across archives that are used in both 32 and 64 bit ISAs, though with
 loss of precision if a 64-bit archive was dearchived on 32-bit (and this might
 become a permanent loss if the data is reachived and then opened in 64-bit).
 Scalar properties that explicitly declare 'long long' would be always 64-bit.
 I doubt if this is an issue in practice.

So what is the purpose of valueForInteger ?



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: KVC, binding multiple properties, top level object

2014-07-13 Thread Trygve Inda
 
 On 14 Jul 2014, at 7:29 am, Trygve Inda cocoa...@xericdesign.com wrote:
 
 Is NSInteger treated the same way? This page does not mention it:
 
 NSInteger is a typedef for 'long', which size depends on the platform (32/64
 bit), so valueForKey: will wrap it as a NSNumber using type 'long'. That's
 safe across archives that are used in both 32 and 64 bit ISAs, though with
 loss of precision if a 64-bit archive was dearchived on 32-bit (and this might
 become a permanent loss if the data is reachived and then opened in 64-bit).
 Scalar properties that explicitly declare 'long long' would be always 64-bit.
 I doubt if this is an issue in practice.

So what is the purpose of the NSInteger access within NSNumber eg
integerValue and setIntegerValue ?


Please disregard my last message - it got sent before I could stop it.  :-)



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com