SwiftSwift开发学习

iOS & 网络请求Alamofire及数据转换ObjectMa

2021-07-21  本文已影响0人  南窗云

Alamofire & AlamofireObjectMapper

对于掌握一门新技术而言,请求接口数据Alamofire及数据转换ObjectMapper是必不可少的。

而技术选型只是大致调研了下,然后集成到项目中,多了解多对比,后面再优化或者替换。

因为用了Alamofire ,所以数据转换ORM这块选用了更适用的 AlamofireObjectMapper

作为一个小白,仿佛一切又回到了起点,用了太久的GraphQL自动生成POJO,从不用担心ORM这块的我,终于又要手敲转换类了。

小白总要将就,先使用AlamofireObjectMapper手动生成POJO,后面有合适的再换

1.修改Podfile文件,安装相应库

Pod 增加配置

执行安装命令

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<ResultBase>) 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.页面展示

Table View 展示列表数据

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<ResultBase>) 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
                }
            })
    }
}

うずまき ナルト
上一篇下一篇

猜你喜欢

热点阅读