如何声明由可变类型支持的不可变属性?

zou*_*oul 20 properties objective-c

我想声明一个公共不可变属性:

@interface Foo
@property(strong, readonly) NSSet *items;
@end
Run Code Online (Sandbox Code Playgroud)

...在实现文件中以可变类型支持:

@interface Foo (/* private interface*/)
@property(strong) NSMutableSet *items;
@end

@implementation
@synthesize items;
@end
Run Code Online (Sandbox Code Playgroud)

我想要的是实现中的可变集合,当从外部访问时,它会被转换为不可变的集合.(我并不关心调用者是否可以将实例强制转换NSMutableSet并打破封装.我住在一个安静,体面的城镇,这样的事情不会发生.)

现在我的编译器将属性视为NSSet实现内部.我知道有很多方法可以让它工作,例如使用自定义getter,但有没有办法简单地使用声明的属性?

eds*_*sko 9

最简单的解决方案是

@interface Foo {
@private
    NSMutableSet* _items;
}

@property (readonly) NSSet* items;
Run Code Online (Sandbox Code Playgroud)

然后就是

@synthesize items = _items;
Run Code Online (Sandbox Code Playgroud)

在你的实现文件中.然后你可以通过_items访问可变集,但公共接口将是一个不可变集.

  • 无需猜测:添加下划线.从使用LLVM编译器4.0的Xcode 4.4开始,我们有了新功能"@property实例变量和访问器方法的默认综合".无需调用`@ synthesize`.默认合成(自动合成)使用变量的名称加上下划线字符的前缀.因此,对于属性`foo`,你应该能够直接引用`_foo`,就像在`self - > _ foo = ... whatever ......;`.我不是专家,但这似乎对我有用.有关默认综合的文章:http://useyourloaf.com/blog/2012/08/01/property-synthesis-with-xcode-4-dot-4.html (2认同)
  • 编译器确实保证了它.这是正确的方法.除非绝对必要,否则不应使用Synthesize. (2认同)

小智 8

您必须将公共接口中的属性声明为readonly,以便编译器不要抱怨.像这样:

Word.h

#import <Foundation/Foundation.h>

@interface Word : NSObject
@property (nonatomic, strong, readonly) NSArray *tags;
@end
Run Code Online (Sandbox Code Playgroud)

Word.m

#import "Word.h"

@interface Word()
@property (nonatomic, strong) NSMutableArray *tags;
@end

@implementation Word
@end
Run Code Online (Sandbox Code Playgroud)

  • 在整个.m文件中,如果不使用此解决方案,编译器似乎仍然认为它是不可变版本. (8认同)
  • 除了"非原子的,强大的"之外,私有财产还需要"读写". (2认同)

D.C*_*.C. 2

你可以在你的实现中自己做:

@interface Foo : NSObject
    @property(nonatomic, retain) NSArray *anArray;
@end
Run Code Online (Sandbox Code Playgroud)

--- 实施文件 ---

@interface Foo()
{
    NSMutableArray *_anArray;
}
@end

@implementation Foo

- (NSArray *)anArray
{
    return _anArray;
}

- (void)setAnArray:(NSArray *)inArray
{
     if ( _anArray == inArray )
     {
         return;
     }
     [_anArray release];
     _anArray = [inArray retain];
}

- (NSMutableArray *)mutablePrivateAnArray
{
    return _anArray;
}

@end
Run Code Online (Sandbox Code Playgroud)

  • 手动编写 getter 和 setter 正是我想要避免的。 (3认同)