alamofire object mapper .. why print my project name? - swift

Screenshot Here
Note: This is my first swift file
override func viewDidLoad() {
super.viewDidLoad()
let encodingURL = url.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
Alamofire.request(encodingURL!).responseObject { (response: DataResponse<channel>) in
let MovieResponse = response.result.value
print("결과: \(MovieResponse?.channel?.result as AnyObject)")
print("타이틀: \(MovieResponse?.channel?.title as AnyObject)")
print("토탈카운트: \(MovieResponse?.channel?.totalCount as AnyObject)")
print("전체:\(MovieResponse?.channel as AnyObject)")
print("아이템: \(MovieResponse?.channel?.item as AnyObject)")
print("배우:\(MovieResponse?.channel?.item.first?.actor as AnyObject)")
}
}
Note: second swift file
import Foundation
import ObjectMapper
class channel : Mappable {
var channel : channelComponents?
required init?(map: Map){ }
func mapping(map: Map) {
self.channel <- map["channel"]
}
}
class channelComponents : Mappable {
var totalCount : Int?
var result : Int?
var title : String?
var item : [item]
required init?(map: Map){
item = []
}
func mapping(map: Map) {
self.totalCount <- map["totalCount"]
self.result <- map["result"]
self.title <- map["q"]
self.item <- map["item"]
}
}
class item : Mappable {
var actor : [Actor]
required init?(map: Map) {
actor = []
}
func mapping(map: Map) {
self.actor <- map["actor"]
}
}
class Actor : Mappable {
var content : String?
var link : String?
required init?(map: Map) { }
func mapping(map: Map) {
self.content <- map["content"]
self.link <- (map["link"])
}
}
input
print("아이템: \(MovieResponse?.channel?.item as AnyObject)")
print("배우:\(MovieResponse?.channel?.item.first?.actor as AnyObject)")
output
아이템: (
"Movie_D.item"
)
배우:(
"Movie_D.Actor",
"Movie_D.Actor",
"Movie_D.Actor",
"Movie_D.Actor",
"Movie_D.Actor",
"Movie_D.Actor",
"Movie_D.Actor"
)
Movie_D is my project name.
I want to know the actor's name, but there is just my project name. (the count is right)

You should cast the actor property to a String (assuming it is one) to properly display the actor's name in your print statement.
print("배우:\(String(describing: MovieResponse?.channel?.item.first?.actor))")

Related

Generic DataResponse with Alamofire and ObjectMapper

I want to create a custom class for Alamofire so I will be able to call the request over and over again in various classes. In order to do that I need to pass the model class that extends to Mappable in DataResponse. But I got many errors.
This is my current code in the custom class:
func callAPI<T: Mappable>(response: T){
Alamofire.request(url!, method: .post, parameters: nil, encoding: JSONEncoding.default, headers: nil).responseObject { (response: DataResponse<T>) in
let result = response.result.value as! BaseData
}
}
And this is my code when i call the method:
func data() {
let manager = ManagerData(url: url)
manager.callAPI(response: Model.self)
}
This is my Model class:
class Model: BaseData {
var point: String?
var list: [Voucher]?
override func mapping(map: Map) {
super.mapping(map: map)
totalPoint <- map["TOTAL_POINT"]
list <- map["VOUCHER"]
}
}
class BaseData: Mappable {
var status: String?
var message: String?
required init() {
}
required init?(map: Map) {
}
func mapping(map: Map) {
status <- map["STATUS"]
message <- map["MESSAGE"]
}
}
On manager.callAPI(response: Model.self) error is Argument type Model.Type does not conform to expected type Mappable.
Any suggestion how to do it?

Using Object Mapping with Kinvey

I have an array of objects I'm trying to get out of one of my collections. I've followed along using their docs and also some Googling and I believe I'm close to the solution, however not close enough. Here's what I have:
class Clothing: Entity {
var categories: [Category]!
var gender: String!
override class func collectionName() -> String {
//return the name of the backend collection corresponding to this entity
return "categories"
}
override func propertyMapping(_ map: Map) {
super.propertyMapping(map)
categories <- map["clothing"]
gender <- map["gender"]
}
}
class Category: NSObject, Mappable{
var title: String?
var image: String?
convenience required init?(map: Map) {
self.init()
}
func mapping(map: Map) {
title <- map["category"]
image <- map["image"]
}
}
I'm able to get the right gender, but the array of categories doesn't seem to get mapped to the Category object. Any thoughts?
your model actually have one issue, as you can see at https://devcenter.kinvey.com/ios/guides/datastore#Model you should use let categories = List<Category>() instead of var categories: [Category]!. Here's the model that and test and worked:
import Kinvey
class Clothing: Entity {
let categories = List<Category>()
var gender: String!
override class func collectionName() -> String {
//return the name of the backend collection corresponding to this entity
return "clothing"
}
override func propertyMapping(_ map: Map) {
super.propertyMapping(map)
categories <- ("categories", map["categories"])
gender <- ("gender", map["gender"])
}
}
class Category: Object, Mappable{
var title: String?
var image: String?
convenience required init?(map: Map) {
self.init()
}
func mapping(map: Map) {
title <- ("category", map["category"])
image <- ("image", map["image"])
}
}
and here's a sample code how to save a new Clothing object
let casualCategory = Category()
casualCategory.title = "Casual"
let shirtCategory = Category()
shirtCategory.title = "Shirt"
let clothing = Clothing()
clothing.gender = "male"
clothing.categories.append(shirtCategory)
clothing.categories.append(casualCategory)
dataStore.save(clothing) { (result: Result<Clothing, Swift.Error>) in
switch result {
case .success(let clothing):
print(clothing)
case .failure(let error):
print(error)
}
}

Using AlamofireObjectMapper Error

I'm using AlamofireObjectMapper to map object from JSON,But no response retrieved.Here is my code
let articleAPI = "https://news-at.zhihu.com/api/4/news/latest"
Alamofire.request(articleAPI).responseObject {(response: DataResponse<ArticleResponse>) in
let contents = response.result.value
print((contents?.stories?[0].title)!)
the ArticleResponse object looks like the following:
import ObjectMapper
class ArticleResponse: Mappable {
var date: String?
var stories: [ArticleDetailResponse]?
var top_stories: [TopStoriesResponse]?
required init?(map: Map) {
}
func mapping(map: Map) {
date <- map["date"]
stories <- map["stories"]
top_stories <- map["top_stories"]
}
}
class ArticleDetailResponse: Mappable {
var images: [String]?
var type: Int?
var id: Int?
var ga_prefix: String?
var title: String?
var multipic: Bool?
required init?(map: Map) {
}
func mapping(map: Map) {
images <- map["images"]
type <- map["type"]
id <- map["id"]
ga_prefix <- map["ga_prefix"]
title <- map["title"]
multipic <- map["multipic"]
}
}
class TopStoriesResponse: Mappable {
var image: String?
var type: Int?
var id: Int?
var ga_prefix: String?
var title: String?
required init?(map: Map) {
}
func mapping(map: Map) {
image <- map["image"]
type <- map["type"]
id <- map["id"]
ga_prefix <- map["ga_prefix"]
title <- map["title"]
}
}
I am doing this according the AlamofireObjectMapper usage document.In addition to that,Is there anything else have to implement?

Generic function to map JSON objects with ObjectMapper

I have a generic function:
func toObjectMapper<T: Mappable>(mapper: T, success: (result: Mappable) -> Void, failure: (error: NSError) -> Void){
let alomofireApiRequest = AlamofireApiRequest(apiRequest: self)
Alamofire.request(alomofireApiRequest)
.responseObject { (response: Response<T, NSError>) in
guard let value = response.result.value else {
failure(error: response.result.error!)
return
}
success(result: value)
}
}
And I want to call it like this:
public func login(login: String, password: String) -> UserResponse {
let params = ["email":login, "password":password]
let request = ApiRequest(method: .POST, path: "login", parameters: params)
request.toObjectMapper(UserResponse.self, success: { result in
print(result)
}, failure: { error in
print(error.description)
})
}
But I always get this error:
Cannot invoke 'toObjectMapper' with an argument list of type '(UserResponse.Type, success: (result: Mappable) -> Void, failure: (error: NSError) -> Void)'
This is my userResponse:
import Foundation
import ObjectMapper
import RealmSwift
public class UserResponse: Object, Mappable {
dynamic var id = 0
dynamic var name = ""
dynamic var address = ""
dynamic var zipcode = ""
dynamic var city = ""
dynamic var country = ""
dynamic var vat = ""
dynamic var email = ""
dynamic var created_at = NSDate()
dynamic var updated_at = NSDate()
override public static func primaryKey() -> String? {
return "id"
}
//Impl. of Mappable protocol
required convenience public init?(_ map: Map) {
self.init()
}
public func mapping(map: Map) {
id <- map["id"]
name <- map["name"]
address <- map["address"]
zipcode <- map["zipcode"]
city <- map["city"]
country <- map["country"]
vat <- map["vat"]
email <- map["email"]
created_at <- map["created_at"]
updated_at <- map["updated_at"]
}
}
Any help ?
I think the problem is that you are trying to use UserResponse as an instantiated object but using UserResponse.self is only the class type.
A solution is to make UserResonse a singleton (or just instantiate an instance before passing it to 'toObjectMapper' as an argument)
I don't know if this code specifically will work but it's along these lines:-
public class UserResponse: Object, Mappable {
dynamic var id = 0
dynamic var name = ""
dynamic var address = ""
dynamic var zipcode = ""
dynamic var city = ""
dynamic var country = ""
dynamic var vat = ""
dynamic var email = ""
dynamic var created_at = NSDate()
dynamic var updated_at = NSDate()
static let shared = UserResponse() //singleton instantiation
override public static func primaryKey() -> String? {
return "id"
}
//Impl. of Mappable protocol
required convenience public init?(_ map: Map) {
self.init()
}
public func mapping(map: Map) {
id <- map["id"]
name <- map["name"]
address <- map["address"]
zipcode <- map["zipcode"]
city <- map["city"]
country <- map["country"]
vat <- map["vat"]
email <- map["email"]
created_at <- map["created_at"]
updated_at <- map["updated_at"]
}
}
and then in your function call
public func login(login: String, password: String) -> UserResponse {
let params = ["email":login, "password":password]
let request = ApiRequest(method: .POST, path: "login", parameters: params)
request.toObjectMapper(UserResponse.shared, success: { result in
print(result)
}, failure: { error in
print(error.description)
})
}

Using Alamofire and Objectmapper the integer value always zero

I am using Alamofire with ObjectMapper and my model class is like that
class Category: Object, Mappable {
dynamic var id: Int = 0
dynamic var name = ""
dynamic var thumbnail = ""
var children = List<Category>()
override static func primaryKey() -> String? {
return "id"
}
required convenience init?(_ map: Map) {
self.init()
}
func mapping(map: Map) {
id <- map["id"]
name <- map["name"]
thumbnail <- map["thumbnail"]
children <- map["children"]
}
}
and I am using Alamofire like that
Alamofire.request(.GET, url).responseArray { (response: Response<[Category], NSError>) in
let categories = response.result.value
if let categories = categories {
for category in categories {
print(category.id)
print(category.name)
}
}
}
the id is always zero, I don't know why?
I fixed it by adding transformation in the mapping function in model class like that
id <- (map["id"], TransformOf<Int, String>(fromJSON: { Int($0!) }, toJSON: { $0.map { String($0) } }))
thanks to #BobWakefield
Does the "id" field exist in the JSON file? If it does not, your initial value of zero will remain. Is the value in quotes in the JSON file? If it is, then it's a string. I don't know if ObjectMapper will convert it to Int.
Moved my comment to an answer.