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 Moyalet 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 UIKitimport 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)\n歌曲:\(title)" self?.showAlert(title: "歌曲信息", message: message) } }).disposed(by: self.disposeBag)
import RxSwiftimport RxCocoaimport ObjectMapperclass 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 UIKitimport RxSwiftimport RxCocoaclass 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!)\n歌曲:\(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) }}

相关文章