代码示例中将传统的项目用 RxSwift 来改造。
使用 Variable 替代传统的变量
let todoItems = Variable<[TodoItem]>([])
使用变量时,仅需要取todoItems.value
.
这样做可以方便监听todoItems
的值(信号)的变化,tableView 可以统一做刷新操作。
todoItems.asObservable()
.subscribe(onNext: { [weak self] todos in
self?.updateUI(todos: todos)
})
.disposed(by: bag)
额外的,如果改变 TodoItem 属性值,是不会触发信号变化的,这时我们需要手动触发一下。例如:
odoItems.value[indexPath.row] = newTodoItem
使用 Observer 进行 ViewController 之间的值传递(反向传值)
以vc1
push TodoDetailViewController
为例.
TodoDetailViewController
中声明:
fileprivate let todoSubject = PublishSubject<TodoItem>()
var todo: Observable<TodoItem> {
return todoSubject.asObservable()
}
在 vc1 中进行订阅:
_ = currController.todo.subscribe(onNext: { [weak self] item in
self?.todoItems.value.append(item)
}) {
print("Finish adding a new todo.")
}
为了进行资源释放,TodoDetailViewController
页面图退出的时候,执行 complete,以便让订阅者自动取消订阅。
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
todoSubject.onCompleted()
}
RxSwift 对某些方法返回方式的改造
func saveTodoItems() {
let data = NSMutableData()
let archiver = NSKeyedArchiver(forWritingWith: data)
archiver.encode(todoItems.value, forKey: "TodoItems")
archiver.finishEncoding()
data.write(to: dataFilePath(), atomically: true)
}
我们知道data.write...
并不一定能操作成功,因此改造为如下方式:
func saveTodoItems() -> Observable<Void> {
let data = NSMutableData()
let archiver = NSKeyedArchiver(forWritingWith: data)
archiver.encode(todoItems.value, forKey: "TodoItems")
archiver.finishEncoding()
return Observable.create { ob -> Disposable in
let res = data.write(to: self.dataFilePath(), atomically: true)
if res {
ob.onCompleted()
} else {
ob.onError(SaveTodoError.cannotSaveToLocalFile)
}
return Disposables.create()
}
}
方法的调用如下:
_ = saveTodoItems().subscribe(onError: { error in
print(error)
}, onCompleted: {
print("on completed")
}, onDisposed: {
print("on disposed")
})
用户授权的灵活配置
这里以用户获取图片读取权限为例:
import Foundation
import Photos
import RxSwift
extension PHPhotoLibrary {
static var isAuthorized: Observable<Bool> {
return Observable.create { observer in
DispatchQueue.main.async {
if authorizationStatus() == .authorized {
observer.onNext(true)
observer.onCompleted()
} else {
observer.onNext(false)
requestAuthorization {
observer.onNext($0 == .authorized)
observer.onCompleted()
}
}
}
return Disposables.create()
}
}
}
判断用户授予权限时,进行页面的刷新
let isAuthorized = PHPhotoLibrary.isAuthorized
isAuthorized
.skipWhile { $0 == false }
.take(1)
.observeOn(MainScheduler.instance)
.subscribe(onNext: { [weak self] _ in
self?.photos = PhotoCollectionViewController.loadPhotos()
self?.collectionView.reloadData()
})
.disposed(by: bag)
判断用户拒绝给与权限或者当前没有图片权限时,给与提示:
isAuthorized
.distinctUntilChanged()
.takeLast(1)
.filter { $0 == false }
.subscribe { [weak self] _ in
self?.flash(title: "Cannot access your photo library",
message: "You can authorize access from the Settings.",
callback: { [weak self] _ in
self?.navigationController?.popViewController(animated: true)
})
}
.disposed(by: bag)