我正在尝试在我的 ios 项目中使用 ReSwift,并且对如何处理我的视图中的更改有疑问。我发现我需要知道旧状态是什么,然后才能应用新状态提出的更改。在我的反应项目中使用 redux 时,我从来不需要知道我的旧状态是什么。
我的特殊用例是,我正在构建一个带有 Overlay 屏幕的 CameraView。从应用程序中的任何位置说一个 ViewController 我可以创建一个 CameraView 并触发它通过触发一个动作从其中打开一个 UIImagePickerController。这是一些代码:
//ViewController:
class MainViewController: UIViewController {
var cameraView: CameraView?
@IBOutlet weak var launchCameraButton: UIButton!
init() {
cameraView = CameraView(self)
}
@IBAction func launchCameraButtonClicked(_ sender: Any) {
store.dispatch(OpenCameraAction())
}
}
//CameraActions
struct OpenCameraAction: Action {}
struct CloseCameraAction: Action {}
//CameraState
struct CameraState {
var cameraIsVisible: Bool
}
func cameraReducer(state: CameraState?, action: Action) -> CameraState {
let initialState = state ?? CameraState()
switch action {
case _ as OpenCameraAction:
return CameraState(cameraIsVisible: true)
default:
return initialState
}
}
//CameraView
class CameraView: StoreSubscriber {
private var imagePicker: UIImagePickerController?
weak private var viewController: UIViewController?
init(viewController: UIViewController) {
self.viewController = viewController
super.init()
imagePicker = UIImagePickerController()
imagePicker?.allowsEditing = true
imagePicker?.sourceType = .camera
imagePicker?.cameraCaptureMode = .photo
imagePicker?.cameraDevice = .rear
imagePicker?.modalPresentationStyle = .fullScreen
imagePicker?.delegate = self
imagePicker?.showsCameraControls = false
store.subscribe(self) { subscription in
subscription.select { state in
state.camera
}
}
}
func newState(state: CameraState?) {
guard let state = state else {
return
}
if state.cameraIsVisible {
self.open()
} else if !state.cameraIsVisible {
self.close()
}
}
func open() {
if let imagePicker = self.imagePicker {
self.viewController?.present(
imagePicker,
animated: true
)
}
}
func close(){
self.imagePicker?.dismiss(animated: true)
}
}
以上就是打开和关闭相机的所有代码。当我们添加更多操作(例如禁用或启用闪光灯)时,我的困惑开始了。在我看来,我需要处理额外的状态转换。
我的行动现在发展到:
struct OpenCameraAction: Action {}
struct CloseCameraAction: Action {}
struct FlashToggleAction: Action {}
我的状态现在看起来像这样:
struct CameraState {
var cameraIsVisible: Bool
var flashOn: Bool
}
// not showing reducer changes as it self explanatory
// what the state changes will be for my actions.
我的观点是复杂性开始的地方。如果用户启用了 flash 并且我正在响应 FlashToggleAction 状态更改,我如何在我的视图中处理状态更改?
func newState(state: CameraState?) {
guard let state = state else {
return
}
// this will get triggered regardless of whether
// a change in the flash happened or not.
self.toggleFlash(state.flashOn)
// now the below lines will be executed even though
// the only change was a flash on action.
//I don't want my camera to opened again or closed.
if state.cameraIsVisible {
self.open()
} else if !state.cameraIsVisible {
self.close()
}
}
我现在如何应对变化?我能想到的唯一方法是存储对旧状态的引用并自己比较差异。