Меня беспокоит странное поведение, проиллюстрированное следующим примером:
NSMutableArray *a1 = [[NSMutableArray alloc] init]; // fine
NSMutableArray *a2 = [NSMutableArray array]; // fine, too
// compiler reports incompatible pointer types; good:
NSMutableArray *a3 = [[NSArray alloc] init];
// compiler says nothing and is happy to assign this!
NSMutableArray *a4 = [NSArray array];
Оба метода init и array обоих классов NSArray и NSMutableArray возвращают id. Однако поведение, когда я называю эти методы, просто не то же самое, и clang позволяет мне с радостью назначить пустую переменную NSArray переменной NSMutableArray!
Оказывается, что clang автоматически изменяет тип возвращаемого значения некоторых методов, включая семейство init, на instancetype и таким образом, во время компиляции можно определить, что [[NSArray alloc] init] возвращает NSArray *, а не NSMutableArray *. Но эта проверка просто не работает с методом array.
Почему? Должны ли строки, подобные моему последнему примеру, генерировать хотя бы предупреждение? Почему не все эти методы объявлены как возвращающие instancetype? Будет ли это изменяться в будущем?
Обновление
Хорошие новости: с iOS 7, [NSArray array] возвращает instancetype, поэтому присвоение a4 выше также дает предупреждение. Другие методы, такие как arrayWithContentsOfFile: или arrayWithContentsOfURL, возвращают id, хотя...