使用TableView正确使用RxSwift

时间:2017-02-19 19:38:54

标签: mvvm swift3 tableview rx-swift

我不知道如何在ModelView和ViewController之间传输数据。在

SelectModelViewController

class SelectModelViewController: UIViewController {

@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var errorLabel: UILabel!
@IBOutlet weak var activityIndicator: UIActivityIndicatorView!

var markViewModel : MarkViewModel?
let markService = MarkService()
let disposeBag = DisposeBag()



override func viewDidLoad() {
    super.viewDidLoad()
    markViewModel = MarkViewModel(markService: markService)
    markViewModel?.data.asObservable()
        .bindTo(tableView.rx.items(cellIdentifier: "Cell", cellType: UITableViewCell.self)) { (_, element, cell) in
            cell.textLabel?.text = element
        }
        .addDisposableTo(disposeBag)
}
}

MarkViewModel有错误。我做错了什么

struct MarkViewModel {

let markService: MarkService
var data: Driver<[Mark]>

init(markService: MarkService) {
    self.markService = markService

    data = markService.get()
        .map { result in
            switch result {
            case.success(let marks):
                return marks.map { mark in
                    return mark
                }
            case .error(let error):
                print(error)
            }

        }.asDriver(onErrorJustReturn: .error(.other))
}}

MarkService

struct MarkService {

func get() -> Observable<Result<[Mark]>> {
    return URLSession.shared.rx.json(url: URL(string: API.BaseURL)!)
        .retry(3)
        .map {
            var marks = [Mark]()
            guard let json = $0 as? [String: Any],
                let items = json["RBMarks"] as? [[String : Any]] else {
                    return .error(.badJSON)
            }
            for item in items {
                if let mark = Mark(json: item) {
                    marks.append(mark)
                } else {
                    return .error(.badJSON)
                }
            }
            return .success(marks)
        }
        .catchErrorJustReturn(.error(.noInternet))
}}

1 个答案:

答案 0 :(得分:0)

首先,我们可以从Observable<Result<[Mark]>>而不是MarkService返回Any。稍后显示它们将非常有用。

struct MarkService {

    func get() -> Observable<Result<[Mark]>> {
        return URLSession.shared.rx.json(url: URL(string: API.BaseURL)!)
            .retry(3)
            .map {
                var marks = [Mark]()
                guard let json = $0 as? [String: Any],
                    let items = json["RBMarks"] as? [[String : Any]] else {
                        return .error(.badJSON)
                }
                for item in items {
                    if let mark = Mark(json: item) {
                        marks.append(mark)
                    } else {
                        return .error(.badJSON)
                    }
                }
                return .success(marks)
            }
            .catchErrorJustReturn(.error(.noInternet))
    }
}

然后,让我们删除dataMarkViewModel的订阅。我们还会将标记转换为更适合演示的内容。

struct MarkViewModel {

    let markService: MarkService
    var data: Driver<[String]>
    var marks: Variable<[Mark]>
    let disposeBag = DisposeBag()

    init(markService: MarkService) {
        self.markService = markService


        data = markService.get()
            .map { result in
                guard case .success(let marks) = result else {
                    return ["Error while getting marks"]
                }

                return marks.map { mark in
                    "For assignment \(mark.assignmentName), you were marked with \(mark.grade)/10"
                }
            }
            .asDriver(onErrorJustReturn: .error(.other))
    }
}

现在,在视图控制器中,我们可以使用RxSwift的表视图绑定来显示这些数据

let disposeBag = DisposeBag()

func viewDidLoad() {
    viewModel.data
        .bindTo(tableView.rx.items(cellIdentifier: "Cell", cellType: UITableViewCell.self)) { (_, element, cell) in
            cell.textLabel?.text = element
        }
        .addDisposableTo(disposeBag)
}

这显然只是一个如何做到这一点的示例,代码将根据特定视图的要求而改变。