使用 AlamofireObjectMapper 映射模型 - swift
Posted
技术标签:
【中文标题】使用 AlamofireObjectMapper 映射模型 - swift【英文标题】:using AlamofireObjectMapper for mapping model - swift 【发布时间】:2017-12-06 18:06:06 【问题描述】:我正在使用AlamofierObjectMapper 将来自服务器的 json 映射到我的模型。从服务器接收到的json是这样的:
[
"Title": "string",
"ImageUrl": "string",
"Url": "string",
"UrlType": "none"
]
我用于映射的类是:
class Banner: Mappable
var Title: String?
var ImageUrl: String?
var Url: String?
var UrlType: String?
required init?(map: Map)
// Mappable
func mapping(map: Map)
Title <- map["Title"]
ImageUrl <- map["ImageUrl"]
Url <- map["Url"]
UrlType <- map["UrlType"]
我的类不是数组,但我的 json 是数组。我怎样才能在没有这样的情况下获取数据:
"result" : [
"Title": "string",
"ImageUrl": "string",
"Url": "string",
"UrlType": "none"
]
编辑:
我的要求:
Alamofire.request(url, method: .get)
.responseObject (response: DataResponse<Banner>) in
【问题讨论】:
【参考方案1】:很简单,只需要使用方法responseArray:
Alamofire.request(url, method: .get).responseArray (response: DataResponse<[Banner]>) in
let bannersArray = response.result.value
if let bannersArray = bannersArray
for banner in bannersArray
// Do anything with it
【讨论】:
你的意思是我不使用我的请求,而是使用 Alamofire 请求并使用 mapArray 传递 json? 对不起,一开始没有正确理解你,我已经更新了我的答案【参考方案2】:1) Model Class One--------------
-----------------------------------------
-----------------------------------------
import Foundation
import ObjectMapper
class MainData : NSObject, Mappable
var page : Int?
var per_page : Int?
var total : Int?
var total_pages : Int?
var data : [Data]?
override init()
required init?(map: Map)
func mapping(map: Map)
page <- map["page"]
per_page <- map["per_page"]
total <- map["total"]
total_pages <- map["total_pages"]
data <- map["data"]
2) Model Class Two--------------
-----------------------------------------
-----------------------------------------
import Foundation
import ObjectMapper
class Data : NSObject, Mappable
var id : Int?
var name : String?
var year : Int?
var color : String?
var pantone_value : String?
override init()
required init?(map: Map)
func mapping(map: Map)
id <- map["id"]
name <- map["name"]
year <- map["year"]
color <- map["color"]
pantone_value <- map["pantone_value"]
3) ViewController--------------
-----------------------------------------
-----------------------------------------
import UIKit
class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate
@IBOutlet weak var myTableview: UITableView!
@IBAction func btnNewFeature(_ sender: UIButton)
let vc3 = self.storyboard? .instantiateViewController(withIdentifier: "TheardViewController") as! TheardViewController
self.navigationController? .pushViewController(vc3, animated: true)
var DictData = MainData()
var ArrayData = [Data]()
override func viewDidLoad()
super.viewDidLoad()
self.myTableview.layer.cornerRadius = 10
getData()
// Do any additional setup after loading the view, typically from a nib.
func getData()
let dict = [
"name":"shital",
"rollno":"1"
]
APIManager.sharedInstance.getListOfFeatures(parms: dict, onsuccess: (responsedata, anystring) in
self.DictData = responsedata
self.ArrayData = self.DictData.data!
print(self.DictData.page)
for item in self.ArrayData
print(item.color)
print(item.id)
print(item.name)
self.myTableview.reloadData()
) (error, error1) in
print(error,error1)
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
print(self.ArrayData.count)
return self.ArrayData.count
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
var cell = myTableview.dequeueReusableCell(withIdentifier: "TableViewCell") as! TableViewCell
let element = self.ArrayData[indexPath.row]
let id = "\(element.id!)"
cell.txtNoofvotes.text = id
cell.lblFeatureTitle.text = element.name
cell.lblRequestedName.text = element.name
cell.txtViewFeatureDesc.text = element.pantone_value
cell.lblRequestedDate.text = "\(element.year!)"
if (element.id == 1)
cell.btnVote.setTitle("Voted", for: .normal)
cell.btnVote.isEnabled = false
else
cell.btnVote.setTitle("Vote", for: .normal)
cell.btnVote.tag = indexPath.row
cell.btnVote.addTarget(self, action: #selector(voteButtonPressed(sender:)), for: .touchUpInside)
return cell
@objc func voteButtonPressed(sender:UIButton)
let arrdata = self.ArrayData[sender.tag]
self.myTableview.reloadData()
let dict = [
"commandType":"registervote",
"requestedId":"10"
]
APIManager.sharedInstance.getListOfFeatures(parms: dict, onsuccess: (responsedata, anymessage) in
print(responsedata,anymessage)
) (error1, error2) in
print(error1,error2)
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
let vc2 = self.storyboard? .instantiateViewController(withIdentifier: "SecendViewController") as! SecendViewController
let element = self.ArrayData[indexPath.row]
vc2.arrpass = [element]
self.navigationController? .pushViewController(vc2, animated: true)
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
return 300
4) SecendViewController--------------
-----------------------------------------
-----------------------------------------
import UIKit
class SecendViewController: UIViewController
var arrpass = [Data]()
@IBOutlet weak var uiMainView: UIView!
@IBOutlet weak var lblFeatureTitile: UILabel!
override func viewDidLoad()
super.viewDidLoad()
let item = self.arrpass[0]
self.lblFeatureTitile.text = item.name
self.uiMainView.layer.cornerRadius = 10
// Do any additional setup after loading the view.
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
5) TheardViewController--------------
-----------------------------------------
-----------------------------------------
import UIKit
class TheardViewController: UIViewController
@IBOutlet weak var lblUseCase: UILabel!
@IBOutlet weak var txtUsecase: UITextView!
@IBOutlet weak var txtFeatureDescription: UITextView!
@IBOutlet weak var txtName: UITextField!
@IBOutlet weak var txtFeatureTitile: UITextField!
@IBOutlet weak var txtEmail: UITextField!
let imgselected = UIImage.init(named: "Selected")
let imgunselected = UIImage.init(named: "Unselected")
@IBOutlet weak var btnLow: UIButton!
@IBOutlet weak var btnMedium: UIButton!
@IBOutlet weak var btnHigh: UIButton!
var strresult = ""
override func viewDidLoad()
super.viewDidLoad()
self.btnMedium.setImage(imgunselected, for: .normal)
self.btnHigh.setImage(imgunselected, for: .normal)
self.btnLow.setImage(imgunselected, for: .normal)
// Do any additional setup after loading the view.
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
@IBAction func btnLowPressed(_ sender: UIButton)
self.strresult = "L"
self.btnLow.setImage(imgselected, for: .normal)
self.btnHigh.setImage(imgunselected, for: .normal)
self.btnMedium.setImage(imgunselected, for: .normal)
self.lblUseCase.text = "Use Case"
@IBAction func btnMediumPressed(_ sender: UIButton)
self.strresult = "M"
self.btnMedium.setImage(imgselected, for: .normal)
self.btnHigh.setImage(imgunselected, for: .normal)
self.btnLow.setImage(imgunselected, for: .normal)
self.lblUseCase.text = "Use Case *"
@IBAction func btnHighPressed(_ sender: UIButton)
self.strresult = "H"
self.btnHigh.setImage(imgselected, for: .normal)
self.btnLow.setImage(imgunselected, for: .normal)
self.btnMedium.setImage(imgunselected, for: .normal)
self.lblUseCase.text = "Use Case *"
@IBAction func btnSendReQuest(_ sender: UIButton)
var strname = self.txtName.text!
var stremail = self.txtEmail.text!
var strtitile = self.txtFeatureTitile.text!
var strUsecase = self.txtUsecase.text!
if strname.count <= 0
let alert = UIAlertController(title: "Warning", message: "Please Enter Name", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil))
self.present(alert, animated: true, completion: nil)
else if stremail.count <= 0
let alert = UIAlertController(title: "Warning", message: "Please Enter Email", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
self.present(alert, animated: true, completion: nil)
else if strtitile.count <= 0
let alert = UIAlertController(title: "Warning", message: "Please Enter Title", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
self.present(alert, animated: true, completion: nil)
else if strresult.count <= 0
let alert = UIAlertController(title: "Warning", message: "Please Set Priority", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
self.present(alert, animated: true, completion: nil)
else if (((strresult == "H") && (self.txtUsecase.text.count <= 0)) || (strresult == "M") && (self.txtUsecase.text.count <= 0))
let alert = UIAlertController(title: "Warning", message: "Please enter uese case.", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
self.present(alert, animated: true, completion: nil)
else
let alert = UIAlertController(title: "Success", message: "All Ok", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
self.present(alert, animated: true, completion: nil)
6) APIManager--------------
-----------------------------------------
-----------------------------------------
import UIKit
import ObjectMapper
import Alamofire
class APIManager: NSObject
static let sharedInstance = APIManager()
func getListOfFeatures(parms:[String:Any], onsuccess:@escaping(MainData,String) -> Void, onfailure:@escaping(String,String) ->Void)
let url = URL.init(string: "https://reqres.in/api/unknown")
let headres: HTTPHeaders = ["content-type":"application/json"]
Alamofire.request(url!, method: .get, parameters: parms, encoding: JSONEncoding.default, headers: headres).responseJSON
response in
switch response.result
case .success:
let string = NSString(data: response.data!, encoding: String.Encoding.utf8.rawValue)
print("string:\(String(describing: string))")
do
let jsonResponse = try JSONSerialization.jsonObject(with: response.data!, options: []) as! [String:AnyObject]
let userDetails = Mapper<MainData>() .map(JSON: jsonResponse)
if jsonResponse != nil
onsuccess(userDetails!,"success")
else
onfailure((response.error?.localizedDescription)!,"fail")
catch let parsingError
print("error",parsingError)
onfailure((response.error?.localizedDescription)!,"fail")
break
case .failure(let error):
print(error)
onfailure((response.error?.localizedDescription)!,"fail")
【讨论】:
【参考方案3】:1) Model Class One--------------
-----------------------------------------
-----------------------------------------
import Foundation
import ObjectMapper
class MainData : NSObject, Mappable
var page : Int?
var per_page : Int?
var total : Int?
var total_pages : Int?
var data : [Data]?
override init()
required init?(map: Map)
func mapping(map: Map)
page <- map["page"]
per_page <- map["per_page"]
total <- map["total"]
total_pages <- map["total_pages"]
data <- map["data"]
2) Model Class Two--------------
-----------------------------------------
-----------------------------------------
import Foundation
import ObjectMapper
class Data : NSObject, Mappable
var id : Int?
var name : String?
var year : Int?
var color : String?
var pantone_value : String?
override init()
required init?(map: Map)
func mapping(map: Map)
id <- map["id"]
name <- map["name"]
year <- map["year"]
color <- map["color"]
pantone_value <- map["pantone_value"]
3) ViewController--------------
-----------------------------------------
-----------------------------------------
import UIKit
class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate
@IBOutlet weak var myTableview: UITableView!
@IBAction func btnNewFeature(_ sender: UIButton)
let vc3 = self.storyboard? .instantiateViewController(withIdentifier: "TheardViewController") as! TheardViewController
self.navigationController? .pushViewController(vc3, animated: true)
var DictData = MainData()
var ArrayData = [Data]()
override func viewDidLoad()
super.viewDidLoad()
self.myTableview.layer.cornerRadius = 10
getData()
// Do any additional setup after loading the view, typically from a nib.
func getData()
let dict = [
"name":"shital",
"rollno":"1"
]
APIManager.sharedInstance.getListOfFeatures(parms: dict, onsuccess: (responsedata, anystring) in
self.DictData = responsedata
self.ArrayData = self.DictData.data!
print(self.DictData.page)
for item in self.ArrayData
print(item.color)
print(item.id)
print(item.name)
self.myTableview.reloadData()
) (error, error1) in
print(error,error1)
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
print(self.ArrayData.count)
return self.ArrayData.count
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
var cell = myTableview.dequeueReusableCell(withIdentifier: "TableViewCell") as! TableViewCell
let element = self.ArrayData[indexPath.row]
let id = "\(element.id!)"
cell.txtNoofvotes.text = id
cell.lblFeatureTitle.text = element.name
cell.lblRequestedName.text = element.name
cell.txtViewFeatureDesc.text = element.pantone_value
cell.lblRequestedDate.text = "\(element.year!)"
if (element.id == 1)
cell.btnVote.setTitle("Voted", for: .normal)
cell.btnVote.isEnabled = false
else
cell.btnVote.setTitle("Vote", for: .normal)
cell.btnVote.tag = indexPath.row
cell.btnVote.addTarget(self, action: #selector(voteButtonPressed(sender:)), for: .touchUpInside)
return cell
@objc func voteButtonPressed(sender:UIButton)
let arrdata = self.ArrayData[sender.tag]
self.myTableview.reloadData()
let dict = [
"commandType":"registervote",
"requestedId":"10"
]
APIManager.sharedInstance.getListOfFeatures(parms: dict, onsuccess: (responsedata, anymessage) in
print(responsedata,anymessage)
) (error1, error2) in
print(error1,error2)
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
let vc2 = self.storyboard? .instantiateViewController(withIdentifier: "SecendViewController") as! SecendViewController
let element = self.ArrayData[indexPath.row]
vc2.arrpass = [element]
self.navigationController? .pushViewController(vc2, animated: true)
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
return 300
4) SecendViewController--------------
-----------------------------------------
-----------------------------------------
import UIKit
class SecendViewController: UIViewController
var arrpass = [Data]()
@IBOutlet weak var uiMainView: UIView!
@IBOutlet weak var lblFeatureTitile: UILabel!
override func viewDidLoad()
super.viewDidLoad()
let item = self.arrpass[0]
self.lblFeatureTitile.text = item.name
self.uiMainView.layer.cornerRadius = 10
// Do any additional setup after loading the view.
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
5) TheardViewController--------------
-----------------------------------------
-----------------------------------------
import UIKit
class TheardViewController: UIViewController
@IBOutlet weak var lblUseCase: UILabel!
@IBOutlet weak var txtUsecase: UITextView!
@IBOutlet weak var txtFeatureDescription: UITextView!
@IBOutlet weak var txtName: UITextField!
@IBOutlet weak var txtFeatureTitile: UITextField!
@IBOutlet weak var txtEmail: UITextField!
let imgselected = UIImage.init(named: "Selected")
let imgunselected = UIImage.init(named: "Unselected")
@IBOutlet weak var btnLow: UIButton!
@IBOutlet weak var btnMedium: UIButton!
@IBOutlet weak var btnHigh: UIButton!
var strresult = ""
override func viewDidLoad()
super.viewDidLoad()
self.btnMedium.setImage(imgunselected, for: .normal)
self.btnHigh.setImage(imgunselected, for: .normal)
self.btnLow.setImage(imgunselected, for: .normal)
// Do any additional setup after loading the view.
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
@IBAction func btnLowPressed(_ sender: UIButton)
self.strresult = "L"
self.btnLow.setImage(imgselected, for: .normal)
self.btnHigh.setImage(imgunselected, for: .normal)
self.btnMedium.setImage(imgunselected, for: .normal)
self.lblUseCase.text = "Use Case"
@IBAction func btnMediumPressed(_ sender: UIButton)
self.strresult = "M"
self.btnMedium.setImage(imgselected, for: .normal)
self.btnHigh.setImage(imgunselected, for: .normal)
self.btnLow.setImage(imgunselected, for: .normal)
self.lblUseCase.text = "Use Case *"
@IBAction func btnHighPressed(_ sender: UIButton)
self.strresult = "H"
self.btnHigh.setImage(imgselected, for: .normal)
self.btnLow.setImage(imgunselected, for: .normal)
self.btnMedium.setImage(imgunselected, for: .normal)
self.lblUseCase.text = "Use Case *"
@IBAction func btnSendReQuest(_ sender: UIButton)
var strname = self.txtName.text!
var stremail = self.txtEmail.text!
var strtitile = self.txtFeatureTitile.text!
var strUsecase = self.txtUsecase.text!
if strname.count <= 0
let alert = UIAlertController(title: "Warning", message: "Please Enter Name", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil))
self.present(alert, animated: true, completion: nil)
else if stremail.count <= 0
let alert = UIAlertController(title: "Warning", message: "Please Enter Email", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
self.present(alert, animated: true, completion: nil)
else if strtitile.count <= 0
let alert = UIAlertController(title: "Warning", message: "Please Enter Title", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
self.present(alert, animated: true, completion: nil)
else if strresult.count <= 0
let alert = UIAlertController(title: "Warning", message: "Please Set Priority", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
self.present(alert, animated: true, completion: nil)
else if (((strresult == "H") && (self.txtUsecase.text.count <= 0)) || (strresult == "M") && (self.txtUsecase.text.count <= 0))
let alert = UIAlertController(title: "Warning", message: "Please enter uese case.", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
self.present(alert, animated: true, completion: nil)
else
let alert = UIAlertController(title: "Success", message: "All Ok", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
self.present(alert, animated: true, completion: nil)
6) APIManager--------------
-----------------------------------------
-----------------------------------------
import UIKit
import ObjectMapper
import Alamofire
class APIManager: NSObject
static let sharedInstance = APIManager()
func getListOfFeatures(parms:[String:Any], onsuccess:@escaping(MainData,String) -> Void, onfailure:@escaping(String,String) ->Void)
let url = URL.init(string: "https://reqres.in/api/unknown")
let headres: HTTPHeaders = ["content-type":"application/json"]
Alamofire.request(url!, method: .get, parameters: parms, encoding: JSONEncoding.default, headers: headres).responseJSON
response in
switch response.result
case .success:
let string = NSString(data: response.data!, encoding: String.Encoding.utf8.rawValue)
print("string:\(String(describing: string))")
do
let jsonResponse = try JSONSerialization.jsonObject(with: response.data!, options: []) as! [String:AnyObject]
let userDetails = Mapper<MainData>() .map(JSON: jsonResponse)
if jsonResponse != nil
onsuccess(userDetails!,"success")
else
onfailure((response.error?.localizedDescription)!,"fail")
catch let parsingError
print("error",parsingError)
onfailure((response.error?.localizedDescription)!,"fail")
break
case .failure(let error):
print(error)
onfailure((response.error?.localizedDescription)!,"fail")
【讨论】:
以上是关于使用 AlamofireObjectMapper 映射模型 - swift的主要内容,如果未能解决你的问题,请参考以下文章
使用 AlamofireObjectMapper 映射模型 - swift
AlamofireObjectMapper,嵌套的 JSON 结构在序列化时总是 nil
在 AlamofireObjectMapper 响应中映射 allHeaderFields