Alamofire & AlamofireObjectMapper
对于掌握一门新技术而言,请求接口数据Alamofire及数据转换ObjectMapper是必不可少的。
而技术选型只是大致调研了下,然后集成到项目中,多了解多对比,后面再优化或者替换。
因为用了Alamofire ,所以数据转换ORM这块选用了更适用的 AlamofireObjectMapper
作为一个小白,仿佛一切又回到了起点,用了太久的GraphQL自动生成POJO,从不用担心ORM这块的我,终于又要手敲转换类了。
小白总要将就,先使用AlamofireObjectMapper手动生成POJO,后面有合适的再换
1.修改Podfile文件,安装相应库
执行安装命令
arch -x86_64 Pod install
2.生成转换类
// 接口返回数据结构
{
"result": {
"songs": [
{
"id": 347230,
"name": "海阔天空",
"artists": [
{
"id": 11127,
"name": "Beyond",
"picUrl": null,
"alias": [],
"albumSize": 0,
"picId": 0,
"img1v1Url": "http://p1.music.126.net/6y-UleORITEDbvrOLV0Q8A==/5639395138885805.jpg",
"img1v1": 0,
"trans": null
}
],
"duration": 326000,
"copyrightId": 7002,
"status": 0,
"alias": [],
"rtype": 0,
"ftype": 0,
"transNames": [
"Boundless Oceans, Vast Skies"
],
"mvid": 376199,
"fee": 1,
"rUrl": null,
"mark": 8192
}
],
"hasMore": true,
"songCount": 524
},
"code": 200
}
字段太多了,只选择几个典型的进行转换
//
// SongsResponse.swift
// AlamofireDemo
//
// Created by Jake on 2021/7/20.
//
import ObjectMapper
/**
请求转换基类 ( 竟然需要手写,后面要找自动生成的插件 )
map 可以跨越无用的中间类,例如 :name <- map["result.songs.1.name"]
*/
class ResultBase: Mappable {
var songs : [Songs]?
var code : Int?
// var name : String?
required init?(map: Map) {
}
func mapping(map: Map) {
songs <- map["result.songs"]
code <- map["code"]
// name <- map["result.songs.1.name"]
}
}
class Songs: ResultBase{
var id :Int?
var name : String?
var imageUrl : String?
required init?(map: Map) {
super.init(map: map)
}
override func mapping(map: Map) {
super.mapping(map: map)
id <- map["id"]
name <- map["name"]
// 默认取第一个 artists 的 img1v1Url
imageUrl <- map["artists.0.img1v1Url"]
}
}
注意:类的继承与super的调用;还有子类名要与接口返回一致。
Map的匹配规则:可跳跃用不到的属性,但是一定要注意与字段名一致。
// 跳跃举例如下
songs <- map["result.songs"]
imageUrl <- map["artists.0.img1v1Url"]
3.网络请求
Alamofire 封装了很多返回值的格式,此处用 responseObject ,原因上面说过了
override func viewDidLoad() {
super.viewDidLoad()
// 简陋的网络请求,后面要封装
_ = Alamofire.request("http://192.168.10.3:3000/search?keywords=%E6%B5%B7%E9%98%94%E5%A4%A9%E7%A9%BA")
.responseObject(completionHandler: { (response: DataResponse) in
switch response.result {
case let .success(data):
if data.songs != nil {
self.queryData = data.songs!
self.creatTableView()
}
break
case let .failure(data):
print(data.localizedDescription)
break
}
})
}
4.页面展示
5.附上简陋的VC代码,待整理。
//
// ViewController.swift
// AlamofireDemo
//
// Created by Jake on 2021/7/19.
//
import UIKit
import Alamofire
import AlamofireObjectMapper
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var tableView: UITableView!
var queryData:[Songs] = []
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
self.queryData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "cell")!
let id = self.queryData[indexPath.row].id ?? 0
let name = self.queryData[indexPath.row].name ?? ""
cell.textLabel?.text = name + "> > id \(id)"
return cell
}
func numberOfSections(in tableView: UITableView) -> Int {
self.queryData.count
}
/// 创建表格
func creatTableView() {
self.tableView = ({
let tableView = UITableView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height), style: .plain)
tableView.delegate = self
tableView.dataSource = self
tableView.separatorStyle = .none
tableView.register(UITableViewCell.classForCoder(), forCellReuseIdentifier: "cell")
self.view.addSubview(tableView)
return tableView
})()
}
override func viewDidLoad() {
super.viewDidLoad()
// 简陋的网络请求,后面要封装
_ = Alamofire.request("http://192.168.10.3:3000/search?keywords=%E6%B5%B7%E9%98%94%E5%A4%A9%E7%A9%BA")
.responseObject(completionHandler: { (response: DataResponse) in
switch response.result {
case let .success(data):
if data.songs != nil {
self.queryData = data.songs!
self.creatTableView()
}
break
case let .failure(data):
print(data.localizedDescription)
break
}
})
}
}