<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      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)\n歌曲:\(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!)\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)
          }
      }
      
      import UIKit
      import SnapKit
      
      class ViewController: UIViewController {
          
          private lazy var items = [HomeDataItem]()
          
          private lazy var availableTexts = [String]()
          
          private lazy var availableImages = [String]()
          
          private lazy var tableView: UITableView = {
              let tableView = UITableView()
              tableView.backgroundColor = .clear
              tableView.dataSource = self
              tableView.delegate = self
              tableView.rowHeight = 50
              tableView.register(HomeTableViewCell.self, forCellReuseIdentifier: "Cell")
              return tableView
          }()
          
          private lazy var deleteButton : UIButton = {
              var deleteButton = UIButton()
              deleteButton.setTitle("Delete", for: .normal)
              deleteButton.setTitle("", for: .disabled)
              deleteButton.backgroundColor = .red
              deleteButton.layer.cornerRadius = 10
              deleteButton.tintColor = .white
              deleteButton.addTarget(self, action: #selector(deleteAction), for: .touchUpInside)
              return deleteButton
          }()
          
          private lazy var addButton : UIButton = {
              var addButton = UIButton()
              addButton.setTitle("Add", for: .normal)
              addButton.setTitle("", for: .disabled)
              addButton.backgroundColor = .blue
              addButton.layer.cornerRadius = 10
              addButton.tintColor = .white
              addButton.addTarget(self, action: #selector(addAction), for: .touchUpInside)
              return addButton
          }()
          
          override func viewDidLoad() {
              super.viewDidLoad()
              
              setupUI()
              createDataSources()
          }
          
          private func setupUI() {
              
              let imageView = UIImageView(image: UIImage(named: "bg"))
              imageView.contentMode = .scaleAspectFill
              
              view.addSubview(imageView)
              imageView.snp.makeConstraints { make in
                  make.edges.equalToSuperview()
              }
              
              view.addSubview(tableView)
              tableView.snp.makeConstraints { make in
                  make.left.top.right.equalToSuperview()
                  make.bottom.equalToSuperview().offset(self.view.safeAreaInsets.bottom).offset(-100)
              }
              
              view.addSubview(deleteButton)
              deleteButton.snp.makeConstraints { make in
                  make.right.equalToSuperview().offset(-20)
                  make.top.equalTo(tableView.snp.bottom).offset(10)
                  make.size.equalTo(CGSize(width: 100, height: 40))
              }
              
              view.addSubview(addButton)
              addButton.snp.makeConstraints { make in
                  make.left.equalToSuperview().offset(10)
                  make.top.equalTo(tableView.snp.bottom).offset(10)
                  make.size.equalTo(CGSize(width: 100, height: 40))
              }
          }
          
          private func createDataSources() {
              getImages()
              readTxtContent()
              initializeData()
          }
          
          private func initializeData() {
              for _ in 1...10 {
                  addItem()
              }
          }
          
          private func addItem() {
              if let item = addRandomItem() {
                  items.append(item)
                  updateButtonStates()
              }
          }
          
          private func addRandomItem() -> HomeDataItem? {
              if availableImages.isEmpty || availableTexts.isEmpty {
                  return nil
              }
              
              let randomImageIndex = Int.random(in: 0..<availableImages.count)
              let randomTextIndex = Int.random(in: 0..<availableTexts.count)
              
              let image = availableImages.remove(at: randomImageIndex)
              let text = availableTexts.remove(at: randomTextIndex)
              return HomeDataItem(imageName: image, title: text)
          }
          
          @objc private func deleteAction() {
              if items.count >= 2 {
                  deleteItem(at: 1)
              } else if items.count == 1 {
                  deleteItem(at: 0)
              }
          }
          
          @objc private func addAction() {
              if items.count < 3 {
                  addItem()
                  self.tableView.reloadData()
              } else if items.count < 20 {
                  if let item = addRandomItem() {
                      items.insert(item, at: 2)
                      tableView.insertRows(at: [IndexPath(row: 2, section: 0)], with: .bottom)
                  }
                  if (self.items.count == 20) {
                      addButton.isEnabled = false
                  }
              }
          }
          
          private func updateButtonStates() {
              deleteButton.isEnabled = items.count > 0
              addButton.isEnabled = items.count < 20
          }
          
          private func deleteItem(at index: Int) {
              guard index < items.count else { return }
              let item = items.remove(at: index)
            
              availableImages.append(item.imageName)
              availableTexts.append(item.title)
              
              tableView.deleteRows(at: [IndexPath(row: index, section: 0)], with: .fade)
              updateButtonStates()
          }
          
          private func getImages() {
              for i in 1...25 {
                  let name = String(format: "thumb%02d", i)
                  availableImages.append(name)
              }
          }
          
          private func readTxtContent()  {
              guard let path = Bundle.main.path(forResource: "strings", ofType: "txt") else {
                  print("File not found.")
                  return
              }
              do {
                  let content = try String(contentsOfFile: path, encoding: .utf8)
                  availableTexts = content.split(separator: "\n").map { String($0.trimmingCharacters(in: .whitespaces)) }
              } catch {
                  print("Error reading file: \(error)")
              }
          }
      }
      
      extension ViewController: UITableViewDelegate {
          
          func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
              print("Selected item: \(items[indexPath.row])")
          }
      }
      
      extension ViewController: UITableViewDataSource {
          
          func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
              return items.count
          }
          
          func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
              let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! HomeTableViewCell
              cell.model = items[indexPath.row]
              cell.selectionStyle = .none
              return cell
          }
      }
      
      class HomeTableViewCell: UITableViewCell {
          
          var model: HomeDataItem? {
              didSet {
                  if let model = model {
                      avatarImageView.image = UIImage(named: model.imageName)
                      titleLabel.text = model.title
                  }
              }
          }
          
          private let maskLayer = CALayer()
          
          private lazy var avatarImageView: UIImageView = {
              let imageView = UIImageView()
              imageView.contentMode = .scaleAspectFit
              return imageView
          }()
          
          private lazy var titleLabel: UILabel = {
              let label = UILabel()
              label.font = UIFont.systemFont(ofSize: 15)
              label.textColor = .white
              return label
          }()
          
          override func awakeFromNib() {
              super.awakeFromNib()
              // Initialization code
          }
          
          override func setSelected(_ selected: Bool, animated: Bool) {
              super.setSelected(selected, animated: animated)
              
              // Configure the view for the selected state
          }
          
          override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
              super.init(style: style, reuseIdentifier: reuseIdentifier)
              
              maskLayer.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
              if let maskImage = UIImage(named: "frame") {
                  maskLayer.contents = maskImage.cgImage
              }
              self.avatarImageView.layer.mask = maskLayer
              
              setupUI()
          }
          
          required init?(coder: NSCoder) {
              fatalError("init(coder:) has not been implemented")
          }
          
          private func setupUI() {
              self.contentView.backgroundColor = .clear
              self.backgroundColor = .clear
              contentView.addSubview(avatarImageView)
              avatarImageView.snp.makeConstraints { make in
                  make.centerY.equalToSuperview()
                  make.left.equalToSuperview().offset(15)
                  make.size.equalTo(40)
              }
              
              contentView.addSubview(titleLabel)
              titleLabel.snp.makeConstraints { make in
                  make.centerY.equalToSuperview()
                  make.left.equalTo(avatarImageView.snp.right).offset(10)
              }
          }
      }
      

      posted on 2019-01-14 23:08  youhui  閱讀(1499)  評論(0)    收藏  舉報

      主站蜘蛛池模板: 免费国产精品黄色一区二区| 久久人与动人物a级毛片 | 99久热在线精品视频| 国产精品va在线观看h| 亚洲av永久无码精品成人| 激情综合网五月婷婷| 亚欧洲乱码视频在线观看| 久久99热只有频精品8| 99精品国产一区二区三区| 国产不卡免费一区二区| 日本肥老妇色xxxxx日本老妇| 日韩精品中文字幕国产一| 国产精品亚洲二区亚瑟| 西丰县| 精品一区二区成人码动漫| 亚洲愉拍一区二区三区| 少妇人妻偷人偷人精品| 久久久久四虎精品免费入口| 成全影视大全在线观看| 国产精品最新免费视频| 日韩高清亚洲日韩精品一区二区| 农民人伦一区二区三区| 无码av人片在线观看天堂| 日韩有码国产精品一区| 屯昌县| 国产老头多毛Gay老年男| 成人无码影片精品久久久| 欧美极品色午夜在线视频| 精品国产综合成人亚洲区| 热久久美女精品天天吊色 | 亚洲精品人妻中文字幕| 欧美综合人人做人人爱| 中文字幕人妻无码一夲道| 久久亚洲精品亚洲人av| 国产精品疯狂输出jk草莓视频| 风韵丰满妇啪啪区老老熟女杏吧| 高清偷拍一区二区三区| 少妇人妻综合久久中文字幕| 久久青青草原国产精品最新片| 久久人与动人物a级毛片| 中文字幕熟妇人妻在线视频|