Search code examples
iosjsonswift2alamofireobjectmapper

Mapping to Swift Object issue showing nil using Alamofire ObjectMapper


I m new to iOS and Swift development environment. I was trying to use Alamofire for pulling JSON and AlamofireObjectMapper for Mapping the retrieved JSON collections back to my Swift Object.

The issue is I m able to fetch the JSON thru Alamofire request and the count is shown, but the mapping part seems to be showing nil. Is something I had been missed out . Appreciate help.

Model Class

import UIKit
import CoreLocation
import ObjectMapper

class BranchObjectMapper : Mappable {
    // MARK: Properties
    var id: Int?
    var cityId: Int?
    var areaId: Int?
    var name: String?
    var nameAr: String?
    var branchAddr: String?
    var branchAddr2: String?
    var location: CLLocation?

    required init?(_ map: Map) {
        mapping(map)
    }

    func mapping(map: Map) {
        id     <- map["id"]
        cityId    <- map["cityId"]
        areaId  <- map["areaId"]
        name  <- map["name"]
        nameAr  <- map["nameAr"]
        branchAddr  <- map["branchAddr"]
        branchAddr2  <- map["branchAddr2"]
        location  <- map["location"]
    }

}

Request part in viewDidLoad()

 Alamofire.request(.GET, UrlEndpoints.branchUrl()).responseArray { (response: Response<[BranchObjectMapper], NSError>) in

    self.branchList = response.result.value!

    print(self.branchList.count) // count is correct

    for branch in self.branchList {      
        print(branch.id) // prints nil
        print(branch.id) // prints nil
    }
}

Thanks in advance

The complete JSON response looks like below. Have constructed only needed ones in Model.

[{"Id":"16","areaId":"17","name":"Al Aqiq”,”cityId”:4”,”Zip":"","nameAr":"\u0637\u0631\u064a\u0642 \u0627\u0644\u0645","branchAddr":"test","branchAddr2":"test"Latitude":"24.60425","Longitude":"46.629631","cityId":"1"}]


Solution

  • i think you are missing the right documentation of ObjectMapper lib. Check this Github ObjectMapper.

    These are the types supported by the lib:

    • Int
    • Bool
    • Double
    • Float
    • String
    • RawRepresentable (Enums)
    • Array<AnyObject>
    • Dictionary<String, AnyObject>
    • Object<T: Mappable>
    • Array<T: Mappable>
    • Array<Array<T: Mappable>>
    • Set<T: Mappable>
    • Dictionary<String, T: Mappable>
    • Dictionary<String, Array<T:Mappable>>
    • Optionals of all the above
    • Implicitly Unwrapped Optionals of the above

    So, if you are trying to map an Object not in that list, the result is nil.

    In your case is var location: CLLocation?.

    If you need to map CLLocation Object, one way is to map a CustomCLLocation with all properties as follows: JSON(i don't know your Json, this is an example)

    "location":{
        "long": 43.666,
        "lat": 73.4
    }
    

    Swift: create another file "CustomCLLocation" for example like the first one but for mapping CLLocation with your Json

    var latitude: Double?
    var longitude: Double?
    
    required init?(_ map: Map) {
    mapping(map)
    
    }
    func mapping(map: Map) {
    
       longitude <- map["long"]
       latitude <- map["lat"]
    }
    

    and now, you can map an "fake" CLLocation Object: var location: CustomCLLocation?

    Then if you want a really CLLocation. just create an Simply Extension like that(add it in the CustomCLLocation file):

    extension CLLocation {
         public class func createFromCustomCLLocation(custom: CustomCLLocation) -> CLLocation {
             return self.init(custom.latitude,custom.longitude)
         }
    }
    

    Using the conversion:

    var locationCLL = CLLocation.createFromCustomCLLocation(location) // now is a CLLocation
    

    Edited: Alamofire Request

    I have the same request on my app with the last version of AlamofireObjectMapper for ios 8.0 +

    Alamofire.request(.GET, UrlEndpoints.branchUrl()).responseArray { (response: [BranchObjectMapper]?, error : ErrorType?) in
        if(error != nil) {
            print(error)
        }else{
            print("data downloaded")
    
    
            if let response = response {
                branchList(response)
                for branch in self.branchList {
                    print(branch.id)
                    print(branch.name)
                }
            }
        }
    }