Search code examples
iosswiftuitableviewnsarraynsdictionary

Mapping Dictionary to custom object for TableView


We have a custom Plist which contains data for a bunch of fields we are adding to a tableView. The layout is like this:

Root Array
-- Section (Array)
--- Field (Dictionary)
---- FieldName
---- HasError
---- FieldType
--- Field (Dictionary)
---- FieldName
---- HasError
---- FieldType

There are multiple sections, with multiple fields in each. Each field is a dictionary, which we will later map to a custom object type. For example 'FieldObject'.

I understand we can create a custom initWithDictionary method on the 'FieldObject' to create a model object from each dictionary.

At the moment we get the relevant data like this:

 let tvDataPath = NSBundle.mainBundle().pathForResource("CandRegisterFields", ofType: "plist")
self.tableViewData = NSArray.init(contentsOfFile: tvDataPath!)

What we want to do is map all the dictionaries for the fields into the custom model object, then add them back into original NSArray data as the new object type in the same index etc. Is there a quick/easy way to do this?


Solution

  • Why do you want to want to place your objects back into an NSArray wouldn't it be better to convert from cocoa objects into native swift collection types so you can use a struct rather than a class for your Field object?

    For example:

    struct Field
    {
        let fieldName: String
        let hasError: Bool
        let fieldType: String //Should actually most likely be an enum
    }
    
    extension Field
    {
        init?(dictionary: NSDictionary?)
        {
            guard let dictionary = dictionary, let fieldName = dictionary["FieldName"] as? String else { return nil }
            let hasError = dictionary["HasError"] as? Bool ?? false
            let fieldType = dictionary["FieldType"] as? String ?? ""
            self.init(fieldName: fieldName, hasError: hasError, fieldType: fieldType)
        }
    }
    

    Create a struct for your Field object. Have some init method that converts an NSDictionary into a Field.

    var sectionsArray = [[Field]]()
    for array in plistArray
    {
        guard let array = array as? NSArray else { continue }
        let section = array.flatMap { Field(dictionary: $0 as? NSDictionary) }
        sectionsArray.append(section)
    }
    

    Iterate over the sections in your plist. Each of those sections is an array of dictionaries. You can map each of those dictionaries to a Field so your [NSDictionary] is mapped to a [Field]. You can then add that array to another array to retain the initial structure of the data.