代码架构

MVVM

  • Model 数据层,读写数据,保存 App 状态

  • View 页面层,提供用户输入行为,并且显示输出状态

  • ViewModel 逻辑层,它将用户输入行为,转换成输出状态

  • ViewController 主要负责数据绑定


API访问设计

API采用当下主流的Moya,具体的封装方法可自行搜索。这里主要聊一下将moya请求下来的json数据转化为Observable对象。

创建RxMoyaResponseMapper负责转化Moya从API获取到的数据

// API错误返回结果
enum RESError: Swift.Error 
    case RESNoRepresentor
    case RESNotSuccessfulHTTP
    case RESNoData
    case RESCouldNotMakeObjectError
    case RESBizError(code: String?, message: String?)
}

// API返回状态
enum BizStatus: String {
    case bizSuccess = "1"
    case bizError
}

public protocol Mapable {
    init?(json: JSON)
}

let RESULT_CODE = "code"
let RESULT_MSG = "message"
let RESULT_DATA = "data"

extension Observable {

    // 处理单对象数据
    func mapResponseToObj<T: Mapable>(type: T.Type) -> Observable<T?> {
        return map { representor in
            // get Moya.Response
            guard let response = representor as? Moya.Response else {
                throw RESError.RESNoRepresentor
            }

            // check http status
            guard (200...209) ~= response.statusCode else {
                throw RESError.RESNotSuccessfulHTTP
            }

            // unwrap biz json shell
            let json: JSON = response.tdw_mapJSON()
            //let json = JSON.init(data: response.data)

            // check biz status
            if json[RESULT_CODE] != JSON.null {
                return self.resultFromJSON(jsonData: json, classType: type)
            } else {
                throw RESError.RESCouldNotMakeObjectError
            }
        }
    }

    // 处理多对象数据
    func mapResponseToObjArray<T: Mapable>(type: T.Type) -> Observable<[T]> {
        return map { response in

            // get Moya.Response
            guard let response = response as? Moya.Response else {
                throw RESError.RESNoRepresentor
            }

            // check http status
            guard (200...209) ~= response.statusCode else {
                throw RESError.RESNotSuccessfulHTTP
            }

            // unwrap biz json shell
            let json: JSON = response.tdw_mapJSON()
            if json[RESULT_CODE] != JSON.null {
                //return self.resultFromJSON(jsonData: json, classType:type)
                var objects = [T]()
                let objectsArrays = json[RESULT_DATA].array
                if let array = objectsArrays {
                    for object in array {
                        if let obj = self.resultFromJSON(jsonData: object, classType: type) {
                            objects.append(obj)
                        }
                    }
                    return objects
                } else {
                    throw RESError.RESNoData
                }
            } else {
                throw RESError.RESCouldNotMakeObjectError
            }
        }
    }

    private func resultFromJSON<T: Mapable>(jsonData: JSON, classType: T.Type) -> T? {
        return T(json: jsonData)
    }
}

创建RxReactiveHelper来处理请求结果(成功、失败等),里面的扩展可按需求自行决定

enum CommonResult {
    case success(message: String)
    case empty
    case failed(message: String)
}

extension CommonResult {
    var isValid: Bool {
        switch self {
        case .success:
            return true
        default:
            return false
        }
    }
}

extension CommonResult {
    var textColor: UIColor {
        switch self {
        case .success:
            return UIColor(red: 138.0 / 255.0, green: 221.0 / 255.0, blue: 109.0 / 255.0, alpha: 1.0)
        case .empty:
            return UIColor.black
        case .failed:
            return UIColor.red
        }
    }
}

extension CommonResult {
    var description: String {
        switch self {
        case let .success(message):
            return message
        case .empty:
            return ""
        case let .failed(message):
            return message
        }
    }
}

/*****************************自定义的可观察对象**********************/
extension Reactive where Base: UILabel {
    var validationResult: Binder<(base: Base, result: CommonResult)> {
        return Binder(self.base) { label, result in
            label.textColor = result.base.textColor
            label.text = result.result.description
        }
    }
}

extension Reactive where Base: UITextField {
    var inputEnabled: Binder<(base: Base, result: CommonResult)> {
        return Binder(self.base) { textFiled, result in
            textFiled.isEnabled = result.result.isValid
        }
    }
}

extension Reactive where Base: UIButton {
    var tapEnabled: Binder<(base: Base, result: CommonResult)> {
        return Binder(self.base) { button, result in
            button.isEnabled = result.result.isValid
            button.alpha = result.result.isValid ? 1.0 : 0.5
        }
    }
}
/*****************************自定义的可观察对象**********************/

results matching ""

    No results matching ""