• RxSwift + Moya + ObjectMapper


    https://www.jianshu.com/p/173915b943af

    use_frameworks!
     
    target 'RXDemo' do
        pod 'RxSwift'
        pod 'RxCocoa'
        pod 'Moya-ObjectMapper/RxSwift'
        pod 'Moya/RxSwift'
    end
    
    import Moya
    
    let DouBanProvider = MoyaProvider<DouBanAPI>()
    
    public enum DouBanAPI {
        case channels  //获取频道列表
        case playlist(String) //获取歌曲
    }
    
    extension DouBanAPI: TargetType {
     
        public var baseURL: URL {
            switch self {
            case .channels:
                return URL(string: "https://www.douban.com")!
            case .playlist(_):
                return URL(string: "https://douban.fm")!
            }
        }
        
        public var path: String {
            switch self {
            case .channels:
                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 .playlist(let channel):
                var params: [String: Any] = [:]
                params["channel"] = channel
                params["type"] = "n"
                params["from"] = "mainsite"
                return .requestParameters(parameters: params,
                                          encoding: URLEncoding.default)
            default:
                return .requestPlain
            }
        }
        
        public var validate: Bool {
            return false
        }
        
        public var sampleData: Data {
            return "{}".data(using: String.Encoding.utf8)!
        }
        
        public var headers: [String: String]? {
            return nil
        }
    }
    
    import UIKit
    import ObjectMapper
    
    //豆瓣接口模型
    struct Douban: Mappable {
        //频道列表
        var channels: [Channel]?
        
        init?(map: Map) { }
        
        // Mappable
        mutating func mapping(map: Map) {
            channels <- map["channels"]
        }
    }
    
    //频道模型
    struct Channel: Mappable {
        var name: String?
        var nameEn:String?
        var channelId: String?
        var seqId: Int?
        var abbrEn: String?
        
        init?(map: Map) { }
        
        // Mappable
        mutating func mapping(map: Map) {
            name <- map["name"]
            nameEn <- map["name_en"]
            channelId <- map["channel_id"]
            seqId <- map["seq_id"]
            abbrEn <- map["abbr_en"]
        }
    }
    
    //歌曲列表模型
    struct Playlist: Mappable {
        var r: Int!
        var isShowQuickStart: Int!
        var song:[Song]!
        
        init?(map: Map) { }
        
        // Mappable
        mutating func mapping(map: Map) {
            r <- map["r"]
            isShowQuickStart <- map["is_show_quick_start"]
            song <- map["song"]
        }
    }
    
    //歌曲模型
    struct Song: Mappable {
        var title: String!
        var artist: String!
        
        init?(map: Map) { }
        
        // Mappable
        mutating func mapping(map: Map) {
            title <- map["title"]
            artist <- map["artist"]
        }
    }
    
    
    
      let data = DouBanProvider.rx.request(.channels)
                .mapObject(Douban.self)
                .map { $0.channels ?? [] }
                .asObservable()
            
            data.bind(to: self.tableView.rx.items) { tableView, _, channel in
                let cell = tableView.dequeueReusableCell(withIdentifier: "CellIdentifier")!
                cell.textLabel?.text = channel.name
                cell.accessoryType = .disclosureIndicator
                return cell
                }.disposed(by: self.disposeBag)
            
            tableView.rx.modelSelected(Channel.self)
                .map{ $0.channelId ?? "" }
                .flatMap { DouBanProvider.rx.request(.playlist($0)) }
                .mapObject(Playlist.self)
                .subscribe(onNext: { [weak self] (playList) in
                    if playList.song != nil && playList.song.count > 0 {
                        let artist = playList.song[0].artist!
                        let title = playList.song[0].title!
                        let message = "歌手:(artist)
    歌曲:(title)"
                        self?.showAlert(title: "歌曲信息", message: message)
                    }
                }).disposed(by: self.disposeBag)
    
    import RxSwift
    import RxCocoa
    import ObjectMapper
    
    class DoubanService {
    
        //获取频道数据
        func loadChannels() -> Observable<[Channel]> {
            return DouBanProvider.rx.request(.channels)
                .mapObject(Douban.self)
                .map{ $0.channels ?? [] }
                .asObservable()
        }
        
        //获取歌曲列表数据
        func loadPlaylist(channelId: String) -> Observable<Playlist> {
            return DouBanProvider.rx.request(.playlist(channelId))
                .mapObject(Playlist.self)
                .asObservable()
        }
        
        //获取频道下第一首歌曲
        func loadFirstSong(channelId: String) -> Observable<Song> {
            return loadPlaylist(channelId: channelId)
                .filter{ $0.song != nil && $0.song.count > 0}
                .map{ $0.song[0] }
        }
    }
    
    import UIKit
    import RxSwift
    import RxCocoa
    
    class MusicViewController: UIViewController {
        
        private var viewModel = MusicListViewModel()
        
        private var disposeBag = DisposeBag()
        
        private lazy var tableView: UITableView = {
            let tableView = UITableView(frame: self.view.bounds)
            tableView.register(UITableViewCell.self, forCellReuseIdentifier: "CellIdentifier")
            tableView.tableFooterView = UIView()
            return tableView
        }()
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
            self.view.backgroundColor = .white
            
            self.view.addSubview(self.tableView)
            
            let service = DoubanService()
            
            //获取列表数据
            let data = service.loadChannels()
            
            //将数据绑定到表格
            data.bind(to: tableView.rx.items) { (tableView, row, element) in
                let cell = tableView.dequeueReusableCell(withIdentifier: "CellIdentifier")!
                cell.textLabel?.text = "(element.name!)"
                cell.accessoryType = .disclosureIndicator
                return cell
                }.disposed(by: disposeBag)
            
            //单元格点击
            tableView.rx.modelSelected(Channel.self)
                .map{ $0.channelId ?? "" }
                .flatMap(service.loadFirstSong)
                .subscribe(onNext: {[weak self] song in
                    //将歌曲信息弹出显示
                    let message = "歌手:(song.artist!)
    歌曲:(song.title!)"
                    self?.showAlert(title: "歌曲信息", message: message)
                }).disposed(by: disposeBag)
            
        }
        
        //显示消息
        func showAlert(title:String, message:String) {
            let alertController = UIAlertController(title: title,
                                                    message: message, preferredStyle: .alert)
            let cancelAction = UIAlertAction(title: "确定", style: .cancel, handler: nil)
            alertController.addAction(cancelAction)
            self.present(alertController, animated: true, completion: nil)
        }
    }
    
  • 相关阅读:
    js原生小小总结(二)
    js原生小小总结(一)
    js原生小小总结
    寻找峰值
    第一个错误的版本
    [JSOI2018] 战争
    CF232E Quick Tortoise
    [JLOI2015] 骗我呢
    CF1428G Lucky Numbers
    CF1239E Turtle
  • 原文地址:https://www.cnblogs.com/youhui/p/10269624.html
Copyright © 2020-2023  润新知