evermeer / EVReflection

Reflection based (Dictionary, CKRecord, NSManagedObject, Realm, JSON and XML) object mapping with extensions for Alamofire and Moya with RxSwift or ReactiveSwift
Other
965 stars 119 forks source link

Still having an retrieving objects from a initialized nested arrays. #212

Open noobs2ninjas opened 7 years ago

noobs2ninjas commented 7 years ago

I tried to reply to the old issue I had which had already been closed. I wish I hadnt been busy so I could have tested and replied to weather or not the issue had been fixed.

So, initializing a nested array has never really been initializing.

Specifically its when I try to access the data I get "fatal error: NSArray element failed to match the Swift Array Element type" on something like. let dataModel = data[0][0][0]

Inspecting the data has on crash..the first nested array looks fine. Its the arrays inside that, that remain "_NSDictionaryM *".

In otherwords I see [0] = ([[App.MyDataModel])) -> [0] = ([App.MyDataModel]) -> [0] = (_NSDictionaryM *)

evermeer commented 7 years ago

I will give it another look...

evermeer commented 6 years ago

On request here the workaround: You have to create a propertyConverter for that property. the decodeConverter will be called with an [[NSDictionary]]. In version 5.6.0 I added helper functions to convert it to [[YourObject]]. The code (from the unit tests) will look something like this:

class A81b: EVObject {
    var array: [[A81]] = [[]]

    override func propertyConverters() -> [(key: String, decodeConverter: ((Any?) -> ()), encodeConverter: (() -> Any?))] {
        return [(key: "array",
            decodeConverter: {
                self.array = ($0 as? NSArray)?.nestedArrayMap { A81(dictionary: $0) } ?? [[]]
        }, encodeConverter: { return self.array })]
    }
}

class A81c: EVObject {
    var array: [[[A81]]] = [[[]]]

    override func propertyConverters() -> [(key: String, decodeConverter: ((Any?) -> ()), encodeConverter: (() -> Any?))] {
        return [(key: "array",
                 decodeConverter: {
                    self.array = ($0 as? NSArray)?.doubleNestedArrayMap { A81(dictionary: $0) } ?? [[]]
        }, encodeConverter: { return self.array })]
    }
}

class A81d: EVObject {
    // Skipping the triple, quadruple, quintuple nestedArrayMap and go strait to the sextuple
    // You should not want something like this
    var array: [[[[[[[A81]]]]]]] = [[[[[[[]]]]]]]

    override func propertyConverters() -> [(key: String, decodeConverter: ((Any?) -> ()), encodeConverter: (() -> Any?))] {
        return [(key: "array",
                 decodeConverter: {
                    self.array = ($0 as? NSArray)?.sextupleNestedArrayMap { A81(dictionary: $0) } ?? [[[[[[]]]]]]
        }, encodeConverter: { return self.array })]
    }
}

class A81: EVObject {
    var openId: String = ""
}
Erhannis commented 5 years ago

Fyi, this fails for eg [[Double]], because Double doesn't get deserialized to an NSDictionary. Until something's fixed/changed, y'all, you can use some form of the following in the decodeConverter, taken from the definition nestedArrayMap:

                self.array = (($0 as? NSArray)?.map {
                    (($0 as? NSArray)?.map {
                        $0 as? Double ?? 0.0
                        }) ?? []
                })