Objective-C 属性,仅公开超类

3

我在头文件中声明了一个类属性;

@property (readonly) NSArray *pages

我希望公开展示的方式如此。但在内部,我将把它分配为NSMutableArray,以便添加/删除其中的内容。 但要做到这一点,我每次都必须进行类型转换。 有更好的方法吗? 谢谢。

2个回答

3

你的做法真的很糟糕。如果你坚持使用带有动态内容的可变数组,请修改你的getter方法返回一个不可变的拷贝,否则在快速枚举期间进行变更操作会导致奇怪的副作用和异常。


我不坚持暴露一个可变数组。我想要暴露一个不可变的数组。如果我暴露一个不可变的数组,它就不能在外部被改变(如果有人将其强制转换为可变的,则那是他们的问题)。如果我有任何错误,请纠正我。 - 0xSina
1
@OxSina 但是当某人在迭代他们认为是不可变数组时,它可以在内部发生变异。 - hpique

2

这个问题目前还没有解决方案。你需要每次都进行转换,或使用不同的属性。下面是第二种方法的示例:

@interface MyClass : NSObject
@property (nonatomic, strong, readonly) NSArray *pages;
-(void)addObject:(id)obj;
@end

@interface MyClass()
@property (nonatomic, strong, readwrite) NSMutableArray *mPages;
@end

@implementation MyClass
-(id) init {
    self = [super init]
    if (self){
        _mPages = [NSMutableArray array];
    }
    return self;
}
-(NSArray*)pages {
    return [NSArray arrayWithArray:self.mPages];
}
-(void)addObject:(id)obj {
    [self.mPages addObject:obj];
}
@end


int main(int argc, char *argv[]) {
    @autoreleasepool {
        MyClass *m = [MyClass new];
        [m addObject:@"x"];     // the collection is mutable
        NSLog(@"%@",[m pages]); // but only accessible as an immutable copy
    }
}

如果您频繁访问集合,这将是昂贵的,并且可能与内部可变集合不同步(在您迭代副本时可能被修改)。
可以通过返回伪装成不可变类(NSArray)的内部可变实例(NSMutableArray)来避免复制,但这会带来以下风险:
客户端可能会转换为可变并更改它。
内部副本可能会被修改。如果您正在迭代,则会导致应用程序崩溃,或者可能会导致索引超出范围异常。
请注意,以下习语不能解决问题:
@interface MyClass : NSObject
@property (nonatomic, strong, readonly) NSArray *pages;
@end

@interface MyClass()
@property (nonatomic, strong, readwrite) NSMutableArray *pages;
@end

这允许你设置变量,但不能将其用作与接口中声明的不同类。换句话说,它强制你在每次使用时进行转换:

[(NSMutableArray*)pages addObject:@"x"];

1
嗯...强引用不是意味着具有所有权的读写吗?这个可以运行,我只是在想为什么。(说强引用、只读没有任何意义) - 0xSina
不,它只是为了内存管理目的而暗示所有权(你只保留自己拥有的东西)。你可以拥有一个只读变量。 - Jano
但是我无法在实现中为页面调用 addObject: 方法?你试过了吗? - sunkehappy
在构造函数中使用可变实例进行初始化,尝试 [(NSMutableArray*)self.pages addObject:obj]; - Jano
Jano,那就是最初的问题 :( - “但是为了做到这一点,我每次都必须进行类型转换。” - 0xSina
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接