2

In some cases, self = [self init] is called in init method instead of [super init] in the code I reviewed. Do you think that kind of syntax is acceptable or it is the sign that logic arranged in some ways wrong (the wrong patterns) if it is lead to the use of [self init]?

For instance (it could be another example),

- (instancetype)init {
  self = [super init];
  //my code block
  return self;
}

- (instancetype)initWithDelegate:(id<MyDelegate>)delegate {
  self = [self init]; //self = [super init] is not called since "my code block" needs to be implemented
  if (self) {
    self.delegate = delegate;
  }
  return self;
}

Can it be the case when self = [self init] is ok? If yes, do you have any example?

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Darius Miliauskas
  • 3,391
  • 4
  • 35
  • 53
  • Reviewing, and especially because of how Swift works... That depends on whether the `initWithDelegate` is a _convenience_ initializer with `init` being the **designated** initializer. Which, if that is the case, the _convenience_ initializer `initWithDelegate` should call the **designated** `[self init]` 「using `self` and not `super` or the required initializers will not be invoked properly in the inst-type-chain」. – smallscript Feb 16 '23 at 06:21

2 Answers2

2

The above code is backwards. The designated initializer is initWithDelegate: (since it's the one that initializes all properties). So init should call initWithDelegate::

- (instancetype)init {
  self = [self initWithDelegate:nil];
  return self;
}

- (instancetype)initWithDelegate:(id<MyDelegate>)delegate {
  self = [super init];
  if (self) {
    //my code block
    self.delegate = delegate;
  }
  return self;
}

See iOS Designated Initializers : Using NS_DESIGNATED_INITIALIZER for how to properly annotate your designated initializer in the header.

And of course everyone should listen to James Dempsey sing about how this mistake impacted him.

To the basic question of whether self = [self init] is ever correct, it would be surprising in most app-level code (i.e. outside of libraries). Designated initializers are typically the initializer that takes the most parameters, so init is the least likely candidate when there are multiple initializers. On the other hand, self = [self init...] is very common and correct.

However, in code that had existing subclasses that you don't control (if you ship a library for example), it's possible that it began life with only init, and other initializers were added later. In that case, it would often be wise to keep init designated (so that existing subclasses wouldn't have to be rewritten), and in that case, sure, self = [self init] could be correct.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • That depends on whether the `initWithDelegate` is a _convenience_ initializer with `init` being the **designated** initializer. Which, if that is the case, the _convenience_ initializer `initWithDelegate` should call the **designated** `[self init]` 「using `self` and not `super` or the required initializers will not be invoked properly in the inst-type-chain」. – smallscript Feb 16 '23 at 06:16
0

To understand if [self init] ok, I think we should first know about alloc - init.

  • Alloc is to create the memory allocation for the object of class. So when we call init after alloc, the object has been created for "self"
  • In init method, because self has already been created , it make sense to call [self init]
  • Interesting note : It is ok theoretically to just assign myObject = [MyObjectClass alloc]. However as Class normally has variables assigned in init method, this is not a good coding style.
Mihozil
  • 1
  • 2