Pallavi Nikumbh
Pallavi Nikumbh

Reputation: 308

Swift: SetValue to NSDictionary

I have try to set the array value to array of dictionary key. here is my code

this is my Time Slots array Initialization:

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

I was show the value of 'time' key on tableview initially. When user select day from calendar I was fetching data from database respective to the selected day. the data is in Dictionary format as:

{     
   "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";
 }

so I want to add this dictionary in ArrmTimeSlots array for "action" key. Here is my code to add the dictionary in array:

 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")
         }
 }

but, My app is crash and get the error on 'd.setValue(array, forKey: "action")' this line :

Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<_TtGCSs29_NativeDictionaryStorageOwnerSSCSo8NSObject_ 0x1566dbc0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key action.' *** First throw call stack: (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: terminating with uncaught exception of type NSException

Please Suggest me solution for this. Thanks in Advance!

Upvotes: 0

Views: 2676

Answers (3)

Enea Dume
Enea Dume

Reputation: 3232

your problem is that you have declared it as a NSDictionary, so make it NSMutableDictionary and it will work. :)

Upvotes: 0

vadian
vadian

Reputation: 285190

Your repeat loop is very inefficient because all items are evaluated even if the first item already matches the time.

At first glance NSArray and NSDictionary seem to be more convenient because you don't have to take care of the type but that's a false conclusion.

This is a native Swift solution replacing your entire repeat loop. If gets the index of the array using the indexOf function, assigns the array if necessary and updates the item in the arrmTimeSlots array.

The only disadvantage is you have to assign child items back to parent items due to the value type semantics of Swift collection types

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

I recommend to use a custom struct rather than a dictionary for the arrmTimeSlots items. It can avoid more type casting yet.

Upvotes: 0

konrad.bajtyngier
konrad.bajtyngier

Reputation: 1786

You will need to overwrite the array item with a modified object. You can user enumerate() to get and index and object in each iteration at the same time.

Secondly, when declaring the day variable, you need to use var instead of let so you can modify it.

Here is a sample code:

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
    }
}

Upvotes: 1

Related Questions