From c276b09d7433fb3103e9c606a3337f8beb1e0948 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Mon, 2 May 2022 17:39:03 -0400 Subject: [PATCH 1/7] reorganizing defaults --- .../Protocols/MoleculeDelegateProtocol.swift | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/MVMCoreUI/Atomic/Protocols/MoleculeDelegateProtocol.swift b/MVMCoreUI/Atomic/Protocols/MoleculeDelegateProtocol.swift index 1d0a3f61..f2f01b6c 100644 --- a/MVMCoreUI/Atomic/Protocols/MoleculeDelegateProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/MoleculeDelegateProtocol.swift @@ -23,4 +23,33 @@ public protocol MoleculeDelegateProtocol: AnyObject { extension MoleculeDelegateProtocol { public func moleculeLayoutUpdated(_ molecule: MoleculeViewProtocol) { } + + public func getModuleWithName(_ moleculeName: String) -> MoleculeModelProtocol? { + let moduleJSON: [AnyHashable: Any]? = getModuleWithName(moleculeName) + guard let moduleJSON = moduleJSON as? [String: Any], + let moleculeName = moduleJSON.optionalStringForKey("moleculeName"), + let modelType = ModelRegistry.getType(for: moleculeName, with: MoleculeModelProtocol.self) + else { return nil } + + do { + return try modelType.decode(jsonDict: moduleJSON as [String : Any]) as? MoleculeModelProtocol + } catch { + MVMCoreUILoggingHandler.logDebugMessage(withDelegate: "error: \(error)") + } + + return nil + } +} + +extension MoleculeDelegateProtocol where Self: TemplateProtocol { + public func getRootMolecules() -> [MoleculeModelProtocol] { + templateModel?.rootMolecules ?? [] + } +} + +extension MoleculeDelegateProtocol where Self: MVMCoreViewControllerProtocol { + public func getModuleWithName(_ name: String?) -> [AnyHashable : Any]? { + guard let name = name else { return nil } + return loadObject??.modulesJSON?.optionalDictionaryForKey(name) + } } From 35f1cc5c178a0827fdc2c817984351204c547997 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Mon, 2 May 2022 17:43:18 -0400 Subject: [PATCH 2/7] template protocol update --- .../Atomic/Protocols/TemplateProtocol.swift | 47 ++++++++++--------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/MVMCoreUI/Atomic/Protocols/TemplateProtocol.swift b/MVMCoreUI/Atomic/Protocols/TemplateProtocol.swift index 3d1bea9c..06660715 100644 --- a/MVMCoreUI/Atomic/Protocols/TemplateProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/TemplateProtocol.swift @@ -8,43 +8,46 @@ import Foundation -public protocol TemplateProtocol: AnyObject { +public protocol TemplateProtocol: AnyObject, PageProtocol { associatedtype TemplateModel: TemplateModelProtocol var templateModel: TemplateModel? { get set } func decodeTemplate(using decoder: JSONDecoder, from data: Data) throws -> TemplateModel } -public extension TemplateProtocol where Self: ViewController { +public extension TemplateProtocol { + // Utilize existing underlying property + var templateModel: TemplateModel? { + get { + pageModel as? TemplateModel + } + set { + var mutableSelf = self + mutableSelf.pageModel = newValue + } + } + + /// Helper function to do common parsing logic. func parseTemplate(json: [AnyHashable: Any]?) throws { guard let pageJSON = json else { return } + let delegateObject = (self as? MVMCoreViewControllerProtocol)?.delegateObject?() as? MVMCoreUIDelegateObject let data = try JSONSerialization.data(withJSONObject: pageJSON) let decoder = JSONDecoder() - try decoder.add(delegateObject: delegateObjectIVar) + if let delegateObject = delegateObject { + // Add the delegate to access mid parsing if applicable. + try decoder.add(delegateObject: delegateObject) + } templateModel = try decodeTemplate(using: decoder, from: data) - model = templateModel as? MVMControllerModelProtocol - guard let model = model else { return } - traverseAndAddRequiredBehaviors() - var behaviorHandler = self - behaviorHandler.createBehaviors(for: model, delegateObject: delegateObjectIVar) + + // Add additional required behaviors if applicable. + guard var behaviorHandlerModel = templateModel as? TemplateModelProtocol & PageBehaviorHandlerModelProtocol, + var behaviorHandler = self as? PageBehaviorHandlerProtocol else { return } + behaviorHandlerModel.traverseAndAddRequiredBehaviors() + behaviorHandler.createBehaviors(for: behaviorHandlerModel, delegateObject: delegateObject) } func decodeTemplate(using decoder: JSONDecoder, from data: Data) throws -> TemplateModel { try decoder.decode(TemplateModel.self, from: data) } - - /// Traverses all models and adds any required behavior models. - func traverseAndAddRequiredBehaviors() { - guard var model = model else { return } - let behaviorModels: [PageBehaviorModelProtocol] = model.reduceDepthFirstTraverse(options: .childFirst, depth: 0, initialResult: []) { (accumulator, molecule, depth) in - if let behaviorRequirer = molecule as? PageBehaviorProtocolRequirer { - return accumulator + behaviorRequirer.getRequiredBehaviors() - } - return accumulator - } - for behavior in behaviorModels { - model.add(behavior: behavior) - } - } } From 27f7c223400873b45ad71f7369ab90f6aff38fa8 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Mon, 2 May 2022 17:47:25 -0400 Subject: [PATCH 3/7] Change conflicting name TemplateModel to BaseTemplateModel --- MVMCoreUI.xcodeproj/project.pbxproj | 8 ++++---- .../{TemplateModel.swift => BaseTemplateModel.swift} | 4 ++-- MVMCoreUI/Atomic/Templates/CollectionTemplate.swift | 1 - MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift | 4 +--- MVMCoreUI/Atomic/Templates/MoleculeStackTemplate.swift | 1 - MVMCoreUI/Atomic/Templates/ThreeLayerModelBase.swift | 2 +- MVMCoreUI/Atomic/Templates/ThreeLayerTemplate.swift | 5 ----- 7 files changed, 8 insertions(+), 17 deletions(-) rename MVMCoreUI/Atomic/Templates/{TemplateModel.swift => BaseTemplateModel.swift} (96%) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 0e5dacbb..aa280b9a 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -345,7 +345,7 @@ D22479942316AE5E003FCCF9 /* NSLayoutConstraintExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22479932316AE5E003FCCF9 /* NSLayoutConstraintExtension.swift */; }; D22479962316AF6E003FCCF9 /* HeadlineBodyLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22479952316AF6D003FCCF9 /* HeadlineBodyLink.swift */; }; D224799B231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D224799A231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift */; }; - D22D8393241C27B100D3DF69 /* TemplateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22D8392241C27B100D3DF69 /* TemplateModel.swift */; }; + D22D8393241C27B100D3DF69 /* BaseTemplateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22D8392241C27B100D3DF69 /* BaseTemplateModel.swift */; }; D22D8395241FB41200D3DF69 /* UIStackView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22D8394241FB41200D3DF69 /* UIStackView+Extension.swift */; }; D23118B325124E18001C8440 /* Notification.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23118B225124E18001C8440 /* Notification.swift */; }; D2351C7A24A4D433007DF0BC /* ListRightVariableToggleAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2351C7924A4D433007DF0BC /* ListRightVariableToggleAllTextAndLinksModel.swift */; }; @@ -930,7 +930,7 @@ D22479932316AE5E003FCCF9 /* NSLayoutConstraintExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSLayoutConstraintExtension.swift; sourceTree = ""; }; D22479952316AF6D003FCCF9 /* HeadlineBodyLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyLink.swift; sourceTree = ""; }; D224799A231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccordionMoleculeTableViewCell.swift; sourceTree = ""; }; - D22D8392241C27B100D3DF69 /* TemplateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateModel.swift; sourceTree = ""; }; + D22D8392241C27B100D3DF69 /* BaseTemplateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseTemplateModel.swift; sourceTree = ""; }; D22D8394241FB41200D3DF69 /* UIStackView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIStackView+Extension.swift"; sourceTree = ""; }; D23118B225124E18001C8440 /* Notification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notification.swift; sourceTree = ""; }; D2351C7924A4D433007DF0BC /* ListRightVariableToggleAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariableToggleAllTextAndLinksModel.swift; sourceTree = ""; }; @@ -1969,7 +1969,7 @@ D29DF0DF21E418B2003B2FB9 /* Templates */ = { isa = PBXGroup; children = ( - D22D8392241C27B100D3DF69 /* TemplateModel.swift */, + D22D8392241C27B100D3DF69 /* BaseTemplateModel.swift */, D2092356244FA1EF0044AD09 /* ThreeLayerModelBase.swift */, 014AA72823C5059B006F3E93 /* StackPageTemplateModel.swift */, D2A5146022121FBF00345BFB /* MoleculeStackTemplate.swift */, @@ -3057,7 +3057,7 @@ D23EA7FE247EBBB700D60C34 /* NavigationLabelButtonModel.swift in Sources */, D28A839123CD4FD400DFE4FC /* CornerLabelsModel.swift in Sources */, 012A88F123985E0100FE3DA1 /* Color.swift in Sources */, - D22D8393241C27B100D3DF69 /* TemplateModel.swift in Sources */, + D22D8393241C27B100D3DF69 /* BaseTemplateModel.swift in Sources */, 012A889C23889E8400FE3DA1 /* TemplateModelProtocol.swift in Sources */, EAA0CFB1275E823A00D65EB0 /* HideFormFieldEffectModel.swift in Sources */, D23A8FFB26123189007E14CE /* PageBehaviorModelProtocol.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Templates/TemplateModel.swift b/MVMCoreUI/Atomic/Templates/BaseTemplateModel.swift similarity index 96% rename from MVMCoreUI/Atomic/Templates/TemplateModel.swift rename to MVMCoreUI/Atomic/Templates/BaseTemplateModel.swift index 27cb3183..21024474 100644 --- a/MVMCoreUI/Atomic/Templates/TemplateModel.swift +++ b/MVMCoreUI/Atomic/Templates/BaseTemplateModel.swift @@ -1,5 +1,5 @@ // -// TemplateModel.swift +// BaseTemplateModel.swift // MVMCoreUI // // Created by Scott Pfeil on 3/13/20. @@ -9,7 +9,7 @@ import Foundation -@objcMembers open class TemplateModel: MVMControllerModelProtocol, TabPageModelProtocol { +@objcMembers open class BaseTemplateModel: MVMControllerModelProtocol, TabPageModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Templates/CollectionTemplate.swift b/MVMCoreUI/Atomic/Templates/CollectionTemplate.swift index f3bd5d83..b1128d8e 100644 --- a/MVMCoreUI/Atomic/Templates/CollectionTemplate.swift +++ b/MVMCoreUI/Atomic/Templates/CollectionTemplate.swift @@ -13,7 +13,6 @@ //-------------------------------------------------- public typealias TemplateModel = CollectionTemplateModel - public var templateModel: CollectionTemplateModel? public var moleculesInfo: [(identifier: String, class: AnyClass, molecule: (CollectionItemModelProtocol & MoleculeModelProtocol))]? diff --git a/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift index fa404172..d797038d 100644 --- a/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift @@ -19,9 +19,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol public var moleculesInfo: [MoleculeInfo]? var observer: NSKeyValueObservation? - - public var templateModel: ListPageTemplateModel? - + //-------------------------------------------------- // MARK: - Computed Properties //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Templates/MoleculeStackTemplate.swift b/MVMCoreUI/Atomic/Templates/MoleculeStackTemplate.swift index 046469a8..61b247fb 100644 --- a/MVMCoreUI/Atomic/Templates/MoleculeStackTemplate.swift +++ b/MVMCoreUI/Atomic/Templates/MoleculeStackTemplate.swift @@ -15,7 +15,6 @@ open class MoleculeStackTemplate: ThreeLayerViewController, TemplateProtocol { //-------------------------------------------------- var observer: NSKeyValueObservation? - public var templateModel: StackPageTemplateModel? //-------------------------------------------------- // MARK: - Lifecycle diff --git a/MVMCoreUI/Atomic/Templates/ThreeLayerModelBase.swift b/MVMCoreUI/Atomic/Templates/ThreeLayerModelBase.swift index 06d813ef..9f130089 100644 --- a/MVMCoreUI/Atomic/Templates/ThreeLayerModelBase.swift +++ b/MVMCoreUI/Atomic/Templates/ThreeLayerModelBase.swift @@ -7,7 +7,7 @@ // -@objcMembers open class ThreeLayerModelBase: TemplateModel, ThreeLayerTemplateModelProtocol { +@objcMembers open class ThreeLayerModelBase: BaseTemplateModel, ThreeLayerTemplateModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Templates/ThreeLayerTemplate.swift b/MVMCoreUI/Atomic/Templates/ThreeLayerTemplate.swift index 502b269f..4d1a4a66 100644 --- a/MVMCoreUI/Atomic/Templates/ThreeLayerTemplate.swift +++ b/MVMCoreUI/Atomic/Templates/ThreeLayerTemplate.swift @@ -9,11 +9,6 @@ import UIKit @objcMembers open class ThreeLayerTemplate: ThreeLayerViewController, TemplateProtocol { - //-------------------------------------------------- - // MARK: - Properties - //-------------------------------------------------- - - public var templateModel: TemplateModel? //-------------------------------------------------- // MARK: - Lifecycle From d1239eda74a60f53a70f5b174b6fe7e7f7ebc5fd Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Mon, 2 May 2022 17:50:00 -0400 Subject: [PATCH 4/7] move functions to default --- .../BaseControllers/ViewController.swift | 28 ------------------- 1 file changed, 28 deletions(-) diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index d7e947db..26ab983f 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -484,26 +484,6 @@ import UIKit model?.rootMolecules ?? [] } - open func getModuleWithName(_ name: String?) -> [AnyHashable: Any]? { - guard let name = name else { return nil } - return loadObject?.modulesJSON?.optionalDictionaryForKey(name) - } - - open func getModuleWithName(_ moleculeName: String) -> MoleculeModelProtocol? { - guard let moduleJSON = loadObject?.modulesJSON?.optionalDictionaryForKey(moleculeName), - let moleculeName = moduleJSON.optionalStringForKey("moleculeName"), - let modelType = ModelRegistry.getType(for: moleculeName, with: MoleculeModelProtocol.self) - else { return nil } - - do { - return try modelType.decode(jsonDict: moduleJSON) as? MoleculeModelProtocol - } catch { - MVMCoreUILoggingHandler.logDebugMessage(withDelegate: "error: \(error)") - } - - return nil - } - // Needed otherwise when subclassed, the extension gets called. open func moleculeLayoutUpdated(_ molecule: MoleculeViewProtocol) { } @@ -618,12 +598,4 @@ import UIKit selectedField = nil } } - - //-------------------------------------------------- - // MARK: - Behavior Execution - //-------------------------------------------------- - - public func executeBehaviors(_ behaviorBlock: (_ behavior: T) -> Void) { - behaviors?.compactMap { $0 as? T }.forEach { behaviorBlock($0) } - } } From 48388343ef06794a1b9a494135d7d1c0f7d1bc41 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Mon, 2 May 2022 17:51:08 -0400 Subject: [PATCH 5/7] Move function for scoping purposes --- .../PageBehaviorHandlerModelProtocol.swift | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/MVMCoreUI/Behaviors/Protocols/PageBehaviorHandlerModelProtocol.swift b/MVMCoreUI/Behaviors/Protocols/PageBehaviorHandlerModelProtocol.swift index d9b8da9f..bb752694 100644 --- a/MVMCoreUI/Behaviors/Protocols/PageBehaviorHandlerModelProtocol.swift +++ b/MVMCoreUI/Behaviors/Protocols/PageBehaviorHandlerModelProtocol.swift @@ -23,3 +23,19 @@ public extension PageBehaviorHandlerModelProtocol { self.behaviors = newBehaviors } } + +public extension PageBehaviorHandlerModelProtocol where Self: MoleculeTreeTraversalProtocol { + + /// Traverses all models and adds any required behavior models. + mutating func traverseAndAddRequiredBehaviors() { + let behaviorModels: [PageBehaviorModelProtocol] = reduceDepthFirstTraverse(options: .childFirst, depth: 0, initialResult: []) { (accumulator, molecule, depth) in + if let behaviorRequirer = molecule as? PageBehaviorProtocolRequirer { + return accumulator + behaviorRequirer.getRequiredBehaviors() + } + return accumulator + } + for behavior in behaviorModels { + add(behavior: behavior) + } + } +} From 6762082b7c24e248b5c2922bde7d8fd4e0f27715 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Mon, 2 May 2022 17:52:15 -0400 Subject: [PATCH 6/7] move function behavior for scoping --- .../Behaviors/Protocols/PageBehaviorHandlerProtocol.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/MVMCoreUI/Behaviors/Protocols/PageBehaviorHandlerProtocol.swift b/MVMCoreUI/Behaviors/Protocols/PageBehaviorHandlerProtocol.swift index eb244cbf..cdabba87 100644 --- a/MVMCoreUI/Behaviors/Protocols/PageBehaviorHandlerProtocol.swift +++ b/MVMCoreUI/Behaviors/Protocols/PageBehaviorHandlerProtocol.swift @@ -34,4 +34,9 @@ public extension PageBehaviorHandlerProtocol { } self.behaviors = behaviors.count > 0 ? behaviors : nil } + + /// Executes all behaviors of type. + public func executeBehaviors(_ behaviorBlock: (_ behavior: T) -> Void) { + behaviors?.compactMap { $0 as? T }.forEach { behaviorBlock($0) } + } } From 677c352b9eae42227b3722b08477d868ba4b9014 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Mon, 2 May 2022 17:54:37 -0400 Subject: [PATCH 7/7] convenience functions --- .../Behaviors/Protocols/PageBehaviorHandlerProtocol.swift | 2 +- MVMCoreUI/Behaviors/Protocols/PageBehaviorProtocol.swift | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Behaviors/Protocols/PageBehaviorHandlerProtocol.swift b/MVMCoreUI/Behaviors/Protocols/PageBehaviorHandlerProtocol.swift index cdabba87..79f3364f 100644 --- a/MVMCoreUI/Behaviors/Protocols/PageBehaviorHandlerProtocol.swift +++ b/MVMCoreUI/Behaviors/Protocols/PageBehaviorHandlerProtocol.swift @@ -36,7 +36,7 @@ public extension PageBehaviorHandlerProtocol { } /// Executes all behaviors of type. - public func executeBehaviors(_ behaviorBlock: (_ behavior: T) -> Void) { + func executeBehaviors(_ behaviorBlock: (_ behavior: T) -> Void) { behaviors?.compactMap { $0 as? T }.forEach { behaviorBlock($0) } } } diff --git a/MVMCoreUI/Behaviors/Protocols/PageBehaviorProtocol.swift b/MVMCoreUI/Behaviors/Protocols/PageBehaviorProtocol.swift index 3f14f3cc..76bc7f84 100644 --- a/MVMCoreUI/Behaviors/Protocols/PageBehaviorProtocol.swift +++ b/MVMCoreUI/Behaviors/Protocols/PageBehaviorProtocol.swift @@ -50,8 +50,11 @@ public protocol PageCustomActionHandlerBehavior: PageBehaviorProtocol { } public extension MVMCoreUIDelegateObject { + var behaviorModelDelegate: PageBehaviorHandlerModelProtocol? { + (moleculeDelegate as? PageProtocol)?.pageModel as? PageBehaviorHandlerModelProtocol + } weak var behaviorTemplateDelegate: (PageBehaviorHandlerProtocol & NSObjectProtocol)? { - (moleculeDelegate as? PageProtocol)?.pageModel as? (PageBehaviorHandlerProtocol & NSObjectProtocol) + moleculeDelegate as? (PageBehaviorHandlerProtocol & NSObjectProtocol) } }