[英]How to conform to Objective-C protocol with readonly properties in Swift
[英]Objective-C readonly properties in a subclass
我有一個稱為SuperClass的超類,它是一個只讀屬性。 看起來像這樣:
@property (nonatomic, strong, readonly) NSArray *arrayProperty;
在子類中,我需要一個初始化程序,該初始化程序將SuperClass的實例作為參數:
- (instancetype)initWithSuperClass:(SuperClass *)superClass
我創建了一個GitHub示例項目來顯示問題所在: https : //github.com/marosoaie/Objc-test-project
我無法在初始化程序中執行_arrayProperty = superClass.arrayProperty
。 我也想在SubClass中保持該屬性為只讀。
關於如何解決的任何想法?
我知道我可以在SubClass實現文件中的類擴展中將該屬性聲明為readwrite,但是我希望有比這更好的解決方案。
編輯:SuperClass.h
#import <Foundation/Foundation.h>
@interface SuperClass : NSObject
- (instancetype)initWithDictionary:(NSDictionary *)dictionary;
@property (nonatomic, strong, readonly) NSString *stringProperty;
@property (nonatomic, strong, readonly) NSArray *arrayProperty;
@end
超類
#import "SuperClass.h"
@implementation SuperClass
- (instancetype)initWithDictionary:(NSDictionary *)dictionary
{
self = [super init];
if (self) {
_arrayProperty = dictionary[@"array"];
_stringProperty = dictionary[@"string"];
}
return self;
}
@end
SubClass.h:
#import <Foundation/Foundation.h>
#import "SuperClass.h"
@interface SubClass : SuperClass
@property (nonatomic, strong, readonly) NSString *additionalStringProperty;
- (instancetype)initWithSuperClass:(SuperClass *)superClass;
@end
子類.m:
#import "SubClass.h"
@implementation SubClass
@synthesize additionalStringProperty = _additionalStringProperty;
- (NSString *)additionalStringProperty
{
if (!_additionalStringProperty) {
NSMutableString *mutableString = [[NSMutableString alloc] init];
for (NSString *string in self.arrayProperty) {
[mutableString appendString:string];
}
_additionalStringProperty = [mutableString copy];
}
return _additionalStringProperty;
}
- (instancetype)initWithSuperClass:(SuperClass *)superClass
{
self = [super init];
if (self) {
// Doesn't work
// _stringProperty = superClass.stringProperty;
// _arrayProperty = superClass.arrayProperty;
}
return self;
}
@end
您已經暴露了一個初始化程序,該初始化程序寫入該只讀屬性-initWithDictionary:
在您的SubClass中調用它,而不是[super init]
:
- (instancetype)initWithSuperClass:(SuperClass *)superClass {
NSDictionary *dict = @{
@"array": superClass.arrayProperty,
@"string": superClass.stringProperty,
};
self = [super initWithDictionary:dict];
if (self) {
// Nothing here.
}
return self;
}
對於只讀屬性有一個初始化器是很常見的,盡管使用字典並不是一個好的解決方案。 通常,我會創建:
- (instancetype)initWithArray:(NSArray *)array string:(NSString *)string;
首先,測試設置中存在一個錯誤@"arrayProperty"
- (instancetype)initWithDictionary:(NSDictionary *)dictionary
是@"array"
,其中數組包含@"arrayProperty"
。
關於您的問題:
//...
@interface SuperClass : NSObject
{
@protected // this is what you want: a protected class property, accessible in subclasses, but no where else
NSString *_stringProperty;
NSArray *_arrayProperty;
}
@property (nonatomic, strong, readonly) NSString *stringProperty;
@property (nonatomic, strong, readonly) NSArray *arrayProperty;
- (instancetype)initWithDictionary:(NSDictionary *)dictionary;
@end
// SubClass.m
//...
@implementation SuperClass
- (instancetype)initWithDictionary:(NSDictionary *)dictionary
{
self = [super init];
if (self) {
_arrayProperty = dictionary[@"arrayProperty"]; // this was @"array", so could not work
_stringProperty = dictionary[@"stringProperty"]; // same here
}
return self;
}
@end
然后就可以了。 另外,我會寫
@interface SubClass ()
@property (nonatomic, strong, readwrite) NSString *additionalStringProperty;
@end
@implementation SubClass
- (instancetype)initWithSuperClass:(SuperClass *)superClass
{
self = [super init];
if (self) {
_stringProperty = superClass.stringProperty;
_arrayProperty = superClass.arrayProperty;
}
return self;
}
因為相比@synthesize
魔術,我更喜歡類擴展中的readwrite
屬性。 但這是個人觀點。
有關類設計的一個主要問題仍然存在:如果(類似於您的測試設置)超類的字典不包含鍵,將會發生什么? 然后它不會被初始化,這不是一個好主意,因為您希望它們被初始化。 因此,如果superclass.stringProperty不為nil,則應檢查子類,並為超類添加標准構造函數,以避免兩個字典未初始化。
在您的SuperClass.m中:
- (instancetype)initWithDictionary:(NSDictionary *)dictionary
{
self = [super init];
if (self) {
// these were always nil, check your dictionary keys
_arrayProperty = dictionary[@"arrayProperty"];
_stringProperty = dictionary[@"stringProperty"];
}
return self;
}
在您的SubClass.m中:
@interface SubClass ()
@property (strong, nonatomic) NSString * additionalStringProperty;
@property (strong, nonatomic) NSString * subClassString;
@property (strong, nonatomic) NSArray * subClassArray;
@end
@implementation SubClass
- (instancetype)initWithSuperClass:(SuperClass *)superClass
{
self = [super init];
if (self) {
_subClassString = superClass.stringProperty;
_subClassArray = superClass.arrayProperty;
}
return self;
}
我在這里嘗試答案無濟於事。 最終對我有用的是這個答案 ,它提到您應該直接訪問成員變量(在將其聲明為受保護后),如下所示:
self->_stringProperty = @"some string";
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.