Objective c NSC中的NSDictionary数组

Objective c NSC中的NSDictionary数组,objective-c,cocoa-touch,nsarray,nsdictionary,Objective C,Cocoa Touch,Nsarray,Nsdictionary,我正在尝试开发一个函数,将字典添加到数组中 此函数看起来是这样的,但不起作用: 在CBLModel的实现中,我有属性emailList。我想成为NSDictionary的NSArray的属性 而实施过程将类似于: [persInf addEmail: email1]; [persInf addEmail: email2]; [persInf addEmail: email3]; 有什么帮助吗 编辑 谢谢大家的回复 我在主代码中插入了以下内容,以避免更容易地测试所有内容: NSDictionar

我正在尝试开发一个函数,将字典添加到数组中

此函数看起来是这样的,但不起作用:

在CBLModel的实现中,我有属性emailList。我想成为NSDictionary的NSArray的属性

而实施过程将类似于:

[persInf addEmail: email1];
[persInf addEmail: email2];
[persInf addEmail: email3];
有什么帮助吗

编辑

谢谢大家的回复

我在主代码中插入了以下内容,以避免更容易地测试所有内容:

NSDictionary *inventory = @{
                            @"Mercedes-Benz SLK250" : [NSNumber numberWithInt:13],
                            @"Mercedes-Benz E350" : [NSNumber numberWithInt:22],
                            @"BMW M3 Coupe" : [NSNumber numberWithInt:19],
                            @"BMW X6" : [NSNumber numberWithInt:16],

                            };
NSMutableArray *nsmut= [[NSMutableArray alloc] init];
[nsmut addObject: inventory];
[nsmut addObject: inventory];
[nsmut addObject: inventory];
NSArray *nsarray= [NSArray arrayWithArray:nsmut];

[persInf setEmailList:nsarray];

在这之后,我得到了一个错误。我发布了这个代码示例,因为可能更容易看到错误的位置

您只想在阵列不存在的情况下创建它:

- (void)addEmail:(NSDictionary *) c{
    if (!self.emailList) {
        self.emailList = [[NSMutableArray alloc] init];
    }
    [self.emailList addObject:c];
}
这是延迟初始化,因为数组是在第一次使用时创建的。这很好,只要您意识到数组在对象的生命周期中有时可能为零,这在Objective-C中比在其他语言中更不成问题

更传统的方法是重写init方法并在那里分配数组。

在addEmail:方法之外声明NSMutableArray。您可以按原样使用addObject。

因为emailList是一个属性,所以您应该重写getter,以便在需要时惰性地实例化它,如下所示

- (NSMutableArray *)emailList {
  if(!_emailList) {
    _emailList = [NSMutableArray array];
  }
  return _emailList
}
为了更彻底,您可以使用三元数编写代码,并将其缩短一点:

- (NSMutableArray *)emailList {
  return _emailList = _emailList ?: [NSMutableArray array];
}
最后,一旦覆盖了getter,addEmail方法将变为:

- (void)addEmail: (NSDictionary*)c {
[self.emailList addObject:c];
}

如果您必须将emailList存储为NSArray,我想您需要将其设置为

self.emailList = [NSArray arrayWithArray:mutArrayEmail];

不过,我远不是专家,所以这种方法可能会有问题。我欢迎大家发表这样的评论

您可以声明NSMutableArray的其他属性,它可以位于类扩展中:

@property(nonatomic, copy)NSMutableArray *tempArray;
在init中初始化它

_tempArray = [[NSMutableArray alloc] init];
并将setter方法更改为:

-(void) addEmail: (NSDictionary*) c{
[self.tempArray addObject:c];
}
并将您的getter更改为:

- (NSArray *)emailList {
return [NSArray arrayWithArray:[self.tempArray copy]];
}

我看你是新来的,所以有点友好!建议:你需要在你的问题中提供更多的细节,确切地说你尝试了什么,出了什么问题;e、 在这之后,我得到一个错误。不帮助别人帮助你

现在阅读您的问题和评论,两件事会突然出现:关于CBLModel的断言,以及如何向数组中添加项

[mutArrayEmail addObject:c];
首先,CBL模型。您已经多次声明需要NSArray,如:

我不能将它声明为可变数组,否则它在CBL模型中不起作用

你这是什么意思?如果您说CBLModel中的方法采用NSArray类型参数,那么您可以传递NSMutableArray,因为NSMutableArray是NSArray,即它是一个子类-这是基于继承的语言(如Objective-C)的中心支柱之一

相反,如果您的意思是,如果将NSMutableArray传递给CBLModel,则CBLModel无法正常工作,比如说,因为您自己在传递后对数组进行了变异,而这会以无效方式影响CBLModel[*],那么您只需创建一个不可变副本[NSArray arrayWithArray:someMutableArray]或另一个可变副本[someMutableArray copy]只传递给CBL模型

B.向数组中添加项。让我们逐行查看您的代码,这样您就可以看到它在做什么:

NSMutableArray* mutArrayEmail= [NSMutableArray arrayWithObject: self.emailList];
这将创建一个新的NSMutableArray,该数组使用从self.emailList获得的单个元素初始化,并将对它的引用存储在MutarrayMail中。例如,如果在执行之前self.emailList引用数组[1,2,3],那么在执行之后MutarrayMail引用可变数组[[1,2,3]]——其元素本身就是数组的单个元素数组

[mutArrayEmail addObject:c];
您添加了由c引用的对象,因此使用相同的示例,您现在拥有[[1,2,3],c]-一个包含两个元素的数组

最后,使用MutarrayMail引用的单个对象创建一个新数组。保持相同的示例,您现在有[[1,2,3],c]]。这可能不是您想要的,也不是CBLModel接受的

类方法arrayWithArray:创建一个与另一个数组具有相同元素的数组。如果您使用该方法,上面的示例将生成[1,2,3,c],这可能是您想要的


[*]任何接受具有可变子类型[数组、字符串等]的类型的对象的类通常都会被写入,以便在对象传递后的变异不会以不希望的方式影响行为,即,如果需要,这些类会复制对象。这建议使用copy属性定义此类类型的属性。

通常,如果可变数组是对象状态的一部分,则将其公开给外部世界是个坏主意。这意味着对象的状态可以在对象不知道的情况下进行修改

我会这样做:

具有允许用户获取数组的只读属性

@interface MyClass : NSObject

@property (nonatomic, readonly, strong) NSArray* emailList;

-(void) addEmail: (NSDictionary*) newEmail;

@end
具有将对象添加到数组的方法

@interface MyClass : NSObject

@property (nonatomic, readonly, strong) NSArray* emailList;

-(void) addEmail: (NSDictionary*) newEmail;

@end
在实现中,使用可变实例变量来支持属性,在指定的初始化器中初始化它。实现add方法

// All code assumed to be using ARC

@implementation MyClass
{
    NSMutableArray* _emailList;
}

@synthesize emailList = _emailList;

-(id) init
{
    self = [super init];
    if (self != nil)
    {
        _emailList = [[NSMutableArray alloc] init];
    }
    return self;
}

-(void) addEmail: (NSDictionary*) newEmail
{
    [_emailList addObject: newEmail];
}

@end
虽然属性返回的实际对象是NSMutableArray,但规则是编程到 e接口,这意味着当一个接口说它返回一个不可变的对象时,即使你知道它实际上是一个可变的子类,你也不允许发送它变异的方法

但是,如果您是偏执狂,请实现属性的getter,如下所示:

-(NSArray*) emailList
{
    return [_emailList copy];
}

回答得好。可能值得注意的是,self.emailList需要是OP代码中的NSMutableArray。它似乎是NSArray。@BlackRider是的,我也怀疑,但是他确实分配了NSMutableArray,所以我认为他理解。您好,非常感谢您的时间和耐心。我需要使用emailList作为NSArray,因为CBLModel不接受NSMutableArray。@user3009804抱歉,我没有抓住最后一条评论的要点。您必须将实例变量设置为NSMutableArray,以便在创建后向其添加项。@特洛伊木马再次感谢您!我已经编辑了这个问题,并添加了一个代码示例,以便于查看。我正在尽最大努力,但这仍然不起作用。是的,您只需要创建一次数组,emailList需要声明为可变数组。@HotLicks非常感谢,但我不能将其声明为可变数组,否则它在CBL模型中不起作用。为什么不呢?你可以在任何可以使用NSArray的地方使用NSMutableArray。嗨!非常感谢您的回复,但我不能将其声明为NSMutableArray。对于向数据库插入数据,CBLModel不接受NSMUTABLEARRY,但NSArray'NSInvalidArgumentException',原因:'CBLModel是必需的,但GET u NSDictionaryI 0x769ef20'听起来错误不在设置emailList中,而在对数组元素所做的操作中。我不熟悉CBL,所以我可能没有抓住重点。你确定你想要一个字典数组而不是一个CBLModel数组吗?@user3009804-该错误表示你应该在标记失败的任何调用上传递CBLModel对象。