Ответ 1
Ответ можно найти в Objective-C Особенности документации Clang 3.3:
Связанные типы результатов
В соответствии с Cocoa соглашениями, Objective-C методы с определенными именами ( "init", "alloc" и т.д.) всегда возвращают объекты, являющиеся экземпляром тип принимающих классов. Говорят, что такие методы имеют result type ", что означает, что сообщение, отправленное на один из этих методов, будет имеют тот же статический тип, что и экземпляр класса приемника.
Поэтому в
NSMutableString *s2 = [[NSString alloc] init];
тип правой стороны на самом деле NSString *
, а не id
, а присвоение этому значению NSMutableString *
дает предупреждение "Несовместимые типы указателей".
С другой стороны, метод string
в
NSMutableString *s1 = [NSString string];
не имеет "связанного типа результата", поэтому он просто возвращает id
, который может быть назначен NSMutableString *
.
Отключение alloc/init в отдельные инструкции подавляет предупреждение только в том случае, если вы используете id
как промежуточный тип. С помощью NSString
или NSMutableString
вы все равно получаете предупреждения:
NSString *tmp4 = [NSString alloc];
NSMutableString *s4 = [tmp4 init]; // <-- Warning here
NSMutableString *tmp5 = [NSString alloc]; // <-- Warning here
NSMutableString *s5 = [tmp5 init];
Согласно документации, метод имеет "связанный тип результата", если его тип возврата совместим с типом его класса, и если:
- первое слово - "alloc" или "new", а метод - метод класса, или
- первым словом является "autorelease", "init", "keep" или "self", а метод - метод экземпляра.