The designated initializer of initialization and convenience in objective-c and how to create and bind them correctly

I am trying to figure out which one should be assigned an initializer and which one is a convenience initializer. I read apple docs on this topic, but I'm still not sure. Should the designated initializer have all the values ​​that are required for the class? For example, It was the first designated initializer that I created.

-(id)initWithCardCount:(NSUInteger)cardCount usingDeck:(Deck *)deck { self = [super init]; if (self) { for(int i = 0; i<=cardCount;i++){ Card *card = [deck drawRandomCard]; if (!card) { self = nil; break; }else{ self.cards[i] = card; } } } return self; } 

Now add the cardMatchMode property to this class and want to set it in the initializer. To make the class backward compatible and understand the initializers, I save the one I have and create another initializer.

 -(id)initwithCardCount:(NSUInteger)cardCount usingDeck:(Deck *)deck cardMatchMode:(NSUInteger)matchMode { _cardMatchMode = matchMode; return [self initWithCardCount:cardCount usingDeck:deck];; } 

Based on apple docs, the convenience initializer should return a value for the designated initializer, but the question is, can I set an additional property in this class in the convenience initializer? May I say that self.cardMatchMode = matchMode; Or am I not yet fully initialized?
It works, but I just wanted to understand if this is the right code, and I can access the cardMatchMode property in the convenience of init or I will need to do -(id)initwithCardCount:(NSUInteger)cardCount usingDeck:(Deck *)deck cardMatchMode:(NSUInteger)matchMode

as a designated initializer, and the other for the convenience of initializing and finalizing the code? Thanks!

///// Update

I was getting an error in

 -(id)initwithCardCount:(NSUInteger)cardCount usingDeck:(Deck *)deck cardMatchMode:(NSUInteger)matchMode 

When I tried to do self = [self initWithCardCount:(NSUInteger)cardCount usingDeck:(Deck*)deck; the error says that you cannot assign yourself outside the init family. I realized what the problem is. The init method was lowercase w, and it had to be capital, so now it works. This is the code I have for the convenience initializer.

 -(id)initWithCardCount:(NSUInteger)cardCount usingDeck:(Deck *)deck cardMatchMode:(NSUInteger)matchMode { self = [self initWithCardCount:cardCount usingDeck:deck]; if (self){ _cardMatchMode = matchMode; } return self; } 

Now that makes sense. I called the assigned init, which calls super, and then I set the variable cardMatchMode .

As far as I understand, there are many objects with a convenience initializer with additional parameters, and it will simply call the assigned init. If you look at NSString and it has different initializers with different parameters. This is probably an init call, which is the designated initializer. Is it correct?

+6
source share
2 answers

According to Apple Documentation, designated initiator

usually an init ... method that has most of the parameters and does most of the initialization.

So, in your case it will be - (id)initwithCardCount:(NSUInteger)cardCount usingDeck:(Deck *)deck cardMatchMode:(NSUInteger)matchMode . All other initializers will have fewer arguments, filling in the missing parameters in the designated initializer with default values ​​or otherwise.

Thus, each convenience initializer invokes a designated initializer instead of the superclass initializer.

The initializer parameter, assigned for convenience, will look like this:

 /** Convenience initializers */ - (id)init { self = [self initwithCardCount:kDefaultCardCount usingDeck:[Deck defaultDeck] cardMatchMode:kCardMatchModeDefault]; return self; } - (id)initWithCardCount:(NSUInteger)cardCount usingDeck:(Deck *)deck { self = [self initwithCardCount:cardCount usingDeck:deck cardMatchMode:kCardMatchModeDefault]; if (self) { } return self; } /** Designated initializer */ - (id)initwithCardCount:(NSUInteger)cardCount usingDeck:(Deck *)deck cardMatchMode:(NSUInteger)matchMode { self = [super init]; if (self) { for (int i = 0; i <= cardCount; i++) { Card *card = [deck drawRandomCard]; if (!card) { self = nil; break; } else { self.cards[i] = card; } } // Set card match mode here: _cardMatchMode = matchMode; } return self; } 
+6
source

A designated initializer is one that calls the designated initializer of its superclass of the class, so it is the only initializer that calls the method on the super object. No other initializer in the class should do this; these secondary initializers must invoke the designated initializer using self . Typically, a designated initializer has all the parameters necessary to create a useful class object.

In short, the designated initializer is the only one that calls the initializer on super , and all other initializers in the class call the assigned initializer (using self ).

+15
source

Source: https://habr.com/ru/post/951252/


All Articles