1

In the @interface, I have this declaration:

@interface myClass {
   NSDictionary * myData;
}

@property (nonatomic, assign) NSDictionary * data;
+ (id) initWithData:(NSDictionary *)data;

@end

In the @implementation, I have this code:

@implementation

@synthesize data;

+ (id) initWithData:(NSDictionary *)freshData {
    self = [super init];
    if (self) {
        self->data = freshData;
    }
    return self;
}

@end

But I got error Incomplete definition of type 'struct objc_class on self->data.

If I change it into self.data, I got error Member reference type 'struct objc_class *' is a pointer; did you mean to use '->'?

If I remove the self, I got error `Instance variable 'data' accessed in class method.'

But if I change the method type from + (class method) to - (instance method), I cannot access the init.

And I cannot fix this error by change the assignment from data to myData either.

How should I make a constructor?

The link that I have learned from (but not helping) are:

Community
  • 1
  • 1
Chen Li Yong
  • 5,459
  • 8
  • 58
  • 124

3 Answers3

4

You can do it like this also

+ (id) initWithData:(NSDictionary *)freshData {
    return [[self alloc]initWithData:freshData];
}
- (instancetype) initWithData:(NSDictionary *)freshData {

    NSParameterAssert(freshData != nil);

    self = [super init];

    if (self) {
        self.data = freshData;
    }

    return self;
}
Rajat
  • 10,977
  • 3
  • 38
  • 55
  • If I only implement `- (instancetype) initWithData:(NSDictionary *)freshData` without `+ (id) initWithData:(NSDictionary *)freshData`, what's the downside? – Chen Li Yong Nov 25 '16 at 02:10
  • Well you can do that also, if there is not any issue with creating the object ofthat class, as with instance method you need to create the object of that class to use that method and with class method you can call that method with Class. – Rajat Nov 25 '16 at 02:13
  • Check this also for class method vs instance method - http://stackoverflow.com/questions/1053592/what-is-the-difference-between-class-and-instance-methods – Rajat Nov 25 '16 at 02:16
2

In general, I would not expect an init* method to be a class method. Generally you have a class method with a name like default*, shared*, or *withDictionary:. So for a class named myClass, I'd expect to see this:

+ (myClass*)myClassWithDictionary:(NSDictionary*)dict
{
    return [[myClass alloc] initWithDictionary:dict];
}

This can be important when the static analyzer analyses your code, for example. Naming is significant in Objective-C and hints the compiler (and analyzer) as to what the code's intent is.

user1118321
  • 25,567
  • 4
  • 55
  • 86
  • You mean like `[UIColor colorWithCGColor:]` ? – Chen Li Yong Nov 25 '16 at 02:25
  • Yes, that's what I meant. – user1118321 Nov 25 '16 at 02:26
  • Okay, I think I know what's wrong that I can't access instance init method constructor... I forgot to do `alloc` first before `init`. That's why I only can access the `init` method if I changed the `init` into class constructor, because I immediately wrote `[MyClass initWithData:]`. I'm so used to Swift simplicity that when I have to go back to Objective C, I kinda forget about the drill... Then your answer reminds me why the `init` must be instance method, not class method. Thanks! – Chen Li Yong Nov 25 '16 at 02:31
1

Do not using public init method (+)

+ (id) initWithData:(NSDictionary *)data;

Change to

- (instancetype) initWithData:(NSDictionary *)data;

And I highly recommend you to use instancetype instead of id (reference )

Community
  • 1
  • 1
nynohu
  • 1,628
  • 12
  • 12