Почему Xcode не предоставляет автозаполнение для точечных свойств объектов типа id <protocol>?
Учитывая это определение протокола:
@protocol MyProtocol <NSObject>
@property (nonatomic, strong) NSString *someProperty;
@end
Почему Xcode с радостью предложит автозаполнение для этого утверждения:
id<MyProtocol> thing = [ThingManager currentThing];
[thing someProperty]; // Xcode offered autocompletion here
Но он не предлагает автозаполнение, когда я пытаюсь получить доступ к одному и тому же свойству с помощью точечной нотации:
id<MyProtocol> thing = [ThingManager currentThing];
thing.someProperty; // Xcode claimed there were
// "No completions" available
// after the period
Ответы
Ответ 1
Поскольку id
является базовым типом, Xcode и CLANG не уверены в предоставлении доступа к точечно-синтаксическому сигналу против него, потому что точечный синтаксис является просто синтаксическим сахаром для вызова метода связанному сетевому устройству или получателю в обычном объекте, но id имеет нет определенных членов метода. Глядя на это со стороны C, id - это typedef для указателя структуры, который компилятор не может видеть в своих членах, что означает, что он не может получить к ним доступ (не обращая внимания на то, что вам нужно будет разыменовать id до того, как dot-access будет сделать какой-либо смысловой смысл).
Возвращаясь к Objective-C сторонам, протоколы фактически не добавляют методы или свойства классам, которые утверждают, что их реализуют, скорее они служат в качестве спецификатора для других классов, которые реализуют объект, соответствующий данному протоколу ряд методов. Что касается завершения синтаксиса метода, Xcode объединяет все указанные методы всех файлов, импортированных в данный файл .m, потому что объект идентификатора типа может получать любое сообщение *
* , конечно, он может получить сообщение, но он все равно будет сбой, если он не реализован.
Ответ 2
Это своего рода тангенциальный ответ и мысленный эксперимент.
Но до этого я буду замечать, что вы можете получить автозаполнение свойства, пропустив id
, например:
NSObject<MyProtocol> *thing;
thing.▮
Но если вы не хотите, чтобы весь список методов NSObject
завершал ваше завершение, вы могли бы сделать что-то вроде
EmptyClass<MyProtocol> *thing = [ThingManager currentThing];
// completion list will be (close) to only the protocol props
thing.▮
EmptyClass
служит аналогичный "OK, no promises!". роль, которую выполняет id
, но автозаполнение нравится. Здесь EmptyClass
:
NS_ROOT_CLASS
@interface EmptyClass
@end
@implementation EmptyClass
+ (void)initialize {} // required
@end
Помните, что объект в thing
на самом деле не внедрен на EmptyClass
(не может быть), поэтому это высокий fakery. Тем не менее, он
- значительно недооценивает то, что действительно может сделать
thing
.
- не (не может!) создает экземпляр объекта
EmptyClass
.
Так почему бы и нет? Если вы попытаетесь сделать это очень сложно, вы можете вызвать такие проблемы, как
EmptyClass *nooooo = [[NSClassFromString(@"EmptyClass") alloc] init];
который будет немедленно исключать. Но на самом деле это не сложная ошибка.
Я не удивлю меня, но я не знаю этого сейчас. Пожалуйста, оставьте комментарий, если вы это сделаете.