上一篇分享了登录界面,没有网络请求,着重理解下使用流程。这一篇给大家分享一下有网络请求的界面展示,Swift3+MVVM+ReactiveCocoa5该怎么应用。
Talk is cheap. Show me the code
需求描述:
请求豆瓣图书列表,解析并展示在界面表格中
Model
class BookDataModel: NSObject {
var title:String = ""
var subtitle:String = ""
init(dic:[String:Any]) {
super.init()
self.setValuesForKeys(dic)// 字典转BookDataModel便捷方法
}
// 字典转BookDataModel,BookDataModel中没有的key重写不抛出异常
override func setValue(_ value: Any?, forUndefinedKey key: String) {
}
}
ViewController
class BookViewController: UIViewController {
lazy var bookViewModel = {
return BookViewModel()
}()
var table:UITableView!
override func viewDidLoad() {
super.viewDidLoad()
table = UITableView(frame: view.bounds, style: .plain)
table.dataSource = bookViewModel
view.addSubview(table)
// 请求图书列表,观察结果,得到数据后刷新列表
bookViewModel.bookAction.apply(()).startWithResult { (result) in
switch result {
case let .success(value):
self.bookViewModel.models = value
self.table.reloadData()
default:
break
}
}
}
}
ViewModel
// 导入RAC5模块
import ReactiveCocoa
import ReactiveSwift
import Result
class BookViewModel: NSObject,UITableViewDataSource {
let cellIdentifier = "cell"
var bookAction:Action<(),[BookDataModel],AnyError>!
var models = [BookDataModel]()
override init() {
super.init()
initialBind()
}
func initialBind() {
// 请求图书列表并解析业务
bookAction = Action<(),[BookDataModel],AnyError> { (_) -> SignalProducer<[BookDataModel], AnyError> in
SignalProducer<String, AnyError>({ (observer, _) in
// MFNetworkRequest是我自己封装的网络请求,成功返回String报文,失败返回错误原因,可忽略。
let bookRequest = MFNetworkRequest()
bookRequest.sendDataGetRequest(url: "https://api.douban.com/v2/book/search?q=基础", successBlock: { (successStr) in
observer.send(value: successStr)
observer.sendCompleted()
}, failedBlock: { (failedStr) in
})
}).map({ (str) -> [BookDataModel] in
// 将请求成功得到的String报文中的数组解析成BookDataModel数组
let bookObject = try! JSONSerialization.jsonObject(with: str.data(using: .utf8) ?? Data(), options: .mutableContainers)
let bookDic = bookObject as! Dictionary<String, Any>
let bookArr = bookDic["books"] as! Array<Dictionary<String,Any>>
var books = [BookDataModel]()
for book in bookArr {
let model = BookDataModel(dic: book)
books.append(model)
}
return books
})
}
}
//MARK:UITableViewDataSource
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return models.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier)
if cell == nil {
cell = UITableViewCell(style: .subtitle, reuseIdentifier: cellIdentifier)
}
let book = models[indexPath.row]
cell?.textLabel?.text = book.title
cell?.detailTextLabel?.text = book.subtitle
return cell!
}
}
效果图
如果觉得我的文章对您有用,请点击喜欢。您的支持将鼓励我继续创作!
大家有什么不懂或我哪里写错了都可以评论留言,我一定会回复的~
网友评论