Swift中MVP、Moya、模型设计

Moya

在这里插入图片描述

  • MVP精简设计模式实践
  • Moya、SwiftyJSON、Kingfisher的简单使用
  • Model的设计
  • 所有核心文件都列出了
  • 模型设计的一个工具(apifox)
    在这里插入图片描述

在这里插入图片描述

1. 模拟器录屏方式

  • 为了模拟器录屏,搜了一下方法
  • 新建一个文件夹路径,cd到该文件夹
  • 终端执行指令,开始录屏
  • xcrun simctl io booted recordVideo filename.mov
  • 转gif动图:https://blog.csdn.net/my_angle2016/article/details/123993829

2.MVP框架部分

  • FMPresenter.swift
import Foundation
import Moya
import SwiftyJSON

protocol FMDelegate: NSObject { // 1.要遵守NSObject协议
    func reload()
}

class FMPresenter: NSObject {
    weak var delegate: FMDelegate? // 2. 要设置为弱引用,避免循环引用
    var dataList: [channelData] = [channelData]()
    var FMList: FMArrayList?
    
    
    func attach(_ delegate: FMDelegate) {
        self.delegate = delegate
        getData()
    }
    
    func detach() {
        self.delegate = nil
        print("detach")
    }
    
}

extension FMPresenter {
    func getData() {
        DoubanProvider.request(Douban.channel) { result in
            switch result {
            case let .success(response):
                // 1. 转为data
                let data = response.data
                
                // 2. 转为json
                let json = try! JSON(data: data)
                
                // 3. json转模型
                let list = FMArrayList.init(jsonData: json)
                self.FMList = list
                
                // 4. 刷新数据
                self.delegate?.reload()
            case let .failure(error):
                print("error\(error)")
            }
        }
    }
    
}

  • FMModel.swift
import Foundation
import SwiftyJSON

struct channelData {
    var name: String?
    var EnglishName: String?
    var channel_id: String?
    
    init(jsonData: JSON) {
        name        = jsonData["name"].stringValue
        EnglishName = jsonData["naem_en"].stringValue
        channel_id  = jsonData["channel_id"].stringValue
    }
    
}

struct FMArrayList {
    var list: [channelData] = [channelData]()
    init(jsonData: JSON) {
        let channel = jsonData["channels"].arrayValue
        for ele in channel {
            var details = channelData.init(jsonData: ele)
            details.name = ele["name"].stringValue
            details.EnglishName = ele["name_en"].stringValue
            details.channel_id = ele["channel_id"].stringValue
            list.append(details)
        }
    }
}


struct FMSong {
    var bitTitle: String?
    var songImg: String?
    var singer: String?
    var song: String?
    
    init(jsonData: JSON) {
        let json = jsonData["song"].arrayValue[0]
        
        bitTitle = json["albumtitle"].stringValue
        songImg = json["picture"].stringValue
        singer = json["artist"].stringValue
        song = json["title"].stringValue
    }
}
  • FMListViewController.swift
import UIKit
import SwiftyJSON

class FMListViewController: UIViewController {
    private let presenter = FMPresenter() // 直接定义 presenter实例
    
    private lazy var tableView: UITableView = {
        let _tabelView = UITableView(frame: CGRect(x: 0, y: 0, width: self.view.bounds.width, height: self.view.bounds.height), style: .plain)
        _tabelView.delegate = self
        _tabelView.dataSource = self
        _tabelView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
        
        return _tabelView
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        setUI()
        presenter.attach(self) // 调用方法
    }
    
    func setUI() {
        view.addSubview(tableView)
    }
    
    deinit {
        presenter.detach()
        print("deinit")
    }
}

extension FMListViewController: UITableViewDelegate, UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return presenter.FMList?.list.count ?? 0
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        cell.textLabel?.text = presenter.FMList?.list[indexPath.row].name ?? ""
        cell.detailTextLabel?.text = presenter.FMList?.list[indexPath.row].EnglishName ?? "英文名"
        
        return cell
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 80
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        
        guard let channelID = presenter.FMList?.list[indexPath.row].channel_id else {
            return
        }
        let vc = SongViewController()
        vc.channelID = channelID
        self.navigationController?.pushViewController(vc, animated: true)
        
    }
    
}

extension FMListViewController: FMDelegate {
    func reload() {
        print("FMListViewController -- reload")
        self.tableView.reloadData()
    }
}

3.Moya网络部分

  • FMProvider.swift
import Foundation
import Moya

let DoubanProvider = MoyaProvider<Douban>()

public enum Douban {
    case channel
    case playlist(String)
}

extension Douban: TargetType {
    public var baseURL: URL {
        switch self {
        case .channel:
            return URL(string: "https://www.douban.com")!
        case .playlist(_):
            return URL(string: "https://douban.fm")!
        }
    }
    
    public var path: String {
        switch self {
        case .channel:
            return "/j/app/radio/channels"
        case .playlist(_):
            return "/j/mine/playlist"
        }
    }
    
    public var method: Moya.Method {
        return .get
    }
    
    public var task: Task {
        switch self {
        case .channel:
            return .requestPlain
        case .playlist(let channel):
            var params: [String: Any] = [:]
            params["channel"] = channel
            params["type"] = "n"
            params["from"] = "mainsite"
            
            return .requestParameters(parameters: params, encoding: URLEncoding.default)
        }
       
    }
    
    public var headers: [String : String]? {
        return nil
    }

}

4. 涉及单个view内容部分

  • SongPresenter.swift
import Foundation
import SwiftyJSON

protocol SongDelegate: NSObject {
    func getCurrentData()
}

class SongPresenter: NSObject {
    weak var delegate: SongDelegate?
    var songDetail: FMSong?
    
    func attach(_ delegate: SongDelegate) {
        self.delegate = delegate
    }
    
    func dettach() {
        self.delegate = nil
        print("SongPresenter释放")
    }
}

extension SongPresenter {
    func getSongData(channelID: String) {
        DoubanProvider.request(.playlist(channelID)) { result in
            switch result {
            case let .success(response):
                let data = response.data
                let json = try! JSON(data: data)
                let song = FMSong.init(jsonData: json)
                self.songDetail = song
                print("success")
                self.delegate?.getCurrentData()
            case let .failure(error):
                print("errror\(error)")
            }
        }
        
    }
}
  • SongViewController.swift
import UIKit
import Kingfisher

class SongViewController: UIViewController {

    @IBOutlet weak var bigTitle: UILabel!
    @IBOutlet weak var songImageView: UIImageView!
    @IBOutlet weak var songTitle: UILabel!
    @IBOutlet weak var artist: UILabel!
    public var channelID: String?
    
    private let presenter = SongPresenter()
    
    override func viewDidLoad() {
        super.viewDidLoad()

        presenter.attach(self)

        guard let channelID = channelID else {
            return
        }
        presenter.getSongData(channelID: channelID)
    }
}

extension SongViewController: SongDelegate {
    func getCurrentData() {
        if let songDetail = presenter.songDetail {
            bigTitle.text = songDetail.bitTitle
            songImageView.kf.setImage(with: URL(string: songDetail.songImg ?? ""))
            songTitle.text = songDetail.song
            artist.text = songDetail.singer
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值