RxSwift结合Moya获取天气数据,并结合tableView进行展示
效果图
一. cocoPod安装RxSwift, RxCocoa, Alamofire, Moya/RxSwift
二. 模型
-
枚举表示根据地理位置获取天气数据
enum SkyAPI { //根据经纬度获取天气数据 case getWeatherData(Location) }
-
遵守TargetType协议,创建MoyaProvider
extension SkyAPI: TargetType { var headers: [String : String]? { return nil } var baseURL: URL { return URL(string: BASE_URL)! } var path: String { switch self { case .getWeatherData(let location): return KEY + "/" + "\(location.latitude),\(location.longitude)" } } var method: Moya.Method { return .get } var sampleData: Data { return "找不到数据".data(using: String.Encoding.utf8)! } var validate: Bool { return true } var task: Task { return .requestPlain } }
-
天气模型
struct Sky { var humidity: Double? var time: TimeInterval? var windSpeed: Double? var summary: String? var tempera: Double? init(dict: [String: Any]?) { guard let dict = dict else {return} print(dict) self.humidity = dict["humidity"] as? Double self.time = dict["time"] as? Double self.windSpeed = dict["windSpeed"] as? Double self.summary = dict["summary"] as? String self.tempera = ((dict["temperatureMin"] as? Double ?? 0 ) - 32) / 1.8 } } class SkyModel: NSObject { var currently: Sky? var daily: [Sky]? init?(dict: [String: Any]?) { guard let dict = dict else{return nil} var skyDays = [Sky]() self.currently = Sky(dict: dict["currently"] as? [String: Any]) if let daily = dict["daily"] as? [String: Any] { if let days = daily["data"] as? [[String: Any]] { for day in days { skyDays.append(Sky(dict: day)) } } } self.daily = skyDays } }
-
请求数据
class SkyViewModel: NSObject { override init() { super.init() } func loadWeatherData(location: Location) -> Observable<SkyModel?> { let provider = MoyaProvider<SkyAPI>() return Observable.create({ (observer) -> Disposable in provider.request(.getWeatherData(location), completion: { (response) in switch response { case let .success(result): guard let result = try? result.mapJSON() else {return} observer.onNext(SkyModel(dict: result as? [String: Any])) observer.onCompleted() case let .failure(error): observer.onError(error) } }) return Disposables.create() }) } }
三.展示数据
-
定位,获取地理位置
func setupLocationManager() { locationManager = CLLocationManager() locationManager.delegate = self locationManager.desiredAccuracy = kCLLocationAccuracyBest } func startLocation() { locationManager.requestWhenInUseAuthorization() locationManager.startUpdatingLocation() } extension SkyViewController: CLLocationManagerDelegate { func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { let location = locations.last let coordinate = location?.coordinate if let latitide = coordinate?.latitude, let longitude = coordinate?.longitude { myLocation = Location(name: "", latitude: latitide, longitude: longitude) viewModel.loadWeatherData(location: myLocation) .subscribe(onNext: { if let skyModel = $0 { self.skyModel = skyModel self.setupUI() } }, onError: { print($0) }) .disposed(by: disposedBag) } locationManager.stopUpdatingLocation() } }
-
创建tableView,indicatorView
func setupUI() { indicatorView.stopAnimating() indicatorView.removeFromSuperview() tableView = UITableView() tableView.register(SkyTableViewCell.self, forCellReuseIdentifier: "SkyCellID") tableView.tableFooterView = UIView() tableView.delegate = self tableView.dataSource = self view.addSubview(tableView) tableView.snp.makeConstraints { (make) in make.edges.equalToSuperview() } } func setupIndicator() { indicatorView = UIActivityIndicatorView() view.addSubview(indicatorView) indicatorView.startAnimating() indicatorView.activityIndicatorViewStyle = .gray indicatorView.snp.makeConstraints { (make) in make.centerX.centerY.equalToSuperview() } }
-
绑定数据
extension SkyViewController: UITableViewDelegate, UITableViewDataSource { func numberOfSections(in tableView: UITableView) -> Int { return 1 } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return skyModel.daily?.count ?? 0 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "SkyCellID") as! SkyTableViewCell cell.displayData(sky: skyModel.daily![indexPath.row]) return cell } func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return 60 } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) } }
-
自定义cell
class SkyTableViewCell: UITableViewCell { override init(style: UITableViewCellStyle, reuseIdentifier: String?) { super.init(style: UITableViewCellStyle.subtitle, reuseIdentifier: reuseIdentifier) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } func displayData(sky: Sky) { textLabel?.text = "湿度: \(sky.humidity ?? 0) 温度: \(sky.tempera ?? 0) 风速: \(sky.windSpeed ?? 0)" detailTextLabel?.text = "描述: \(sky.summary ?? "")" } }