No visible @interface

In XCode 9.2 I'm getting an ARC Symantic Issue error when I go to build an aging MacOS app I developed a number of years ago for a client. This has always built fine in the past.


if ([[[self myTreeController] arrangedObjects] count] == 0) {...}


The error is: No visible @interface for 'NSTreeNode' declares the selector 'count'


So it seems XCode is thinking it's getting a NSTreeNode but shouldn't the arrangedObjects of NSTreeController be an NSArray which I can call count on? The property myTreeController is declared in the header file as


@property(nonatomic,weak) IBOutlet NSTreeController *myTreeController;


Thanks!

Answered by QuinceyMorris in 283675022

This is likely the result of the wave of type annotations added to the SDKs in the wake of the Swift language.


I can't find the old declaration of "arrangedObjects" but presumably it was something that allowed you to invoke "count" without a compile time error. (This would be true, for example, if "arrangedObjects" was declared as an "id".)


In the new declaration "arrangedObjects" is stated to be of type "NSTreeNode", which means the arranged objects are actually its children. So try getting the count as the "count" property of the "childNodes" array of the "arrangedObjects" object.


Note that "arrangedObjects" is, and always been, a proxy object, so it can respond to whatever messages it chooses, including "count" directly, regardless of what the @interface says. You could also try this, which should have the same effect your original code, but without the compile-time type check:


if ([(id) [[self myTreeController] arrangedObjects] count] == 0) {...}


but respecting the declared type is probably the better approach.

Accepted Answer

This is likely the result of the wave of type annotations added to the SDKs in the wake of the Swift language.


I can't find the old declaration of "arrangedObjects" but presumably it was something that allowed you to invoke "count" without a compile time error. (This would be true, for example, if "arrangedObjects" was declared as an "id".)


In the new declaration "arrangedObjects" is stated to be of type "NSTreeNode", which means the arranged objects are actually its children. So try getting the count as the "count" property of the "childNodes" array of the "arrangedObjects" object.


Note that "arrangedObjects" is, and always been, a proxy object, so it can respond to whatever messages it chooses, including "count" directly, regardless of what the @interface says. You could also try this, which should have the same effect your original code, but without the compile-time type check:


if ([(id) [[self myTreeController] arrangedObjects] count] == 0) {...}


but respecting the declared type is probably the better approach.

Thanks for not only pointing me in the right direction but also the thoughtful explenation as to why it no longer works as before. As you suggested...


[[[[self myTreeController] arrangedObjects] childNodes] count]


... did the trick.

No visible @interface
 
 
Q