【问题标题】:Swift: SetValue to NSDictionarySwift:将值设置为 NSDictionary
【发布时间】:2016-01-22 14:01:42
【问题描述】:

我尝试将数组值设置为字典键数组。 这是我的代码

这是我的时间槽数组初始化:

 arrmTimeSlots = [
            ["time": "6am", "action": []],
            ["time": "7am", "action":  []],
            ["time": "8am", "action":  []],
            ["time": "9am", "action":  []],
            ["time": "10am", "action":  []],
            ["time": "11am", "action":  []],
            ["time": "12pm", "action":  []],
            ["time": "1pm", "action":  []],
            ["time": "2pm", "action":  []],
            ["time": "3pm", "action":  []],
            ["time": "4pm", "action":  []],
            ["time": "5pm", "action":  []],
            ["time": "6pm", "action":  []],
            ["time": "7pm", "action":  []],
            ["time": "8pm", "action":  []],
            ["time": "9pm", "action":  []],
            ["time": "10pm", "action":  []]
        ];

我最初是在 tableview 上显示“时间”键的值。当用户从日历中选择日期时,我正在从数据库中获取与所选日期相对应的数据。数据采用字典格式:

{     
   "Description" = "this is discription";
   "End_time" = 201601240645;
   "Location" = "xyz";
   "Rec_uid" = "r576thg8ed-698a-4a71-87e5-366bec44638a";
   "Satrt_time" = 201601240645;
   "Title" = "hrhrcffu";
   "uid" = "c39b2987-5d19-4178-8591-c052b5205ad5";
 }

所以我想在 ArrmTimeSlots 数组中为“action”键添加这个字典。 这是我在数组中添加字典的代码:

 for scheduleDay in arrmTimeSlots
   {                  
     let day = scheduleDay as! NSDictionary

     let timeOnSlots = day["time"] as! String

     let action = day["action"] as! NSArray

     print("time \(timeOnSlots)  action \(action)")

      if(timeOnSlots == concatTimeslotTime) // here compare time if true set array to action key
         {
            day.setValue(array, forKey: "action")
         }
 }

但是,我的应用程序崩溃并在 'd.setValue(array, forKey: "action")' 这一行得到错误:

由于未捕获的异常“NSUnknownKeyException”而终止应用程序,原因:“[<_ttgcss29_nativedictionarystorageownersscso8nsobject_> setValue:forUndefinedKey:]:此类不符合键操作的键值编码。” *** 首先抛出调用堆栈: (0x240dc0d7 0x32778c77 0x240dbde5 0x24d71c95 0x1ea1c4 0x1e7888 0x1e57f4 0x1e5974 0x107c2b 0xfc95d 0x27d36dd9 0x2793f495 0x2793f197 0x278bb4c9 0x278bb4c9 0x2776dee3 0x277677f1 0x2773d9b5 0x279b40ff 0x2773c3b7 0x240a200f 0x240a1423 0x2409faa1 0x23feb6d1 0x23feb4e3 0x2b9581a9 0x2779d445 0x17ffd8 0x32d46aaf) libc++abi.dylib:以 NSException 类型的未捕获异常终止

请为此建议我解决方案。 提前致谢!

【问题讨论】:

  • 你必须使用setObject 而不是setValue
  • d 定义在哪里?
  • @SandyChapman 查看我编辑的问题。这是“一天”。
  • 使用 Foundation 集合类型(NSArrayNSDictionary)而不是 Swift 原生类型有什么特别的原因吗?
  • 顺便说一句,您必须使用NSMutableDictionary,否则您将无法更改值(当然使用setObject,而不是setValue)。另请注意,day["action"] = array 也适用于 NSMutableDictionary

标签: arrays swift dictionary key-value-coding


【解决方案1】:

您需要用修改后的对象覆盖数组项。您可以使用enumerate() 在每次迭代中同时获取和索引和对象。

其次,在声明day变量时,需要使用var而不是let,这样就可以修改了。

这是一个示例代码:

for (i, scheduleDay) in arrmTimeSlots.enumerate()
{
    var day = scheduleDay

    let timeOnSlots = day["time"]

    let action = day["action"]

    print("time \(timeOnSlots)  action \(action)")

    if(timeOnSlots == concatTimeslotTime) // here compare time if true set array to action key
    {
        day["action"] = array
        arrmTimeSlots[i] = day
    }
}

【讨论】:

    【解决方案2】:

    您的重复循环效率非常低,因为即使第一项已与时间匹配,也会评估所有项目。

    乍一看NSArrayNSDictionary 似乎更方便,因为您不必关心类型,但这是一个错误的结论。

    这是一个原生 Swift 解决方案,可替代整个重复循环。 如果使用indexOf 函数获取数组的索引,则在必要时分配数组并更新arrmTimeSlots 数组中的项。

    唯一的缺点是由于 Swift 集合类型的值类型语义,您必须将子项分配回父项

    if let indexOfTimeOnSlots = arrmTimeSlots.indexOf( { $0["time"] as! String == concatTimeslotTime }) {
      var item = arrmTimeSlots[indexOfTimeOnSlots]
      item["action"] = array
      arrmTimeSlots[indexOfTimeOnSlots] = item
    }
    

    我建议为 arrmTimeSlots 项目使用自定义 struct 而不是字典。它可以避免更多的类型转换。

    【讨论】:

    • 非常酷的解决方案。如果同一时间值多次出现,则不是,但在这种情况下应该是正确的。
    • 问题中的样本数组具有唯一的时间条目。
    • 是的,这就是为什么在这种情况下它是完美的
    【解决方案3】:

    您的问题是您已将其声明为 NSDictionary,因此将其设为 NSMutableDictionary 即可。 :)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-14
      • 2014-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-14
      • 1970-01-01
      • 2015-10-24
      相关资源
      最近更新 更多