3

What did I do here? Can method parameters be typeless?

In a recent project which works fine, the App is in the store already - no issues so far, I did the following in a .h file:

@property (strong, nonatomic) NSManagedObject          *myPerson;
- (HKPersonPicker*) initWithPerson:person;
- (HKPersonPicker*) initWithPerson:person delegate:(id <HKPersonPickerDelegate>)delegate;

I meant to do it this way but did not:

- (HKPersonPicker*) initWithPerson:(NSManagedObject*)person;
- (HKPersonPicker*) initWithPerson:(NSManagedObject*)person delegate:(id <HKPersonPickerDelegate>)delegate;

The corresponding part of the .m file:

- (HKPersonPicker*) initWithPerson:person
{
    self = [super init];
    if(self){
        self.myPerson = person;
    }
    return (self);
}

- (HKPersonPicker*) initWithPerson:person delegate:(id <HKPersonPickerDelegate>)delegate
{
    self = [self initWithPerson:person];
    if(self){
        self.delegate = delegate;
    }
    return (self);
}

As you can see I did not do anything special with this person object, just assigned it to the property myPerson. As I did not call any of the object's methods or accessed its data, the compiler did not need to know anything about that object. But what is it from the compiler's point of ivew? Type id? Just something? Is there any default type?

As you see, I do not have any real problem. I am just curious. Hope this question does not break any SO rule.

Hermann Klecker
  • 14,039
  • 5
  • 48
  • 71

3 Answers3

3

With C the default type is int, but with Objective-C it's id.

trojanfoe
  • 120,358
  • 21
  • 212
  • 242
  • So that's what it is. I did rely on some default without knowing it and out of pure luck it was ok. Not exactly my usual style but good to know. – Hermann Klecker Mar 06 '13 at 21:31
  • Yes exactly that; I think if you accessed any of the methods of the class, within that method, the compiler would have moaned about it and it would have been more obvious. – trojanfoe Mar 06 '13 at 21:37
  • Exactly. Now that you say that ... I should have tried accessing any method and the compiler would have told me the acutal class that it was assuming: "No visible interface of id implements ... " :) – Hermann Klecker Mar 06 '13 at 22:01
2

Missing type declarations in methods default to id. IIRC, you can see a fair number of methods without return types in Apple's runtime library.

jscs
  • 63,694
  • 13
  • 151
  • 195
2

There is no definitive problem with what you are doing, but its not really kosher at the same time. You should still have a type declaration for the sake of clarity, and maintaining good and consistent Cocoa-like code styling.

So it should really be like:

- (GSPersonPicker*) initWithPerson:(id)person;

And you should really change the property declaration:

@property (strong, nonatomic) id *myPerson;

If that is not changed, then your code is confusing. You KNOW the type that will be coming in. So let the compiler help you with meaningful warnings/errors by using types. You should also probably be using the type 'HKPerson' or whatever you have named your entity, so the compiler doesn't think its ok for you to pass in an 'HKPlace' (they will both be of type 'id' and 'NSManagedObject', which does you no favors)

More importantly, you should not be using the dynamic type (id) unless you have a reason. The compiler is there to help you. Errors and warnings are your friend, they tell you that you messed up, not the computer. When you use 'id', the compiler just goes, Oh, anything can go in here!!! And it will not detect an error where you sent that method a type that will break everything.

Now lets say that you are going to use polymorphism. IE, Lets declare a generic protocol for multiple classes to adhere to, which defines our person:

@protocol GSPerson
-(NSUInteger)age;
@end

So now lets define a couple classes, and have them subscribe to the protocol (the GSPerson thats between carrots markdown is killing me atm lol):

#import "GSPerson.h"
@interface GSSpecialPerson <GSPerson>
// code
@end

#import "GSPerson.h"
@interface GSWeirdPerson <GSPerson>
// code
@end

Then lets redefine our method signature to adhere to the protocol:

- (GSPersonPicker*) initWithPerson:(id<GSPerson>)person;

And our property declaration:

@property (strong, nonatomic) id <GSPerson> *myPerson;

Now the compiler knows that anything i pass into that method should conform to the GSPerson protocol I defined above (ie they need a method that returns the persons age). If i try to pass anything else in, it will throw compiler warnings, WHICH IS GOOD.

Even better, it will throw warnings on your polymorphic classes if they are missing their required methods.

G. Shearer
  • 2,175
  • 17
  • 19
  • 1
    Thanks for the extensive answer. An upvote for that. I fully agree. As a matter of fact, I was copying this code from that project and re-used it in a new one. By doing so I noticed this flare. I will not change it to id but to NSManagedObject* because in the new project I don't generate the model classes out of the entities but use KVC. Anyway, thanks. – Hermann Klecker Mar 06 '13 at 21:30
  • Cool, always nice to learn something new (in this case your use of KVC and therefore a reason to use the NSManagedObject type in a _person-specific_ method) – G. Shearer Mar 06 '13 at 21:40
  • I am just trying how far I can get with the KVC. My current App is just a small one with local storage only. With this app I do not have any gains from KVC but it does not really generate additional effort etc. It just does not matter so far. The next App will have to replicate locally what comes in using a REST web service. And there I might gain a lot when combining the KVC of RestKit objects with identical keys in core data. Will see ... – Hermann Klecker Mar 06 '13 at 22:05
  • You might want to be cautious with RESTKit, see my answer here: http://stackoverflow.com/questions/14854641/restkit-and-saving-to-coredata-as-nsmanagedobject/15075931#15075931 I would definitely recommend just rolling your own solution, especially if you do not have control over the design of your REST api. – G. Shearer Mar 06 '13 at 22:07
  • Thanks, I'll have a look. However, the API is 'mine'. – Hermann Klecker Mar 06 '13 at 22:39