J'essaie de travailler avec ReSwift dans mon projet ios et j'avais une question sur la façon de gérer les changements dans ma vue. Je trouve que j'ai besoin de savoir ce qu'était l'ancien état avant de pouvoir appliquer les changements proposés par le nouvel état. Je n'ai jamais eu besoin de savoir quel était mon ancien état quand je travaillais avec un redux dans mes réactions.ReSwift - Comment gérer les changements d'état qui dépendent de l'ancien état ainsi que du nouvel état dans la vue
Mon cas d'utilisation particulier est, je suis bulding un CameraView avec un écran de superposition. De n'importe où dans l'application, disons un ViewController je peux créer un CameraView et le déclencher pour ouvrir un UIImagePickerController à partir de celui-ci en tirant une action. Voici un code:
//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)
}
}
Ce qui précède est tout le code pour ouvrir et fermer la caméra. Ma confusion commence, lorsque nous ajoutons d'autres actions, telles que désactiver ou activer le flash. J'ai besoin de virer sur les transitions d'état supplémentaires à mon avis.
Mes actions se développent maintenant:
struct OpenCameraAction: Action {}
struct CloseCameraAction: Action {}
struct FlashToggleAction: Action {}
Mon état ressemble maintenant à ceci:
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.
Selon moi, où les complications commencent. Si l'utilisateur a activé Flash et que je réponds à un changement d'état FlashToggleAction, comment puis-je modifier le changement d'état dans ma vue?
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()
}
}
Comment puis-je répondre aux changements maintenant? La seule façon dont je peux penser à gérer cela est de stocker une référence à l'ancien état et de comparer la différence moi-même.
Je n'ai pas le temps de répondre maintenant, mais d'abord en commençant par le début. à l'intérieur de la vue, le contrôleur de vue que vous passez Une voiture faible est probablement le bon candidat pour la conformité à StoreSubscriber.Pour cette action, je stocke généralement un état didAskForCamera qui déclenche l'ouverture de la caméra sur le callback newState. Vous redéfinissez ensuite cette variable sur false pour qu'elle ne soit pas appelée plusieurs fois pour chaque changement d'état. Enfin, créez un état séparé pour la vue de la caméra avec des actions comme flashon, flashoff (pas basculer). – Rog
Aussi pour des actions simples comme ci-dessus, je trouve que les cas d'énumération fonctionnent très bien. ie enum CameraActions: ActionType {affaire flashOn, affaire flashOff, etc) – Rog