【问题标题】:NSArray of NSDictionary in Objective CObjective C 中 NSDictionary 的 NSArray
【发布时间】:2023-03-29 14:40:01
【问题描述】:

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

这个函数看起来是这样但不起作用:

CBLModel的执行中我有emailList的属性。我想成为NSArrayNSDictionary 的属性。

-(void) addEmail: (NSDictionary*) c{
    NSMutableArray* mutArrayEmail= [NSMutableArray arrayWithObject: self.emailList];
    [mutArrayEmail addObject:c];
    self.emailList = [NSArray arrayWithObject:mutArrayEmail];  
}

而实现会是这样的:

[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];

在这之后我得到一个错误。我发布此代码示例可能更容易看出错误可能在哪里

【问题讨论】:

  • 是的,数组只需要创建一次,emailList 需要声明为可变数组。
  • @HotLicks 非常感谢,但我不能将它声明为可变数组,否则它在 CBLModel 中不起作用
  • 为什么不呢?你可以在任何可以使用 NSArray 的地方使用 NSMutableArray。

标签: objective-c cocoa-touch nsarray nsdictionary


【解决方案1】:

如果数组不存在,您只想创建它:

- (void)addEmail:(NSDictionary *) c{
    if (!self.emailList) {
        self.emailList = [[NSMutableArray alloc] init];
    }
    [self.emailList addObject:c];
}

这是延迟初始化,因为数组是在首次使用时创建的。这很好,只要您意识到数组在对象的生命周期中有时可能是 nil(这在 Objective-C 中比在其他语言中问题更少)。

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

【讨论】:

  • 好答案。可能值得注意的是,self.emailList 必须是 NSMutableArray(从 OP 的代码来看,它似乎是 NSArray)。
  • @BlackRider 是的,我也怀疑过,但他确实分配了NSMutableArray,所以我认为他理解这一点。
  • 您好,非常感谢您的时间和耐心。我需要使用 emailList 作为 NSArray,因为 CBLModel 不接受 NSMutableArray。
  • @user3009804 抱歉,我错过了最后一条评论的重点。您必须将实例变量设为 NSMutableArray 以允许您在创建后向其中添加项目。
  • @trojanfoe 再次非常感谢!我已经编辑了这个问题并添加了一个代码示例,所以很容易看到。我正在尽我所能,但这仍然不起作用
【解决方案2】:

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

【讨论】:

  • 嗨!非常感谢您的回复,但我不能将其声明为 NSMutableArray。对于向数据库插入数据,CBLModel 不接受 NSMutableArray,但 NSArray
【解决方案3】:

由于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];
}

【讨论】:

    【解决方案4】:

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

    self.emailList = [NSArray arrayWithArray:mutArrayEmail];
    

    不过,我远非专家,因此这种方法可能存在问题。我欢迎 cmets 达到这个效果!

    【讨论】:

    • 'NSInvalidArgumentException',原因:'需要 CBLModel,但得到了 __NSDictionaryI 0x769ef20'
    • 听起来错误不在于设置 emailList,而在于对数组元素所做的事情。我不熟悉 CBL,所以也许我在这里错过了重点。您确定要字典数组而不是 CBLModel 数组吗?
    • @user3009804 - 该错误表明您应该传递一个 CBLModel 对象(无论调用它是标记失败的地方)。
    【解决方案5】:

    您可以声明 NSMutableArray 的附加属性(可以在您的类扩展中):

    @property(nonatomic, copy)NSMutableArray *tempArray;
    

    在init中初始化

    _tempArray = [[NSMutableArray alloc] init];
    

    并将您的 setter 方法更改为:

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

    并将您的吸气剂更改为:

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

    【讨论】:

      【解决方案6】:

      我知道您是 SO 新手,所以有一点(友好!)建议:您需要在您的问题中提供更多详细信息,确切说明您尝试了什么以及出了什么问题;例如“在这之后我得到一个错误。”不帮助别人帮助你。

      现在阅读您的问题并发现两件事:关于CBLModel 的断言,以及如何将项目添加到数组中。

      A.首先,CBLModel。你已经说过几次你需要NSArray

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

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

      如果您的意思是如果您将NSMutableArray 传递给CBLModel,则它无法正常运行,比如说因为您自己在传递数组后对其进行了变异,并且以无效的方式影响CBLModel [*],那么您可以简单地创建一个不可变副本 ([NSArray arrayWithArray:someMutableArray]) 或只是另一个可变副本 ([someMutableArray copy]),您将传递给 CBLModel

      B.将项目添加到数组中。让我们逐行查看您的代码,以便您了解它在做什么:

      NSMutableArray* mutArrayEmail= [NSMutableArray arrayWithObject: self.emailList];
      

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

      [mutArrayEmail addObject:c];
      

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

      self.emailList = [NSArray arrayWithObject:mutArrayEmail];
      

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

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

      HTH


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

      【讨论】:

        【解决方案7】:

        一般来说,如果可变数组是对象状态的一部分,那么将其暴露给外部世界是个坏主意。这意味着可以在对象不知道的情况下修改对象的状态。

        我会这样做:

        有一个只读属性可以让人们获取数组。

        有一种方法可以将对象添加到数组中。

        @interface MyClass : NSObject
        
        @property (nonatomic, readonly, strong) NSArray* emailList;
        
        -(void) addEmail: (NSDictionary*) newEmail;
        
        @end
        

        在实现中,有一个 mutable 实例变量来支持属性,在您指定的初始化程序中对其进行初始化。实现你的 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,但规则是编程到接口,这意味着当接口说它返回一个不可变对象时,即使你知道它实际上是一个可变子类,你不允许向其发送变异方法。

        但是,如果您是偏执狂,请像这样为属性实现 getter:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-03-10
          • 2011-01-17
          相关资源
          最近更新 更多