Challenge 1 has me stumped!


#1

Anyone have a hint on challenge 1? I thought it would be as easy, but it’s not turning out that way. :frowning:


#2

The solution for this challenge involves the Sort Key field on the table column’s Attributes Inspector.


#3

I get that part, but I’m falling down on how to implement it. I thought it would just be:

But it’s not. I got more explicit and tried:

But that didn’t do it either.

Another hint perhaps?


#4

personName.length is perfectly right. But you should not forget to set the Selector method back to compare: ! Check if you might have left the caseInsensitiveCompare: method in it!


#5

I thought I had done that as well, but will double check. Glad to see I was on the right path at least!

Thanks.


#6

I went back and tried it again and it’s working fine with the sorting now. Not sure what I had messed up before, but I suspect a typo was causing some havoc.

Thanks!


#7

When I first saw this Challenge 1 (sort by name length), I thought it would be trivial. However, after many attempts, I have been unable to make it work. And since it all happens in internal “Controller” code it makes it extremely difficult to debug.

I have done what other have described here: in Interface Editor, select name column, and in the Attributes Inspector for “Table Column” (“Name”), set “Sort Key” to ‘personName.length’ (no quotes) and set Selector to ‘compare:’.

When compiled and run, this does not sort the “Name” column correctly. It appears to “sort” randomly – but it doesn’t throw an exception (nil call I assume).

I have also tried, in the Binding Inspector, under the Value pane (bound to the Array Controller) both checking and unchecking the “Creates Sort Descriptor” field. The incorrect sort behavior does not change, no matter how this checkbox is set.

To a certain extent, my inability to get the column to sort for the key-path “personName.length” seems to make sense. I’m guessing that XCode is generating a call to [NSSortDescriptor sortDescriptorWithKey:key:ascending:selector:] under the covers. Documentation for this call says that the selector(SEL) must be a method implemented by the value object specified by the key:. However, NSString.length returns a NSUInteger, which is just, I believe, a typedef defining no methods (compare: or otherwise). So I actually don’t understand how others have been able to get this code to work using “compare:” as the selector for NSUInteger values.

FWIW, I’m running Xcode 4.4.1 under OSX v10.7.4

Any tips, pointers, or insights would be greatly appreciated. I hate to just chalk this one up to XCode weirdness and move on to the other coding examples.


#8

From your description everything sounds right, so I regret that I’m not sure why it’s not working.

I did want to address the above, however. The reason that personName.length [should] work is that NSSortDescriptor uses key value coding. We can imagine that it does the comparison in this fashion:

Because it’s using KVC, the value returned is an instance of NSNumber, which implements compare:.


#9

I had to have several goes at this but remember you have to compare lengths and don’t forget the semi-colon.


#10

I’ve been trying this for about an hour and still get a crash:

Exception Name: NSInternalInconsistencyException
Description: Error setting value for key path sortDescriptors of object <NSArrayController: 0x10041e030>[object class: Person, number of selected objects: 1] (from bound object <NSTableView: 0x10040f220>): [<Person 0x100261b30> valueForUndefinedKey:]: this class is not key value coding-compliant for the key sortDescriptorPrototype.
User Info: (null)

0 CoreFoundation 0x00007fff907f98ce __exceptionPreprocess + 174
1 libobjc.A.dylib 0x00007fff8ce4cf51 objc_exception_throw + 43
2 CoreFoundation 0x00007fff907f9728 +[NSException raise:format:arguments:] + 104
3 AppKit 0x00007fff91429d5a -[NSBinder _setValue:forKeyPath:ofObject:mode:validateImmediately:raisesForNotApplicableKeys:error:] + 837
4 AppKit 0x00007fff914299bc -[NSBinder setValue:forBinding:error:] + 245
5 AppKit 0x00007fff9168a491 -[NSTableBinder tableView:didChangeToSortDescriptors:] + 146
6 AppKit 0x00007fff9168a3e8 -[_NSBindingAdaptor tableView:didChangeToSortDescriptors:] + 144
7 AppKit 0x00007fff915efae6 -[NSTableView setSortDescriptors:] + 210
8 AppKit 0x00007fff919d04d5 -[NSTableView _changeSortDescriptorsForClickOnColumn:] + 578
9 AppKit 0x00007fff919b4cc2 -[NSTableHeaderView _trackAndModifySelectionWithEvent:onColumn:stopOnReorderGesture:] + 1081
10 AppKit 0x00007fff919b7d70 -[NSTableHeaderView mouseDown:] + 419
11 AppKit 0x00007fff9158e918 -[NSWindow sendEvent:] + 11303
12 AppKit 0x00007fff91588f48 -[NSApplication sendEvent:] + 2021
13 AppKit 0x00007fff914aa599 -[NSApplication run] + 646
14 AppKit 0x00007fff91454563 NSApplicationMain + 940
15 RaiseMan 0x00000001000017c2 main + 34
16 libdyld.dylib 0x00007fff8c21260d start + 1

Update
This appears to be an issue with OS 10.9 and Xcode 5. The example code from this site throws the same exception.


#11

[quote=“JohnnyMac”]When I first saw this Challenge 1 (sort by name length), I thought it would be trivial. However, after many attempts, I have been unable to make it work. And since it all happens in internal “Controller” code it makes it extremely difficult to debug.

I have done what other have described here: in Interface Editor, select name column, and in the Attributes Inspector for “Table Column” (“Name”), set “Sort Key” to ‘personName.length’ (no quotes) and set Selector to ‘compare:’.

When compiled and run, this does not sort the “Name” column correctly. It appears to “sort” randomly – but it doesn’t throw an exception (nil call I assume).

I have also tried, in the Binding Inspector, under the Value pane (bound to the Array Controller) both checking and unchecking the “Creates Sort Descriptor” field. The incorrect sort behavior does not change, no matter how this checkbox is set.

To a certain extent, my inability to get the column to sort for the key-path “personName.length” seems to make sense. I’m guessing that XCode is generating a call to [NSSortDescriptor sortDescriptorWithKey:key:ascending:selector:] under the covers. Documentation for this call says that the selector(SEL) must be a method implemented by the value object specified by the key:. However, NSString.length returns a NSUInteger, which is just, I believe, a typedef defining no methods (compare: or otherwise). So I actually don’t understand how others have been able to get this code to work using “compare:” as the selector for NSUInteger values.

FWIW, I’m running Xcode 4.4.1 under OSX v10.7.4

Any tips, pointers, or insights would be greatly appreciated. I hate to just chalk this one up to XCode weirdness and move on to the other coding examples.[/quote]

Hello
I had this EXACTLY same broplem. I spent two nights with this broplem and I was ready jump from the roof of my building. Then I accidentally fixed it by thinking downwards the key-value path like this:
employees.personName.length

And it works ! for me anyway. Hope this helps somebody (who is on the roof right now =)


#12

I thought we don’t use dot notation in this book, very confusing. Is there another way of doing it without dot notation?


#13

I has the same Problems described above. The solution for me was, that I clicked into the second collumn of the table view and back to the first.
After I have clean the product and build again, the program runs fine!