diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxModel.swift index 87c4568d..31f19bae 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxModel.swift @@ -7,7 +7,7 @@ // -@objcMembers public class CheckboxModel: NSObject, MoleculeModelProtocol, SelectableMoleculeModelProtocol, FormFieldProtocol { +@objcMembers public class CheckboxModel: MoleculeModelProtocol, SelectableMoleculeModelProtocol, FormFieldProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -15,7 +15,7 @@ public static var identifier: String = "checkbox" public var backgroundColor: Color? public var accessibilityIdentifier: String? - public dynamic var selected: Bool = false + public var selected: Bool = false public var enabled: Bool = true public var animated: Bool = true public var inverted: Bool = false @@ -80,6 +80,14 @@ baseValue = isChecked } + //-------------------------------------------------- + // MARK: - Behavior + //-------------------------------------------------- + + public func getRequiredBehaviors() -> [PageBehaviorModelProtocol] { + [SelectAllBoxesBehaviorModel()] + } + //-------------------------------------------------- // MARK: - Codec //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/ToggleModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/ToggleModel.swift index 0fb42632..056035b4 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/ToggleModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/ToggleModel.swift @@ -7,7 +7,7 @@ // -public class ToggleModel: NSObject, MoleculeModelProtocol, FormFieldProtocol, EnableableModelProtocol, SelectableMoleculeModelProtocol { +public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableModelProtocol, SelectableMoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -15,7 +15,7 @@ public class ToggleModel: NSObject, MoleculeModelProtocol, FormFieldProtocol, En public static var identifier: String = "toggle" public var accessibilityIdentifier: String? public var backgroundColor: Color? - public dynamic var selected: Bool = false + public var selected: Bool = false public var animated: Bool = true public var enabled: Bool = true public var action: ActionModelProtocol? diff --git a/MVMCoreUI/Behaviors/SelectAllBoxesBehavior.swift b/MVMCoreUI/Behaviors/SelectAllBoxesBehavior.swift index 1f7326fd..3837eaa9 100644 --- a/MVMCoreUI/Behaviors/SelectAllBoxesBehavior.swift +++ b/MVMCoreUI/Behaviors/SelectAllBoxesBehavior.swift @@ -9,8 +9,8 @@ /// Protocol to apply to any model of a UI Control with a binary on/off nature. /// /// Example classes: Checkbox or Toggle. -@objc public protocol SelectableMoleculeModelProtocol: AnyObject { - @objc dynamic var selected: Bool { get set } +@objc public protocol SelectableMoleculeModelProtocol { + var selected: Bool { get set } } public class SelectAllBoxesBehaviorModel: PageBehaviorModelProtocol { @@ -34,9 +34,6 @@ public class SelectAllBoxesBehavior: PageCustomActionHandlerBehavior, PageMolecu /// Reference to the general PageBehaviorModel. var model: PageBehaviorModelProtocol - /// Dictionary of KVOs to observing the selected property of each `SelectableMoleculeModel`. - private var observers = [String: NSKeyValueObservation?]() - /// A store representing the values of the `SelectableMoleculeModel`. private var valuesMirror = [String: Bool]() @@ -57,45 +54,17 @@ public class SelectAllBoxesBehavior: PageCustomActionHandlerBehavior, PageMolecu public func onPageNew(rootMolecules: [MoleculeModelProtocol], _ delegateObject: MVMCoreUIDelegateObject) { - let selectableModels: [(NSObject & SelectableMoleculeModelProtocol)] = rootMolecules.allMoleculesOfType() + let selectableModels: [SelectableMoleculeModelProtocol] = rootMolecules.allMoleculesOfType() guard !selectableModels.isEmpty else { return } for model in selectableModels { if let key = (model as? FormFieldProtocol)?.fieldKey { valuesMirror[key] = model.selected - setObserver(model, fieldKey: key) } } } - func setObserver(_ model: T, fieldKey: String) where T: (NSObject & SelectableMoleculeModelProtocol) { - - observers[fieldKey] = model.observe(\.selected, options: [.new]) { [weak self] model, change in - guard let self = self, - let isChecked = change.newValue - else { return } - - self.valuesMirror[fieldKey] = isChecked - - // If all are models are in the opposite state of the behavior, then realign. - if self.selectAllIsMisaligned() { - self.realignPageBehaviorAs(willSelectAll: false) - - } else if self.deselectAllIsMisaligned() { - self.realignPageBehaviorAs(willSelectAll: true) - } - } - } - - //-------------------------------------------------- - // MARK: - Deinit - //-------------------------------------------------- - - deinit { - observers.values.forEach { $0?.invalidate() } - } - //-------------------------------------------------- // MARK: - Custom Action //-------------------------------------------------- @@ -110,23 +79,45 @@ public class SelectAllBoxesBehavior: PageCustomActionHandlerBehavior, PageMolecu public func handleAction(type actionType: String?, information: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?) -> Bool { // Verify we have the correct action type and necessary values. - guard actionType == "selectAllBoxes", - let selectableModels: [SelectableMoleculeModelProtocol] = delegate?.moleculeDelegate?.getRootMolecules().allMoleculesOfType(), - !selectableModels.isEmpty - else { return false } - - // Hold value dues to asynch behavior of page refreshing. - let newSelectedState = willSelectAllState - - // Iterate through selectable molecules. - for selectableModel in selectableModels { - if toSelect(model: selectableModel) || toDeselect(model: selectableModel) { - selectableModel.selected = newSelectedState + if actionType == "selectAllBoxes" { + guard let selectableModels: [SelectableMoleculeModelProtocol] = delegate?.moleculeDelegate?.getRootMolecules().allMoleculesOfType(), + !selectableModels.isEmpty + else { return false } + + // Hold value dues to asynch behavior of page refreshing. + let newSelectedState = willSelectAllState + + // Iterate through selectable molecules. + for selectableModel in selectableModels { + if toSelect(model: selectableModel) || toDeselect(model: selectableModel) { + selectableModel.selected = newSelectedState + } } + + willSelectAllState.toggle() + updatePageNavigationUI() + return true + + } else if actionType == "boxSelected" { + guard let checkboxModel = (additionalData?["sourceModel"] as? CheckboxModel), + let fieldKey = checkboxModel.fieldKey + else { return false } + + self.valuesMirror[fieldKey] = checkboxModel.selected + + // If all are models are in the opposite state of the behavior, then realign. + if self.selectAllIsMisaligned() { + self.realignPageBehaviorAs(willSelectAll: false) + + } else if self.deselectAllIsMisaligned() { + self.realignPageBehaviorAs(willSelectAll: true) + } + + return true + + } else { + return false } - - updatePageNavigationUI() - return true } //--------------------------------------------------