Skip to content

Instantly share code, notes, and snippets.

@alaborie
Created July 12, 2012 21:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alaborie/3100972 to your computer and use it in GitHub Desktop.
Save alaborie/3100972 to your computer and use it in GitHub Desktop.
Clang 3.1: interesting warning...
@protocol MyProtocol <NSObject>
@end
int main(int argc, char *argv[])
{
@autoreleasepool
{
id <MyProtocol> foo = nil;
__unused id value = [foo valueForKey:@"bar"];
return EXIT_SUCCESS;
}
}
@alaborie
Copy link
Author

When I compile, I got this warning:

/Users/alex/Desktop/Test/Test/main.m:10:29: warning: instance method '-valueForKey:' not found (return type defaults to 'id')
        __unused id value = [foo valueForKey:@"bar"];
                                      ^~~~~~~~~~~~~~~~~~~~~~~~
1 warning generated.

I don't understand why Clang generates a warning for the previous code? The variable foo is an instance of NSObject. The method valueForKey: is defined in an information protocol of NSObject (NSKeyValueCoding). So why Clang gives me this warning?

There is two ways to remove the warning:

  • Cast foo into an id ([(id)foo valueForKey:@"bar"]).
  • Remove the protocol from the definition (id foo = nil;). It's not an acceptable solution because my object does not conform the protocol anymore.

Does someone knows why this generate a warning?

PS1: The code itself does not have any sense. I wrote the shortest code that generates this warning :).
PS2: I used Xcode 4.3.3 + Clang 3.1.

@gotosleep
Copy link

It's because MyProtocol does not declare "valueForKey:"

In this line:

@protocol MyProtocol <NSObject>

You are extending the NSObject protocol, not the NSObject class. The NSObject protocol does not declare "valueForKey:"

One way to fix this is:

@protocol MyProtocol <NSObject>

- (id)valueForKey:(NSString *)key;

@end

@alaborie
Copy link
Author

The protocol that I have wrote does not declare valueForKey:, but this method should still be accessible through the category NSKeyValueCoding on NSObject. The following code does not generate warning:

id foo = nil;
id value = [foo valueForKey:@"bar"];

This one does:

id < MyProtocol > foo = nil;
id value = [foo valueForKey:@"bar"];

It is as if the compiler does not consider the type 'id < MyProtocol >' of type 'id'. Which is really odd. And so if you force the cast of foo into an id, the code compile without any warning.

id < MyProtocol > foo = nil;
id value = [(id)foo valueForKey:@"bar"];

@alaborie
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment