Ошибка «свойство имеет предыдущее объявление» в расширении класса: ошибка или функция? - PullRequest
0 голосов
/ 31 октября 2018

В Objective-C вы можете , как правило, повторно объявить свойство readonly как readwrite в расширении класса, например:

@interface PubliclyImmutablePrivatelyMutableClass : NSObject

@property (readonly, nonatomic) SomeStateEnum someState;

@end

// In "PubliclyImmutablePrivatelyMutableClass+Private.h"
// or "PubliclyImmutablePrivatelyMutableClass.m"
@interface PubliclyImmutablePrivatelyMutableClass()

@property (readwrite, nonatomic) SomeStateEnum someState;

@end

// In "PubliclyImmutablePrivatelyMutableClass.m"
@implementation PubliclyImmutablePrivatelyMutableClass @end

Если, однако, я ввожу свойство в расширение класса как readonly и попытаюсь повторно объявить его как readwrite во втором, Clang Xcode 10 выдаст мне ошибку компилятора:

@interface ClassWithPrivateImmutableInternallyMutableProperty : NSObject

// any public API

@end


// In "ClassWithPrivateImmutableInternallyMutableProperty+Private.h"
@interface ClassWithPrivateImmutableInternallyMutableProperty()

@property (readonly, nonatomic) SomePrivateStateEnum somePrivateState;

@end


// In "ClassWithPrivateImmutableInternallyMutableProperty.m"
@interface ClassWithPrivateImmutableInternallyMutableProperty()

@property (readwrite, nonatomic) SomePrivateStateEnum somePrivateState; // error: property has a previous declaration

@end

@implementation ClassWithPrivateImmutableInternallyMutableProperty
// other API
@end

Теперь мне интересно:

  • Ошибка компилятора - ошибка / регрессия в Clang или преднамеренная функция?
  • Если это ошибка, есть ли другой обходной путь, чем ручная реализация установщика?

1 Ответ

0 голосов
/ 01 ноября 2018

Я считаю, что это корректное поведение компилятора.

Во втором примере вы используете две категории продолжения класса с одним и тем же именем (), чтобы дважды объявить одно и то же свойство. Это фактически то же самое, что дважды объявлять одно и то же имя свойства в одном и том же расширении.

Обратите внимание, что это отличается от первого примера, в котором свойство сначала объявляется в заголовке , а затем повторно объявляется в единственной категории продолжения класса с именем ().

Если я прав, ответ состоит в том, чтобы пометить расширение класса '+ private' именем, например (Private) вместо ():

@interface ClassWithPrivateImmutableInternallyMutableProperty(Private)

А также, если у вас есть реализация для частного расширения:

@implementation ClassWithPrivateImmutableInternallyMutableProperty(Private)

Надеюсь, это поможет!

...