From bd9e8cf7adc5ca762f053da12e89469947509cb1 Mon Sep 17 00:00:00 2001 From: Kyle Matthew Hedden Date: Tue, 8 Mar 2022 22:28:35 -0500 Subject: [PATCH] insert molecule transformation hooks into the list template --- MVMCoreUI.xcodeproj/project.pbxproj | 4 ++++ .../TextFields/EntryFieldModel.swift | 6 ++++- .../TextFields/TextEntryField.swift | 4 ++++ .../Atoms/Selectors/RadioBoxesModel.swift | 1 + .../Atomic/Atoms/Views/Label/Label.swift | 6 ++++- .../Atomic/Atoms/Views/Label/LabelModel.swift | 4 ++++ .../Atomic/Atoms/Views/LoadImageView.swift | 2 +- .../MoleculeModelProtocol.swift | 3 +++ .../ModelProtocols/PageModelProtocol.swift | 1 + .../Atomic/Protocols/TemplateProtocol.swift | 1 + .../Protocols/ViewMaskingProtocol.swift | 21 +++++++++++++++++ .../Templates/MoleculeListTemplate.swift | 8 ++++--- .../Atomic/Templates/TemplateModel.swift | 7 ++++++ MVMCoreUI/BaseClasses/TextField.swift | 9 ++++++-- MVMCoreUI/BaseClasses/View.swift | 7 +++++- .../BaseControllers/ViewController.swift | 23 ++++++++++++++++++- .../PageBehaviorHandlerProtocol.swift | 6 +++-- .../Protocols/PageBehaviorProtocol.swift | 9 ++++++++ MVMCoreUI/OtherHandlers/MVMCoreUISession.h | 12 ++++++---- MVMCoreUI/OtherHandlers/MVMCoreUISession.m | 4 ++++ 20 files changed, 122 insertions(+), 16 deletions(-) create mode 100644 MVMCoreUI/Atomic/Protocols/ViewMaskingProtocol.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 2b9c6711..a329075f 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -128,6 +128,7 @@ 0AF60F0926B3316E00AC3DB4 /* MVMCoreUIUtility+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF60F0826B3316E00AC3DB4 /* MVMCoreUIUtility+Extension.swift */; }; 1D6D258826899B0C00DEBB08 /* ImageButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D6D258626899B0B00DEBB08 /* ImageButtonModel.swift */; }; 1D6D258926899B0C00DEBB08 /* ImageButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D6D258726899B0B00DEBB08 /* ImageButton.swift */; }; + 27559EFC27D691D3000836C1 /* ViewMaskingProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27559EFB27D691D3000836C1 /* ViewMaskingProtocol.swift */; }; 279B1569242BBC2F00921D6C /* ActionModelAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279B1568242BBC2F00921D6C /* ActionModelAdapter.swift */; }; 27F6B08826051831008529AA /* MoleculeTreeTraversalProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27F6B08726051831008529AA /* MoleculeTreeTraversalProtocol.swift */; }; 27F6B08C26052AFF008529AA /* ParentMoleculeModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27F6B08B26052AFF008529AA /* ParentMoleculeModelProtocol.swift */; }; @@ -711,6 +712,7 @@ 0AF60F0826B3316E00AC3DB4 /* MVMCoreUIUtility+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MVMCoreUIUtility+Extension.swift"; sourceTree = ""; }; 1D6D258626899B0B00DEBB08 /* ImageButtonModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ImageButtonModel.swift; path = MVMCoreUI/Atomic/Atoms/Buttons/ImageButtonModel.swift; sourceTree = SOURCE_ROOT; }; 1D6D258726899B0B00DEBB08 /* ImageButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ImageButton.swift; path = MVMCoreUI/Atomic/Atoms/Buttons/ImageButton.swift; sourceTree = SOURCE_ROOT; }; + 27559EFB27D691D3000836C1 /* ViewMaskingProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewMaskingProtocol.swift; sourceTree = ""; }; 279B1568242BBC2F00921D6C /* ActionModelAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionModelAdapter.swift; sourceTree = ""; }; 27F6B08726051831008529AA /* MoleculeTreeTraversalProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeTreeTraversalProtocol.swift; sourceTree = ""; }; 27F6B08B26052AFF008529AA /* ParentMoleculeModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParentMoleculeModelProtocol.swift; sourceTree = ""; }; @@ -2389,6 +2391,7 @@ D28BA7442481652D00B75CB8 /* TabBarProtocol.swift */, D2B9D0E3265EEE9D0084735C /* MoleculeListProtocol.swift */, 011B58EE23A2AA850085F53C /* ModelProtocols */, + 27559EFB27D691D3000836C1 /* ViewMaskingProtocol.swift */, ); path = Protocols; sourceTree = ""; @@ -2854,6 +2857,7 @@ D23EA800247EBD6C00D60C34 /* LabelBarButtonItem.swift in Sources */, 01EB368F23609801006832FA /* LabelModel.swift in Sources */, 0A6682AC243531C300AD3CA1 /* Padding.swift in Sources */, + 27559EFC27D691D3000836C1 /* ViewMaskingProtocol.swift in Sources */, AA1EC59924373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift in Sources */, AA37CBD52519072F0027344C /* Stars.swift in Sources */, 942C378E2412F5B60066E45E /* ModalMoleculeStackTemplate.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift index 3fed121a..de7dfd74 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift @@ -42,7 +42,8 @@ import Foundation public var wasInitiallySelected: Bool = false public var title: String? public var feedback: String? - + public var shouldMaskRecordedView: Bool = true + //used to drive the EntryFieldView UI public var titleStateLabel: FormLabelModel public var feedbackStateLabel: FormLabelModel @@ -79,6 +80,7 @@ import Foundation case fieldKey case groupName case required + case shouldMaskRecordedView } //-------------------------------------------------- @@ -143,6 +145,7 @@ import Foundation hideBorders = try typeContainer.decodeIfPresent(Bool.self, forKey: .hideBorders) ?? false baseValue = text fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) + shouldMaskRecordedView = try typeContainer.decode(Bool.self, forKey: .shouldMaskRecordedView) if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { self.groupName = groupName } @@ -172,5 +175,6 @@ import Foundation try container.encode(enabled, forKey: .enabled) try container.encode(required, forKey: .required) try container.encode(hideBorders, forKey: .hideBorders) + try container.encode(shouldMaskRecordedView, forKey: .shouldMaskRecordedView) } } diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextEntryField.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextEntryField.swift index 89e17169..540beb97 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextEntryField.swift @@ -338,12 +338,16 @@ import UIKit text = model.text placeholder = model.placeholder + textField.shouldMaskWhileRecording = model.shouldMaskRecordedView + switch model.type { case .password, .secure: textField.isSecureTextEntry = true + textField.shouldMaskWhileRecording = true case .numberSecure: textField.isSecureTextEntry = true + textField.shouldMaskWhileRecording = true textField.keyboardType = .numberPad case .number: diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift index 7e919553..1b397f5e 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift @@ -22,6 +22,7 @@ public var baseValue: AnyHashable? public var enabled: Bool = true public var readOnly: Bool = false + //-------------------------------------------------- // MARK: - Methods //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift b/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift index 687683d7..7a147f13 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Label/Label.swift @@ -12,7 +12,8 @@ import MVMCore public typealias ActionBlock = () -> () -@objcMembers open class Label: UILabel, MVMCoreViewProtocol, MoleculeViewProtocol, MVMCoreUIViewConstrainingProtocol, MFButtonProtocol { +@objcMembers open class Label: UILabel, MVMCoreViewProtocol, MoleculeViewProtocol, MVMCoreUIViewConstrainingProtocol, MFButtonProtocol, ViewMaskingProtocol { + //------------------------------------------------------ // MARK: - Properties //------------------------------------------------------ @@ -41,6 +42,8 @@ public typealias ActionBlock = () -> () NSRange(location: 0, length: text?.count ?? 0) } + public var shouldMaskWhileRecording: Bool = false + //------------------------------------------------------ // MARK: - Multi-Action Text //------------------------------------------------------ @@ -244,6 +247,7 @@ public typealias ActionBlock = () -> () text = nil attributedText = nil originalAttributedString = nil + shouldMaskWhileRecording = model.shouldMaskRecordedView guard let labelModel = model as? LabelModel else { return } diff --git a/MVMCoreUI/Atomic/Atoms/Views/Label/LabelModel.swift b/MVMCoreUI/Atomic/Atoms/Views/Label/LabelModel.swift index 2eec132f..de5c3980 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Label/LabelModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Label/LabelModel.swift @@ -26,6 +26,7 @@ public var hero: Int? public var makeWholeViewClickable: Bool? public var numberOfLines: Int? + public var shouldMaskRecordedView: Bool = false //-------------------------------------------------- // MARK: - Keys @@ -46,6 +47,7 @@ case hero case makeWholeViewClickable case numberOfLines + case shouldMaskRecordedView } enum AttributeTypeKey: String, CodingKey { @@ -79,6 +81,7 @@ hero = try typeContainer.decodeIfPresent(Int.self, forKey: .hero) makeWholeViewClickable = try typeContainer.decodeIfPresent(Bool.self, forKey: .makeWholeViewClickable) numberOfLines = try typeContainer.decodeIfPresent(Int.self, forKey: .numberOfLines) + shouldMaskRecordedView = try typeContainer.decodeIfPresent(Bool.self, forKey: .shouldMaskRecordedView) ?? false } open func encode(to encoder: Encoder) throws { @@ -97,5 +100,6 @@ try container.encodeIfPresent(hero, forKey: .hero) try container.encodeIfPresent(makeWholeViewClickable, forKey: .makeWholeViewClickable) try container.encodeIfPresent(numberOfLines, forKey: .numberOfLines) + try container.encodeIfPresent(shouldMaskRecordedView, forKey: .shouldMaskRecordedView) } } diff --git a/MVMCoreUI/Atomic/Atoms/Views/LoadImageView.swift b/MVMCoreUI/Atomic/Atoms/Views/LoadImageView.swift index 8d8ef49e..f3d381bc 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/LoadImageView.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/LoadImageView.swift @@ -22,7 +22,7 @@ public var addSizeConstraintsForAspectRatio = true public var shouldNotifyDelegateOnUpdate = true public var shouldNotifyDelegateOnDefaultSizeChange = false - + // Allows for a view to hardcode which height to use if there is none in the json. var imageWidth: CGFloat? var imageHeight: CGFloat? diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift index df3b0dca..240136c2 100644 --- a/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift @@ -8,6 +8,7 @@ public enum MolecularError: Swift.Error { public protocol MoleculeModelProtocol: ModelProtocol, AccessibilityModelProtocol, MoleculeTreeTraversalProtocol { var moleculeName: String { get } var backgroundColor: Color? { get set } + var shouldMaskRecordedView: Bool { get } } public extension MoleculeModelProtocol { @@ -17,6 +18,8 @@ public extension MoleculeModelProtocol { static var categoryName: String { "\(MoleculeModelProtocol.self)" } static var categoryCodingKey: String { "moleculeName" } + + var shouldMaskRecordedView: Bool { return false } } diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/PageModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/PageModelProtocol.swift index cfad22df..5796eb0a 100644 --- a/MVMCoreUI/Atomic/Protocols/ModelProtocols/PageModelProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/PageModelProtocol.swift @@ -13,4 +13,5 @@ public protocol PageModelProtocol { var screenHeading: String? { get set } var backgroundColor: Color? { get set } var navigationBar: (NavigationItemModelProtocol & MoleculeModelProtocol)? { get set } + var shouldMaskScreenWhileRecording: Bool { get } } diff --git a/MVMCoreUI/Atomic/Protocols/TemplateProtocol.swift b/MVMCoreUI/Atomic/Protocols/TemplateProtocol.swift index 3d1bea9c..01804b13 100644 --- a/MVMCoreUI/Atomic/Protocols/TemplateProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/TemplateProtocol.swift @@ -28,6 +28,7 @@ public extension TemplateProtocol where Self: ViewController { traverseAndAddRequiredBehaviors() var behaviorHandler = self behaviorHandler.createBehaviors(for: model, delegateObject: delegateObjectIVar) + MVMCoreUISession.sharedGlobal()?.applyGlobalBehaviors(to: self) } func decodeTemplate(using decoder: JSONDecoder, from data: Data) throws -> TemplateModel { diff --git a/MVMCoreUI/Atomic/Protocols/ViewMaskingProtocol.swift b/MVMCoreUI/Atomic/Protocols/ViewMaskingProtocol.swift new file mode 100644 index 00000000..db3073c8 --- /dev/null +++ b/MVMCoreUI/Atomic/Protocols/ViewMaskingProtocol.swift @@ -0,0 +1,21 @@ +// +// ViewMaskingProtocol.swift +// MVMCoreUI +// +// Created by Kyle on 3/7/22. +// Copyright © 2022 Verizon Wireless. All rights reserved. +// + +import Foundation + +public protocol ViewMaskingProtocol: UIView { + + var shouldMaskWhileRecording: Bool { get } + +} + +public protocol ViewMaskingContainerProtocol { + + var maskedViewsWhileRecording: [UIView] { get } + +} diff --git a/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift index fa404172..6ecce3d7 100644 --- a/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift @@ -60,7 +60,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol open override func viewForTop() -> UIView { guard let headerModel = templateModel?.header, - let molecule = ModelRegistry.createMolecule(headerModel, delegateObject: delegateObjectIVar) + let molecule = generateMoleculeView(from: headerModel) else { return super.viewForTop() } // Temporary, Default the horizontal padding @@ -73,7 +73,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol override open func viewForBottom() -> UIView { guard let footerModel = templateModel?.footer, - let molecule = ModelRegistry.createMolecule(footerModel, delegateObject: delegateObjectIVar) + let molecule = generateMoleculeView(from: footerModel) else { return super.viewForBottom() } return molecule @@ -142,7 +142,9 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol (cell as? MoleculeViewProtocol)?.reset() (cell as? MoleculeListCellProtocol)?.setLines(with: templateModel?.line, delegateObject: delegateObjectIVar, additionalData: nil, indexPath: indexPath) - (cell as? MoleculeViewProtocol)?.set(with: moleculeInfo.molecule, delegateObjectIVar, nil) + if let moleculeView = cell as? MoleculeViewProtocol { + updateMoleculeView(moleculeView, from: moleculeInfo.molecule) + } (cell as? MVMCoreViewProtocol)?.updateView(tableView.bounds.width) // Neded to fix an apple defect where the cell is not the correct size on certain devices for certain cells cell.layoutIfNeeded() diff --git a/MVMCoreUI/Atomic/Templates/TemplateModel.swift b/MVMCoreUI/Atomic/Templates/TemplateModel.swift index 27cb3183..e5e9ac5a 100644 --- a/MVMCoreUI/Atomic/Templates/TemplateModel.swift +++ b/MVMCoreUI/Atomic/Templates/TemplateModel.swift @@ -10,6 +10,7 @@ import Foundation @objcMembers open class TemplateModel: MVMControllerModelProtocol, TabPageModelProtocol { + //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -30,6 +31,9 @@ import Foundation public var tabBarHidden: Bool = false public var tabBarIndex: Int? + + // By default we mask until the server unlocks the page. + public var shouldMaskScreenWhileRecording: Bool = false //-------------------------------------------------- // MARK: - Initializer @@ -53,6 +57,7 @@ import Foundation case navigationBar case tabBarHidden case tabBarIndex + case shouldMaskScreenWhileRecording } //-------------------------------------------------- @@ -77,6 +82,7 @@ import Foundation self.tabBarHidden = tabBarHidden } tabBarIndex = try typeContainer.decodeIfPresent(Int.self, forKey: .tabBarIndex) + shouldMaskScreenWhileRecording = try typeContainer.decodeIfPresent(Bool.self, forKey: .shouldMaskScreenWhileRecording) ?? shouldMaskScreenWhileRecording } open func encode(to encoder: Encoder) throws { @@ -89,5 +95,6 @@ import Foundation try container.encodeModelIfPresent(navigationBar, forKey: .navigationBar) try container.encode(tabBarHidden, forKey: .tabBarHidden) try container.encodeIfPresent(tabBarIndex, forKey: .tabBarIndex) + try container.encode(shouldMaskScreenWhileRecording, forKey: .shouldMaskScreenWhileRecording) } } diff --git a/MVMCoreUI/BaseClasses/TextField.swift b/MVMCoreUI/BaseClasses/TextField.swift index 9174426d..5b0dc369 100644 --- a/MVMCoreUI/BaseClasses/TextField.swift +++ b/MVMCoreUI/BaseClasses/TextField.swift @@ -8,12 +8,13 @@ import UIKit -public protocol TextInputDidDeleteProtocol: class { +public protocol TextInputDidDeleteProtocol: AnyObject { func textInputDidDelete() } -@objcMembers open class TextField: UITextField { +@objcMembers open class TextField: UITextField, ViewMaskingProtocol { + //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -23,6 +24,8 @@ public protocol TextInputDidDeleteProtocol: class { /// Set to true to hide the blinking textField cursor. public var hideBlinkingCaret = false + public var shouldMaskWhileRecording: Bool = true + //-------------------------------------------------- // MARK: - Delegate //-------------------------------------------------- @@ -97,6 +100,8 @@ extension TextField: MoleculeViewProtocol { if let accessibilityIdentifier = model.accessibilityIdentifier { self.accessibilityIdentifier = accessibilityIdentifier } + + shouldMaskWhileRecording = model.shouldMaskRecordedView } open func reset() { diff --git a/MVMCoreUI/BaseClasses/View.swift b/MVMCoreUI/BaseClasses/View.swift index c4c36ae8..d7b1cd06 100644 --- a/MVMCoreUI/BaseClasses/View.swift +++ b/MVMCoreUI/BaseClasses/View.swift @@ -9,7 +9,8 @@ import UIKit -@objcMembers open class View: UIView, MoleculeViewProtocol { +@objcMembers open class View: UIView, MoleculeViewProtocol, ViewMaskingProtocol { + //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -18,6 +19,10 @@ import UIKit private var initialSetupPerformed = false + public var shouldMaskWhileRecording: Bool { + return model?.shouldMaskRecordedView ?? false + } + //-------------------------------------------------- // MARK: - Initialization //-------------------------------------------------- diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index d7e947db..b385ae29 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -230,7 +230,7 @@ import UIKit let navigationItem = createDefaultLegacyNavigationModel() model?.navigationBar = navigationItem } - + self.model?.template executeBehaviors { (behavior: PageMoleculeTransformationBehavior) in behavior.onPageNew(rootMolecules: getRootMolecules(), delegateObjectIVar) } @@ -254,6 +254,27 @@ import UIKit manager?.newDataReceived?(in: self) } + public func generateMoleculeView(from model: MoleculeModelProtocol) -> MoleculeViewProtocol? { + executeBehaviors { (behavior: PageMoleculeTransformationBehavior) in + behavior.willSetupMolecule(with: model, updating: nil) + } + guard let moleculeView = ModelRegistry.createMolecule(model, delegateObject: delegateObjectIVar) else { return nil } + executeBehaviors { (behavior: PageMoleculeTransformationBehavior) in + behavior.didSetupMolecule(view: moleculeView, withModel: model) + } + return moleculeView + } + + public func updateMoleculeView(_ view: MoleculeViewProtocol, from model: MoleculeModelProtocol) { + executeBehaviors { (behavior: PageMoleculeTransformationBehavior) in + behavior.willSetupMolecule(with: model, updating: view) + } + view.set(with: model, delegateObjectIVar, nil) + executeBehaviors { (behavior: PageMoleculeTransformationBehavior) in + behavior.didSetupMolecule(view: view, withModel: model) + } + } + //-------------------------------------------------- // MARK: - Navigation Item //-------------------------------------------------- diff --git a/MVMCoreUI/Behaviors/Protocols/PageBehaviorHandlerProtocol.swift b/MVMCoreUI/Behaviors/Protocols/PageBehaviorHandlerProtocol.swift index eb244cbf..b8f117d6 100644 --- a/MVMCoreUI/Behaviors/Protocols/PageBehaviorHandlerProtocol.swift +++ b/MVMCoreUI/Behaviors/Protocols/PageBehaviorHandlerProtocol.swift @@ -15,7 +15,6 @@ public extension PageBehaviorHandlerProtocol { /// Creates the behaviors and sets the variable. mutating func createBehaviors(for model: PageBehaviorHandlerModelProtocol, delegateObject: MVMCoreUIDelegateObject?) { guard let behaviorModels = model.behaviors else { - behaviors = nil return } @@ -32,6 +31,9 @@ public extension PageBehaviorHandlerProtocol { } } } - self.behaviors = behaviors.count > 0 ? behaviors : nil + + if behaviors.count > 0 { + self.behaviors = behaviors + (self.behaviors ?? []) + } } } diff --git a/MVMCoreUI/Behaviors/Protocols/PageBehaviorProtocol.swift b/MVMCoreUI/Behaviors/Protocols/PageBehaviorProtocol.swift index 3f14f3cc..65773aa0 100644 --- a/MVMCoreUI/Behaviors/Protocols/PageBehaviorProtocol.swift +++ b/MVMCoreUI/Behaviors/Protocols/PageBehaviorProtocol.swift @@ -20,6 +20,15 @@ public protocol PageBehaviorProtocol: ModelHandlerProtocol { public protocol PageMoleculeTransformationBehavior: PageBehaviorProtocol { func onPageNew(rootMolecules: [MoleculeModelProtocol], _ delegateObject: MVMCoreUIDelegateObject) + func willSetupMolecule(with model: MoleculeModelProtocol, updating view: MoleculeViewProtocol?) + func didSetupMolecule(view: MoleculeViewProtocol, withModel: MoleculeModelProtocol) +} + +public extension PageMoleculeTransformationBehavior { + // All optional. + func onPageNew(rootMolecules: [MoleculeModelProtocol], _ delegateObject: MVMCoreUIDelegateObject) {} + func willSetupMolecule(with model: MoleculeModelProtocol, updating view: MoleculeViewProtocol?) {} + func didSetupMolecule(view: MoleculeViewProtocol, withModel: MoleculeModelProtocol) {} } public protocol PageVisibilityBehavior: PageBehaviorProtocol { diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUISession.h b/MVMCoreUI/OtherHandlers/MVMCoreUISession.h index ca2db26e..a81c8ee2 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUISession.h +++ b/MVMCoreUI/OtherHandlers/MVMCoreUISession.h @@ -13,6 +13,7 @@ @class MFViewController; @class MFLoadingViewController; @class NavigationController; + NS_ASSUME_NONNULL_BEGIN @interface MVMCoreUISession : MVMCoreSessionObject @@ -25,18 +26,21 @@ NS_ASSUME_NONNULL_BEGIN /// Tracks the current page type the user is currently viewing. KVO compliant. @property (nonatomic, strong, nullable) NSString *currentPageType; -// for handscroll Animation on subclasses of MFScrollingViewController +/// for handscroll Animation on subclasses of MFScrollingViewController @property (assign, nonatomic) BOOL enableHandScrollAnimation; -//indicates if the app launched successfully +/// indicates if the app launched successfully @property (assign, nonatomic) BOOL launchAppLoadedSuccessfully; -// Allows a global overload of the title view of navigation item. +/// Allows a global overload of the title view of navigation item. - (nullable UIView *)titleViewForController:(nonnull MFViewController *)controller; -// Sets up the session as delegate for standard load view controller. Pass the view controller that will be used to present and will be disabled when load view is presented. +/// Sets up the session as delegate for standard load view controller. Pass the view controller that will be used to present and will be disabled when load view is presented. - (void)setupAsStandardLoadViewDelegate:(nonnull UIViewController *)mainViewController; +/// Applies additional behaviors to a controller according to the session. Allows for packages to add additional cross cutting concerns. +- (void)applyGlobalBehaviorsToController:(nonnull UIViewController *)viewController; + @end NS_ASSUME_NONNULL_END diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUISession.m b/MVMCoreUI/OtherHandlers/MVMCoreUISession.m index 433b1ab1..957b5c19 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUISession.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUISession.m @@ -62,4 +62,8 @@ self.mainViewController.view.userInteractionEnabled = YES; } +- (void)applyGlobalBehaviorsToController:(nonnull UIViewController *)viewController { + // Allow extending frameworks to apply behaviors to add cross cutting concerns to the base controllers. +} + @end