代码架构
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
}
}
}
/*****************************自定义的可观察对象**********************/