我正在研究Objective-C。我之前问了一个关于这段代码的问题,但我提出了进一步的问题。以下代码尝试在外部NSArray
,但内部确实NSMutableArray
,因此我可以添加指针或删除NSMutableArray
我面临两个问题。
1)这样做的目的是什么?您是否有外部NSArray
的具体原因?为什么我不能声明NSMutableArray
的属性?
2)我知道当我声明_assets
的属性时,实例变量(NSArray *assets
)。我还在界面下声明了NSMutableArray *_assets
。我认为这两个_assets
相互冲突,即使它们有不同的类型。我是以错误的方式思考这个问题的吗?
@interface BNREmployee : BNRPerson
{
NSMutableArray *_assets;
}
@property (nonatomic) unsigned int employeeID;
@property (nonatomic) unsigned int officeAlarmCode;
@property (nonatomic) NSDate *hireDate;
@property (nonatomic, copy) NSArray *assets;
答案 0 :(得分:1)
穿戴 { NSMutableArray * _assets; } 在@implementation块中
@implementation {
NSMutableArray *_assets;
}
将NSMutableArray放在实现块中隐藏了这样一个事实:它可以从消费者那里变化(它不再在头文件中)。
跟着它:
@synthesize assets = _assets;
实际上这可能不是必需的,但可以让事情变得更加清晰。当您声明属性时,将自动创建ivar(除非您@dynamic属性)。但是,显式声明的同名ivar将覆盖自动创建的ivar - 只要类型相同或是子类。
使其成为NSArray公开可见的原因是没有其他人可以改变您的数据结构。你将控制它。如果它是内部的NSMutableArray,那么您可以添加和删除项目,而不会将该功能暴露给消费者。
您可以将您的属性声明为readonly或readwrite - 读写NSArray意味着您可以使用属性集替换整个数组,但您无法添加或删除项目。如果你在内部添加和删除项目,这可能会使事情变得混乱。当有一个可变的内部版本时,尽量坚持readonly。
答案 1 :(得分:1)
我会按照你问他们的方式尝试你的答案。让希望他们清除你的疑虑。到目前为止,我猜你会知道NSArray
一旦初始化了数据,你将无法添加或删除其中与NSMutableArray
不同的数据。
此处的好处是没有其他人可以更改您的外部可见数据。此外,当您尝试对数组进行排序或迭代时,您确信不会删除或添加其他数据。此外,如果您对此类情况使用NSMutableArray
,则在迭代数组时添加数据时应用程序会崩溃。
喜欢@KirkSpaziani解释
@synthesize assets = _assets;
将为您的属性创建一个实例变量。但实际上你应该只在getter和setter中使用这个_assets
。您应该使用其他地方self.assets
。
您还可以按如下方式合成您的其他数组NSMutableArray *_assets
@synthesize _assets = __assets;
哪个会有双下划线,但坦率地说我们不应该使用下划线作为起始变量名。如果你有完全不同的名字,那就太好了。
同样,随着Objective C的进步,您根本不需要合成这些变量。只需使用self.variableName
即可访问它。
希望它能清除你的一些疑问。
答案 2 :(得分:1)
如果您希望_assets
成为可变数组,但是您不希望其他类修改它,那么您可以执行以下操作:实现assets属性的setter和getter,使它们看起来像这样(实现getter和setter将导致属性不被合成,这意味着NSArray *_assets
将不会自动创建):
-(NSArray *)assets{
return [_assets copy]; // Copy creates an immutable copy
}
-(void)setAssets:(NSArray *)assets{
_assets = [NSMutableArray arrayWithArray:assets];
}
请记住,如果您访问资产数组很多,它可能会很慢,因为您每次都创建一个不可变副本,因此您可以在修改_assets
数组时创建NSArray并返回在-(NSArray *)assets
方法
答案 3 :(得分:0)
您在内部保留NSMutableArray
但在外部公开NSArray
的原因是,您的API用户不会滥用它并改变其数据。将其视为不可变的使人们不太容易弄乱它。
您可以采取的另一种方法是根本不使用属性,而只是在类扩展中使用getter和mutable属性。例如,在你的.h:
@interface BNREmployee : BNRPerson
- (NSArray *)assets;
@end
在你的.m
@interface BNREmployee ()
// Inside of the class manipulate this property
@property (nonatomic, strong) NSMutableArray *mutableAssets;
@end
@implementation BNREmployee
// Clients of your class rely on this
- (NSArray *)assets
{
// copy makes the result immutable
return [self.mutableAssets copy];
}
@end
答案 4 :(得分:0)
另一种方法可能是使该属性只能写入您的类的实现。
为此,请在标题中将您的媒体资源声明为readonly
:
//BNREmployee.h
@property (nonatomic, readonly) NSMutableArray *assets;
在实现的内部接口中将其声明为readwrite
:
//BNREmployee.m
@interface BNREmployee()
@property (nonatomic, readwrite) NSMutableArray *assets;
@end
@implementation
...