diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index d45f3185..7ea64bcf 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -39,7 +39,6 @@ D28B4F8B21FF967C00712C7A /* MVMCoreUIObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D28B4F8921FF967C00712C7A /* MVMCoreUIObject.m */; }; D296E13C229598BF0051EBE7 /* MoleculeListCellProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D296E13B2295969C0051EBE7 /* MoleculeListCellProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; D296E1412295EBBA0051EBE7 /* MoleculeDelegateProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D296E1402295EBBA0051EBE7 /* MoleculeDelegateProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D296E143229729C30051EBE7 /* MoleculeMappingObject+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D296E142229729C30051EBE7 /* MoleculeMappingObject+Extension.swift */; }; D296E14722A5984C0051EBE7 /* MVMCoreUIViewConstrainingProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D296E14622A597490051EBE7 /* MVMCoreUIViewConstrainingProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; D29770C821F7C4AE00B2F0D0 /* TopLabelsView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29770C621F7C4AE00B2F0D0 /* TopLabelsView.m */; }; D29770C921F7C4AE00B2F0D0 /* TopLabelsView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29770C721F7C4AE00B2F0D0 /* TopLabelsView.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -49,6 +48,7 @@ D29770F521F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D29770F121F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsViewController.m */; }; D29770FC21F7C77400B2F0D0 /* MVMCoreUITextFieldView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29770FA21F7C77400B2F0D0 /* MVMCoreUITextFieldView.m */; }; D29770FD21F7C77400B2F0D0 /* MVMCoreUITextFieldView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29770FB21F7C77400B2F0D0 /* MVMCoreUITextFieldView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D29B771022C281F400D6ACE0 /* ModuleMolecule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D29B770F22C281F400D6ACE0 /* ModuleMolecule.swift */; }; D29DF0D121E404D4003B2FB9 /* MVMCoreUI.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF0CF21E404D4003B2FB9 /* MVMCoreUI.h */; settings = {ATTRIBUTES = (Public, ); }; }; D29DF0E621E4F3C7003B2FB9 /* MVMCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D29DF0E521E4F3C7003B2FB9 /* MVMCore.framework */; }; D29DF11521E6805F003B2FB9 /* UIColor+MFConvenience.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF11121E6805F003B2FB9 /* UIColor+MFConvenience.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -207,7 +207,6 @@ D28B4F8921FF967C00712C7A /* MVMCoreUIObject.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIObject.m; sourceTree = ""; }; D296E13B2295969C0051EBE7 /* MoleculeListCellProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MoleculeListCellProtocol.h; sourceTree = ""; }; D296E1402295EBBA0051EBE7 /* MoleculeDelegateProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MoleculeDelegateProtocol.h; sourceTree = ""; }; - D296E142229729C30051EBE7 /* MoleculeMappingObject+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MoleculeMappingObject+Extension.swift"; sourceTree = ""; }; D296E14622A597490051EBE7 /* MVMCoreUIViewConstrainingProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIViewConstrainingProtocol.h; sourceTree = ""; }; D29770C621F7C4AE00B2F0D0 /* TopLabelsView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TopLabelsView.m; sourceTree = ""; }; D29770C721F7C4AE00B2F0D0 /* TopLabelsView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TopLabelsView.h; sourceTree = ""; }; @@ -217,6 +216,7 @@ D29770F121F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TopLabelsAndBottomButtonsViewController.m; sourceTree = ""; }; D29770FA21F7C77400B2F0D0 /* MVMCoreUITextFieldView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUITextFieldView.m; sourceTree = ""; }; D29770FB21F7C77400B2F0D0 /* MVMCoreUITextFieldView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUITextFieldView.h; sourceTree = ""; }; + D29B770F22C281F400D6ACE0 /* ModuleMolecule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModuleMolecule.swift; sourceTree = ""; }; D29DF0CC21E404D4003B2FB9 /* MVMCoreUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MVMCoreUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D29DF0CF21E404D4003B2FB9 /* MVMCoreUI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUI.h; sourceTree = ""; }; D29DF0D021E404D4003B2FB9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -471,6 +471,7 @@ D2E1FADC2268B25E00AEFD8C /* MoleculeTableViewCell.swift */, B8200E142280C4CF007245F4 /* ProgressBar.swift */, B8200E182281DC1A007245F4 /* ProgressBarWithLabel.swift */, + D29B770F22C281F400D6ACE0 /* ModuleMolecule.swift */, ); path = Molecules; sourceTree = ""; @@ -679,7 +680,6 @@ D296E1402295EBBA0051EBE7 /* MoleculeDelegateProtocol.h */, D2A514562211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.h */, D2A514572211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.m */, - D296E142229729C30051EBE7 /* MoleculeMappingObject+Extension.swift */, ); path = OtherHandlers; sourceTree = ""; @@ -901,6 +901,7 @@ D29DF32121ED0CBA003B2FB9 /* LabelView.m in Sources */, DBC4391822442197001AB423 /* CaretView.swift in Sources */, D29770F221F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsTableViewController.m in Sources */, + D29B771022C281F400D6ACE0 /* ModuleMolecule.swift in Sources */, DBC4391922442197001AB423 /* DashLine.swift in Sources */, D29DF29621E7ADB8003B2FB9 /* StackableViewController.m in Sources */, D2E1FADB2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift in Sources */, @@ -944,7 +945,6 @@ D29DF28321E7AB24003B2FB9 /* MVMCoreUICommonViewsUtility.m in Sources */, D206997821FB8A0B00CAE0DE /* MVMCoreUINavigationController.m in Sources */, D29DF27A21E7A533003B2FB9 /* MVMCoreUISession.m in Sources */, - D296E143229729C30051EBE7 /* MoleculeMappingObject+Extension.swift in Sources */, 01DF55E021F8FAA800CC099B /* MFTextFieldListView.swift in Sources */, D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */, D29DF2C921E7BFC6003B2FB9 /* MFSizeObject.m in Sources */, diff --git a/MVMCoreUI/Atoms/Views/ViewConstrainingView.m b/MVMCoreUI/Atoms/Views/ViewConstrainingView.m index b2b6fea8..2f97c09a 100644 --- a/MVMCoreUI/Atoms/Views/ViewConstrainingView.m +++ b/MVMCoreUI/Atoms/Views/ViewConstrainingView.m @@ -48,11 +48,21 @@ #pragma mark - Constraining - (void)pinViewToSuperView:(nonnull UIView *)view { - NSDictionary *dictionary = [NSLayoutConstraint constraintPinSubviewToSuperview:view]; - self.leftPin = dictionary[ConstraintLeading]; - self.topPin = dictionary[ConstraintTop]; - self.bottomPin = dictionary[ConstraintBot]; - self.rightPin = dictionary[ConstraintTrailing]; + NSLayoutConstraint *constraint = [view.leftAnchor constraintEqualToAnchor:view.superview.leftAnchor]; + constraint.active = YES; + self.leftPin = constraint; + + constraint = [view.topAnchor constraintEqualToAnchor:view.superview.topAnchor]; + constraint.active = YES; + self.topPin = constraint; + + constraint = [view.superview.rightAnchor constraintEqualToAnchor:view.rightAnchor]; + constraint.active = YES; + self.rightPin = constraint; + + constraint = [view.superview.bottomAnchor constraintEqualToAnchor:view.bottomAnchor]; + constraint.active = YES; + self.bottomPin = constraint; self.alignCenterPin = [view.centerXAnchor constraintEqualToAnchor:view.superview.centerXAnchor]; self.alignCenterLeftPin = [view.leftAnchor constraintGreaterThanOrEqualToAnchor:view.superview.leftAnchor]; diff --git a/MVMCoreUI/Molecules/ButtonView.swift b/MVMCoreUI/Molecules/ButtonView.swift index 4596164c..d9163ae4 100644 --- a/MVMCoreUI/Molecules/ButtonView.swift +++ b/MVMCoreUI/Molecules/ButtonView.swift @@ -64,7 +64,7 @@ import UIKit primaryButton?.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) } - public override static func estimatedHeight(forRow json: [AnyHashable : Any]?) -> CGFloat { + public override static func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { return 42 } diff --git a/MVMCoreUI/Molecules/MVMCoreUIMoleculeViewProtocol.h b/MVMCoreUI/Molecules/MVMCoreUIMoleculeViewProtocol.h index 9140245e..4c69b1f7 100644 --- a/MVMCoreUI/Molecules/MVMCoreUIMoleculeViewProtocol.h +++ b/MVMCoreUI/Molecules/MVMCoreUIMoleculeViewProtocol.h @@ -9,6 +9,7 @@ #import @import MVMCore.MVMCoreViewProtocol; @class MVMCoreUIDelegateObject; +@class MVMCoreErrorObject; @protocol MVMCoreUIMoleculeViewProtocol @@ -25,11 +26,14 @@ /// For the molecule list to load more efficiently. -+ (CGFloat)estimatedHeightForRow:(nullable NSDictionary *)json; ++ (CGFloat)estimatedHeightForRow:(nullable NSDictionary *)json delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject; /// Allows the molecule to set its name for reuse. Default could be moleculeName. + (nullable NSString *)nameForReuse:(nullable NSDictionary *)molecule delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject; +/// Can return the required modules ++ (nullable NSArray *)requiredModules:(nullable NSDictionary *)json delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject error:(MVMCoreErrorObject *_Nullable *_Nullable)error; + @end diff --git a/MVMCoreUI/Molecules/ModuleMolecule.swift b/MVMCoreUI/Molecules/ModuleMolecule.swift new file mode 100644 index 00000000..316f3f2a --- /dev/null +++ b/MVMCoreUI/Molecules/ModuleMolecule.swift @@ -0,0 +1,98 @@ +// +// ModuleMolecule.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 6/25/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import UIKit + +open class ModuleMolecule: ViewConstrainingView { + + open var molecule: (UIView & MVMCoreUIMoleculeViewProtocol)? + + open override func updateView(_ size: CGFloat) { + super.updateView(size) + molecule?.updateView(size) + } + + // MARK: - MVMCoreUIMoleculeViewProtocol + open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { + super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + + guard let moduleName = json?.optionalStringForKey("moduleName"), let module = delegateObject?.moleculeDelegate?.getModuleWithName(moduleName) else { + // Critical error + return + } + + if molecule == nil { + if let moleculeView = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: module, delegateObject: delegateObject, constrainIfNeeded: true) { + addSubview(moleculeView) + NSLayoutConstraint.activate(Array(NSLayoutConstraint.pinView(toSuperview: moleculeView, useMargins: false).values)) + molecule = moleculeView + } + } else { + molecule?.setWithJSON(module, delegateObject: delegateObject, additionalData: additionalData) + } + } + + open override func setAsMolecule() { + super.setAsMolecule() + updateViewHorizontalDefaults = false + molecule?.setAsMolecule?() + } + + open override func reset() { + super.reset() + molecule?.reset?() + } + + public override static func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + guard let moduleName = json?.optionalStringForKey("moduleName"), let module = delegateObject?.moleculeDelegate?.getModuleWithName(moduleName) else { + // Critical error + return 0 + } + return MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: module)?.estimatedHeight?(forRow: module, delegateObject: delegateObject) ?? 80 + } + + public override static func name(forReuse molecule: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> String? { + guard let moduleName = molecule?.optionalStringForKey("moduleName"), let module = delegateObject?.moleculeDelegate?.getModuleWithName(moduleName) else { + // Critical error + return "moduleMolecule<>" + } + return "moduleMolecule<" + (MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: module)?.name?(forReuse: module, delegateObject: delegateObject) ?? module.stringForkey(KeyMoleculeName)) + ">" + } + + public override static func requiredModules(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { + guard let moduleName = json?.optionalStringForKey("moduleName"), let _ = delegateObject?.moleculeDelegate?.getModuleWithName(moduleName) else { + if let errorObject = MVMCoreErrorObject(title: nil, message: MVMCoreGetterUtility.hardcodedString(withKey: HardcodedErrorUnableToProcess), code: CoreUIErrorCode.ErrorCodeModuleMolecule.rawValue, domain: ErrorDomainNative, location: String(describing: self)) { + error?.pointee = errorObject + MVMCoreUILoggingHandler.shared()?.addError(toLog: errorObject) + } + return nil + } + return [moduleName] + } + + // MARK: - MVMCoreUIViewConstrainingProtocol + open override func useStandardConstraints() -> Bool { + return (molecule as? MVMCoreUIViewConstrainingProtocol)?.useStandardConstraints?() ?? true + } + + open override func alignHorizontal(_ alignment: UIStackView.Alignment) { + (molecule as? MVMCoreUIViewConstrainingProtocol)?.alignHorizontal?(alignment) + } + + open override func alignVertical(_ alignment: UIStackView.Alignment) { + (molecule as? MVMCoreUIViewConstrainingProtocol)?.alignVertical?(alignment) + } + + open override func shouldSetHorizontalMargins(_ shouldSet: Bool) { + (molecule as? MVMCoreUIViewConstrainingProtocol)?.shouldSetHorizontalMargins?(shouldSet) + } + + open override func shouldSetVerticalMargins(_ shouldSet: Bool) { + (molecule as? MVMCoreUIViewConstrainingProtocol)?.shouldSetVerticalMargins?(shouldSet) + } +} diff --git a/MVMCoreUI/Molecules/MoleculeStackView.swift b/MVMCoreUI/Molecules/MoleculeStackView.swift index 8c6e76bf..ad667d16 100644 --- a/MVMCoreUI/Molecules/MoleculeStackView.swift +++ b/MVMCoreUI/Molecules/MoleculeStackView.swift @@ -47,6 +47,7 @@ public class MoleculeStackView: ViewConstrainingView { /// For setting the direction of the stack var axis: NSLayoutConstraint.Axis = .vertical { didSet { + moleculesShouldSetHorizontalMargins = (moleculesShouldSetHorizontalMargins && axis == .vertical) if axis != oldValue { restack() } @@ -136,15 +137,20 @@ public class MoleculeStackView: ViewConstrainingView { } } - // If this item is in another container, do have the child molecules not use alignment. public override func shouldSetHorizontalMargins(_ shouldSet: Bool) { super.shouldSetHorizontalMargins(shouldSet) - moleculesShouldSetHorizontalMargins = false + moleculesShouldSetHorizontalMargins = (shouldSet && axis == .vertical) + for item in items { + (item.view as? MVMCoreUIViewConstrainingProtocol)?.shouldSetHorizontalMargins?(moleculesShouldSetHorizontalMargins) + } } public override func shouldSetVerticalMargins(_ shouldSet: Bool) { super.shouldSetVerticalMargins(shouldSet) moleculesShouldSetVerticalMargins = false + for item in items { + (item.view as? MVMCoreUIViewConstrainingProtocol)?.shouldSetVerticalMargins?(moleculesShouldSetVerticalMargins) + } } open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { @@ -187,32 +193,51 @@ public class MoleculeStackView: ViewConstrainingView { if let item = items?[index] { item.update(with: moleculeJSON) view = item.view + (view as? MVMCoreUIMoleculeViewProtocol)?.setWithJSON(moleculeJSON, delegateObject: delegateObject, additionalData: nil) addStackItem(item, lastItem: index == molecules.count - 1) } else if let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject, constrainIfNeeded: true) { view = molecule addStackItem(StackItem(with: molecule, json: map), lastItem: index == molecules.count - 1) } - (view as? MVMCoreUIViewConstrainingProtocol)?.shouldSetHorizontalMargins?(moleculesShouldSetHorizontalMargins && axis == .vertical) + (view as? MVMCoreUIViewConstrainingProtocol)?.shouldSetHorizontalMargins?(moleculesShouldSetHorizontalMargins) (view as? MVMCoreUIViewConstrainingProtocol)?.shouldSetVerticalMargins?(moleculesShouldSetVerticalMargins) - (view as? MVMCoreUIMoleculeViewProtocol)?.setWithJSON(moleculeJSON, delegateObject: delegateObject, additionalData: nil) } } } public override static func name(forReuse molecule: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> String? { // This will aggregate names of molecules to make an id. - var name = "" guard let molecules = molecule?.optionalArrayForKey(KeyMolecules) else { - return name + return "stack<>" } + var name = "stack<" for case let item as [AnyHashable: AnyHashable] in molecules { - if let moleculeName = item.stringOptionalWithChainOfKeysOrIndexes([KeyMolecule, KeyMoleculeName]) { - name.append(moleculeName) + if let molecule = item.optionalDictionaryForKey(KeyMolecule), let moleculeName = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: molecule)?.name?(forReuse: molecule, delegateObject: delegateObject) ?? molecule.optionalStringForKey(KeyMoleculeName) { + name.append(moleculeName + ",") } } + name.append(">") return name } + public override static func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + // if horizontal, max, if vertical, append. + return 100 + } + + public override static func requiredModules(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { + guard let items = json?.optionalArrayForKey(KeyMolecules) else { + return nil + } + var modules: [String] = [] + for case let item as [AnyHashable: AnyHashable] in items { + if let molecule = item.optionalDictionaryForKey(KeyMolecule), let modulesForMolecule = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: molecule)?.requiredModules?(molecule, delegateObject: delegateObject, error: error) { + modules += modulesForMolecule + } + } + return modules.count > 0 ? modules : nil + } + // MARK: - Adding to stack /// Adds the view to the stack. func addView(_ view: UIView, lastItem: Bool) { diff --git a/MVMCoreUI/Molecules/MoleculeTableViewCell.swift b/MVMCoreUI/Molecules/MoleculeTableViewCell.swift index ed5bf1fc..f8fc00fa 100644 --- a/MVMCoreUI/Molecules/MoleculeTableViewCell.swift +++ b/MVMCoreUI/Molecules/MoleculeTableViewCell.swift @@ -98,13 +98,14 @@ import UIKit } molecule = moleculeView } + } else { + molecule?.setWithJSON(moleculeJSON, delegateObject: delegateObject, additionalData: additionalData) } if let castView = molecule as? MVMCoreUIViewConstrainingProtocol { let standardConstraints = castView.useStandardConstraints?() ?? true castView.shouldSetHorizontalMargins?(!standardConstraints) castView.shouldSetVerticalMargins?(!standardConstraints) } - molecule?.setWithJSON(moleculeJSON, delegateObject: delegateObject, additionalData: additionalData) backgroundColor = molecule?.backgroundColor @@ -126,25 +127,26 @@ import UIKit molecule?.reset?() } - public static func estimatedHeight(forRow json: [AnyHashable: Any]?) -> CGFloat { - guard let moleculeJSON = json?.optionalDictionaryForKey(KeyMolecule), - let theClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: moleculeJSON, delegateObject: nil), - let estimatedHeightFor = theClass.estimatedHeight else { + public static func estimatedHeight(forRow json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + guard let moleculeJSON = json?.optionalDictionaryForKey(KeyMolecule), let height = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: moleculeJSON)?.estimatedHeight?(forRow: moleculeJSON, delegateObject: delegateObject) else { return 80 } - return estimatedHeightFor(moleculeJSON) + return height } public static func name(forReuse molecule: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> String? { - if let molecule = molecule?.optionalDictionaryForKey(KeyMolecule), - let moleculeName = molecule.optionalStringForKey(KeyMoleculeName), - let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping[moleculeName] as? AnyClass, - let castClass = moleculeClass as? MVMCoreUIMoleculeViewProtocol.Type, - let nameFunc = castClass.name { - return nameFunc(molecule, delegateObject) - } else { - return molecule?.optionalDictionaryForKey(KeyMolecule)?.optionalStringForKey(KeyMoleculeName) + guard let molecule = molecule?.optionalDictionaryForKey(KeyMolecule) else { + return nil } + return MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: molecule)?.name?(forReuse: molecule, delegateObject: delegateObject) ?? molecule.optionalStringForKey(KeyMoleculeName) + } + + public static func requiredModules(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer?) -> [String]? { + guard let moleculeJSON = json?.optionalDictionaryForKey(KeyMolecule), + let theClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: moleculeJSON) else { + return nil + } + return theClass.requiredModules?(moleculeJSON, delegateObject: delegateObject, error: error) } // MARK: - Arrow diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.h b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.h index 4e7dd8db..7d85a2ea 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.h +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.h @@ -21,22 +21,19 @@ + (nullable instancetype)sharedMappingObject; /// Returns the molecule class. -- (nullable Class)getMoleculeClassWithJSON:(nonnull NSDictionary *)json delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject; +- (nullable Class)getMoleculeClassWithJSON:(nonnull NSDictionary *)json; #pragma mark - Molecule Creation -/// Creates the molecule for the given name. -- (nullable UIView *)createMoleculeForName:(nonnull NSString *)name; - -/// Creates the molecule for the molecule json. Takes into account moduleMolecule as well. +/// Creates the molecule for the molecule json. - (nullable UIView *)createMoleculeForJSON:(nonnull NSDictionary *)json delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject; -/// Creates the molecule for the molecule json. Takes into account moduleMolecule as well. Also checks if the molecule needs to be constrained for a stack/list style situation. +/// Creates the molecule for the molecule json. Also checks if the molecule needs to be constrained for a stack/list style situation. - (nullable UIView *)createMoleculeForJSON:(nonnull NSDictionary *)json delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject constrainIfNeeded:(BOOL)constrainIfNeeded; -#pragma mark - ModuleMolecule Helpers +#pragma mark - Convenience -/// If the molecule is a module molecule, will get the map for the molecule to load from a module. Otherwise nil. -+ (nullable NSDictionary *)getMoleculeMapForModuleMolecule:(nullable NSDictionary *)moduleMolecule delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject error:(MVMCoreErrorObject *_Nullable *_Nullable)error; ++ (nullable NSArray *)getRequiredModulesForJSON:(nullable NSDictionary *)json delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject error:(MVMCoreErrorObject *_Nullable *_Nullable)error; ++ (void)addRequiredModulesForJSON:(nullable NSDictionary *)json delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject moduleList:(nullable NSMutableArray *)moduleList errorList:(nullable NSMutableArray *)errorList; @end diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index 9da408cb..148932bb 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -10,6 +10,7 @@ @import MVMCore.MVMCoreActionUtility; @import MVMCore.NSDictionary_MFConvenience; @import MVMCore.MVMCoreLoadObject; +@import MVMCore.MVMCoreErrorObject; #import "MVMCoreUIObject.h" #import #import "MFTextField.h" @@ -44,7 +45,8 @@ @"switchLineItem": SwitchLineItem.class, @"switch": Switch.class, @"image": MFLoadImageView.class, - @"leftRightLabelView": LeftRightLabelView.class + @"leftRightLabelView": LeftRightLabelView.class, + @"moduleMolecule": ModuleMolecule.class } mutableCopy]; }); return mapping; @@ -55,9 +57,8 @@ return [MVMCoreActionUtility initializerClassCheck:[MVMCoreUIObject sharedInstance].moleculeMap classToVerify:self]; } -- (nullable Class)getMoleculeClassWithJSON:(nonnull NSDictionary *)json delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject { - NSDictionary *moleculeJSON = [MVMCoreUIMoleculeMappingObject getMoleculeMapForModuleMolecule:json delegateObject:delegateObject error:nil] ?: json; - NSString *moleculeName = [moleculeJSON string:KeyMoleculeName]; +- (nullable Class)getMoleculeClassWithJSON:(nonnull NSDictionary *)json { + NSString *moleculeName = [json string:KeyMoleculeName]; if (moleculeName) { return [self.moleculeMapping objectForKey:moleculeName]; } @@ -83,13 +84,13 @@ } - (nullable UIView *)createMoleculeForJSON:(nonnull NSDictionary *)json delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject constrainIfNeeded:(BOOL)constrainIfNeeded { - NSDictionary *moleculeJSON = [MVMCoreUIMoleculeMappingObject getMoleculeMapForModuleMolecule:json delegateObject:delegateObject error:nil] ?: json; - NSString *moleculeName = [moleculeJSON string:KeyMoleculeName]; + NSString *moleculeName = [json string:KeyMoleculeName]; if (!moleculeName) { return nil; } UIView *molecule = [self createMoleculeForName:moleculeName]; - + [molecule setWithJSON:json delegateObject:delegateObject additionalData:nil]; + // Check if we need to constrain this view. UIView *castMolecule = [molecule conformsToProtocol:@protocol(MVMCoreUIViewConstrainingProtocol)] ? (UIView *)molecule : nil; if (constrainIfNeeded && [castMolecule respondsToSelector:@selector(needsToBeConstrained)] && [castMolecule needsToBeConstrained]) { @@ -98,20 +99,26 @@ return molecule; } -#pragma mark - ModuleMolecule Helpers +#pragma mark - Convenience -+ (nullable NSDictionary *)getMoleculeMapForModuleMolecule:(nullable NSDictionary *)moduleMolecule delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject error:(MVMCoreErrorObject *_Nullable *_Nullable)error { - NSString *moleculeName = [moduleMolecule string:KeyMoleculeName]; - if ([moleculeName isEqualToString:@"moduleMolecule"]) { - NSString *moduleName = [moduleMolecule string:@"moduleName"]; - NSDictionary *module = moduleName ? [delegateObject.moleculeDelegate getModuleWithName:moduleName] : nil; - if (!module && error) { - *error = [[MVMCoreErrorObject alloc] initWithTitle:nil message:[MVMCoreGetterUtility hardcodedStringWithKey:HardcodedErrorUnableToProcess] code:ErrorCodeModuleMolecule domain:ErrorDomainNative location:NSStringFromClass(self)]; - } - return module; ++ (nullable NSArray *)getRequiredModulesForJSON:(nullable NSDictionary *)json delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject error:(MVMCoreErrorObject *_Nullable *_Nullable)error { + Class theClass = [[MVMCoreUIMoleculeMappingObject sharedMappingObject] getMoleculeClassWithJSON:json]; + if ([theClass respondsToSelector:@selector(requiredModules:delegateObject:error:)]) { + return [theClass requiredModules:json delegateObject:delegateObject error:error]; } else { return nil; } } ++ (void)addRequiredModulesForJSON:(nullable NSDictionary *)json delegateObject:(nullable MVMCoreUIDelegateObject *)delegateObject moduleList:(nullable NSMutableArray *)moduleList errorList:(nullable NSMutableArray *)errorList { + MVMCoreErrorObject *error = nil; + NSArray *modules = [self getRequiredModulesForJSON:json delegateObject:delegateObject error:&error]; + if (modules) { + [moduleList addObjectsFromArray:modules]; + } + if (error) { + [errorList addObject:error]; + } +} + @end diff --git a/MVMCoreUI/OtherHandlers/MoleculeMappingObject+Extension.swift b/MVMCoreUI/OtherHandlers/MoleculeMappingObject+Extension.swift deleted file mode 100644 index 3c88a743..00000000 --- a/MVMCoreUI/OtherHandlers/MoleculeMappingObject+Extension.swift +++ /dev/null @@ -1,47 +0,0 @@ -// -// MoleculeMappingObject+Extension.swift -// MVMCoreUI -// -// Created by Scott Pfeil on 5/23/19. -// Copyright © 2019 Verizon Wireless. All rights reserved. -// - -import Foundation - -public extension MVMCoreUIMoleculeMappingObject { - - /// Gets the molecule, and if it belonged to a moduleMolecule, the module name or error. - static func getMoleculeJSON(for map: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> (molecule: [AnyHashable: Any]?, moduleName: String?, error: MVMCoreErrorObject?)? { - guard let map = map, let moleculeName = map.optionalStringForKey(KeyMoleculeName) else { - return nil - } - guard moleculeName == "moduleMolecule" else { - // Not a module molecule. - return (map, nil, nil) - } - - guard let moduleName = map.optionalStringForKey("moduleName"), - let module = delegateObject?.moleculeDelegate?.getModuleWithName(moduleName) else { - guard let error = MVMCoreErrorObject(title: nil, message: MVMCoreGetterUtility.hardcodedString(withKey: HardcodedErrorUnableToProcess), code: CoreUIErrorCode.ErrorCodeModuleMolecule.rawValue, domain: ErrorDomainNative, location: String(describing: self)) else { - return nil - } - MVMCoreUILoggingHandler.shared()?.addError(toLog: error) - return (nil, nil, error) - } - return (module, moduleName, nil) - } - - /// Gets the molecule, and if it belonged to a moduleMolecule adds the module name or error to the passed lists. - static func getMoleculeJSON(for map: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, moduleNames: inout [String]?, errors: inout [MVMCoreErrorObject]?) -> [AnyHashable: Any]? { - guard let molecule = getMoleculeJSON(for: map, delegateObject: delegateObject) else { - return nil - } - if let moduleName = molecule.moduleName { - moduleNames?.append(moduleName) - } - if let error = molecule.error { - errors?.append(error) - } - return molecule.molecule - } -} diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index 9a3fd952..93e9dab4 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -9,15 +9,16 @@ import UIKit open class MoleculeListTemplate: ThreeLayerTableViewController { - var molecules: [(molecule: [AnyHashable: Any]?, moduleName: String?, error: MVMCoreErrorObject?)]? - + var moleculesInfo: [(identifier: String, class: AnyClass, molecule: [AnyHashable: Any])]? + var modulesRequired: NSMutableArray? + open override func shouldFinishProcessingLoad(_ loadObject: MVMCoreLoadObject, error: AutoreleasingUnsafeMutablePointer) -> Bool { var shouldFinish = super.shouldFinishProcessingLoad(loadObject, error: error) guard shouldFinish else { return shouldFinish } - if let firstError = setup()?.first { + if let firstError = setup()?.firstObject as? MVMCoreErrorObject { // Don't continue if there was an error loading needed modules. error.pointee = firstError shouldFinish = false @@ -30,7 +31,6 @@ open class MoleculeListTemplate: ThreeLayerTableViewController { let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, constrainIfNeeded: true) else { return super.viewForTop() } - molecule.setWithJSON(moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, additionalData: nil) return molecule } @@ -39,47 +39,43 @@ open class MoleculeListTemplate: ThreeLayerTableViewController { let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, constrainIfNeeded: true) else { return super.viewForBottom() } - molecule.setWithJSON(moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, additionalData: nil) return molecule } open override func newDataBuildScreen() { super.newDataBuildScreen() - _ = setupMoleculeList() + _ = setup() registerWithTable() } // MARK: - table open override func registerWithTable() { super.registerWithTable() - guard let molecules = molecules else { + guard let moleculesInfo = moleculesInfo else { return } - for molecule in molecules { - if let moleculeInfo = getMoleculeInfo(with: molecule), let moleculeToRegister = moleculeInfo.name { - tableView?.register(moleculeInfo.class, forCellReuseIdentifier: moleculeToRegister) - } + for moleculeInfo in moleculesInfo { + print(moleculeInfo.identifier) + tableView?.register(moleculeInfo.class, forCellReuseIdentifier: moleculeInfo.identifier) } } open override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { - guard let molecule = molecules?[indexPath.row], - let moleculeInfo = getMoleculeInfo(with: molecule), - let estimatedHeight = moleculeInfo.class.estimatedHeight else { + guard let moleculeInfo = moleculesInfo?[indexPath.row], + let estimatedHeight = moleculeInfo.class.estimatedHeight?(forRow: moleculeInfo.molecule, delegateObject: delegateObject() as? MVMCoreUIDelegateObject) else { return 0 } - return estimatedHeight(molecule.molecule) + print("height :" + moleculeInfo.class.description() + " :" + estimatedHeight.description) + return estimatedHeight } open override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return molecules?.count ?? 0 + return moleculesInfo?.count ?? 0 } open override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - guard let molecule = molecules?[indexPath.row], - let moleculeInfo = getMoleculeInfo(with: molecule), - let moleculeName = moleculeInfo.name, - let cell = tableView.dequeueReusableCell(withIdentifier: moleculeName) else { + guard let moleculeInfo = moleculesInfo?[indexPath.row], + let cell = tableView.dequeueReusableCell(withIdentifier: moleculeInfo.identifier) else { return UITableViewCell() } let delegate = delegateObject() as? MVMCoreUIDelegateObject @@ -88,7 +84,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController { } if let protocolCell = cell as? MVMCoreUIMoleculeViewProtocol { protocolCell.reset?() - protocolCell.setWithJSON(molecule.molecule, delegateObject: delegate, additionalData: nil) + protocolCell.setWithJSON(moleculeInfo.molecule, delegateObject: delegate, additionalData: nil) protocolCell.updateView(tableView.bounds.width) } return cell @@ -110,78 +106,52 @@ open class MoleculeListTemplate: ThreeLayerTableViewController { open override func modulesToListenFor() -> [Any]? { // Get all of the molecules that need modules. - return modulesNeeded() + return modulesRequired as? [Any] } - // MARK: - Module Molecule Handling - /// Returns the (name, class) of the molecule for the given map. - func getMoleculeInfo(with molecule: (molecule: [AnyHashable: Any]?, moduleName: String?, error: MVMCoreErrorObject?)) -> (name: String?, class: AnyClass)? { - guard let map = molecule.molecule, let moleculeName = map.optionalStringForKey(KeyMoleculeName), let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping[moleculeName] as? AnyClass else { + // MARK: - Convenience + /// Returns the (identifier, class) of the molecule for the given map. + func getMoleculeInfo(with molecule: [AnyHashable: Any]?) -> (identifier: String, class: AnyClass, molecule: [AnyHashable: Any])? { + guard let molecule = molecule, + let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: molecule), + let moleculeName = moleculeClass.name?(forReuse: molecule, delegateObject: delegateObject() as? MVMCoreUIDelegateObject) ?? molecule.optionalStringForKey(KeyMoleculeName) else { return nil } - if let moleculeClass = moleculeClass as? MVMCoreUIMoleculeViewProtocol.Type, let moleculeNameFunc = moleculeClass.name { - return (moleculeNameFunc(map, delegateObject() as? MVMCoreUIDelegateObject), moleculeClass) - } else { - return (moleculeName, moleculeClass) - } + return (moleculeName, moleculeClass, molecule) } /// Sets up the molecule list and ensures no errors loading all content. - func setupMoleculeList() -> [MVMCoreErrorObject]? { - var errors: [MVMCoreErrorObject] = [] - let delegate = delegateObject() as? MVMCoreUIDelegateObject - var moleculeList: [(molecule: [AnyHashable: Any]?, moduleName: String?, error: MVMCoreErrorObject?)] = [] + func getMoleculeInfoList() -> [(identifier: String, class: AnyClass, molecule: [AnyHashable: Any])]? { + var moleculeList: [(identifier: String, class: AnyClass, molecule: [AnyHashable: Any])] = [] if let molecules = loadObject?.pageJSON?.optionalArrayForKey(KeyMolecules) as? [[AnyHashable: Any]] { for molecule in molecules { - if let object = MVMCoreUIMoleculeMappingObject.getMoleculeJSON(for: molecule, delegateObject: delegate) { - if let error = object.error { - errors.append(error) - } else { - moleculeList.append(object) - } + if let info = getMoleculeInfo(with: molecule) { + moleculeList.append(info) } } } - molecules = moleculeList - return errors.count > 0 ? errors : nil + return moleculeList.count > 0 ? moleculeList : nil } /// Sets up the header, footer, molecule list and ensures no errors loading all content. - func setup() -> [MVMCoreErrorObject]? { - var errors: [MVMCoreErrorObject] = [] + func setup() -> NSMutableArray? { + let modules: NSMutableArray = [] + let errors: NSMutableArray = [] let delegate = delegateObject() as? MVMCoreUIDelegateObject - MoleculeListTemplate.addToErrorList(with: MVMCoreUIMoleculeMappingObject.getMoleculeJSON(for: loadObject?.pageJSON?.optionalDictionaryForKey("header"), delegateObject: delegate), errors: &errors) - MoleculeListTemplate.addToErrorList(with: MVMCoreUIMoleculeMappingObject.getMoleculeJSON(for: loadObject?.pageJSON?.optionalDictionaryForKey("footer"), delegateObject: delegate), errors: &errors) - if let newErrors = setupMoleculeList() { - errors.append(contentsOf: newErrors) - } - return errors.count > 0 ? errors : nil - } - - static func addToErrorList(with moleculeObject: (molecule: [AnyHashable: Any]?, moduleName: String?, error: MVMCoreErrorObject?)?, errors: inout [MVMCoreErrorObject]) { - if let error = moleculeObject?.error { - errors.append(error) - } - } - - static func addToModuleList(with moleculeObject: (molecule: [AnyHashable: Any]?, moduleName: String?, error: MVMCoreErrorObject?)?, moduleNames: inout [String]) { - if let moduleName = moleculeObject?.moduleName { - moduleNames.append(moduleName) - } - } - - /// Gets a list of required modules - func modulesNeeded() -> [String]? { - var modules: [String] = [] - let delegate = delegateObject() as? MVMCoreUIDelegateObject - - MoleculeListTemplate.addToModuleList(with: MVMCoreUIMoleculeMappingObject.getMoleculeJSON(for: loadObject?.pageJSON?.optionalDictionaryForKey("header"), delegateObject: delegate), moduleNames: &modules) - MoleculeListTemplate.addToModuleList(with: MVMCoreUIMoleculeMappingObject.getMoleculeJSON(for: loadObject?.pageJSON?.optionalDictionaryForKey("footer"), delegateObject: delegate), moduleNames: &modules) - if let molecules = molecules { + MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: loadObject?.pageJSON?.optionalDictionaryForKey("header"), delegateObject: delegate, moduleList: modules, errorList: errors) + MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: loadObject?.pageJSON?.optionalDictionaryForKey("footer"), delegateObject: delegate, moduleList: modules, errorList: errors) + + var moleculeList: [(identifier: String, class: AnyClass, molecule: [AnyHashable: Any])] = [] + if let molecules = loadObject?.pageJSON?.optionalArrayForKey(KeyMolecules) as? [[AnyHashable: Any]] { for molecule in molecules { - MoleculeListTemplate.addToModuleList(with: molecule, moduleNames: &modules) + if let info = getMoleculeInfo(with: molecule) { + moleculeList.append(info) + MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: molecule, delegateObject: delegate, moduleList: modules, errorList: errors) + } } } - return (modules.count > 0 ? modules : nil) + moleculesInfo = moleculeList + modulesRequired = modules + return errors.count > 0 ? errors : nil } } diff --git a/MVMCoreUI/Templates/MoleculeStackTemplate.swift b/MVMCoreUI/Templates/MoleculeStackTemplate.swift index 3d6d76d8..7bf2a1ed 100644 --- a/MVMCoreUI/Templates/MoleculeStackTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeStackTemplate.swift @@ -9,10 +9,11 @@ import UIKit public class MoleculeStackTemplate: ThreeLayerViewController { - + var modulesRequired: NSMutableArray? + public override func shouldFinishProcessingLoad(_ loadObject: MVMCoreLoadObject, error: AutoreleasingUnsafeMutablePointer) -> Bool { var shouldFinish = super.shouldFinishProcessingLoad(loadObject, error: error) - if shouldFinish, let firstError = modulesNeeded().errors?.first { + if shouldFinish, let firstError = modulesNeeded().errors?.firstObject as? MVMCoreErrorObject { // Don't continue if there was an error loading needed modules. error.pointee = firstError shouldFinish = false @@ -28,7 +29,6 @@ public class MoleculeStackTemplate: ThreeLayerViewController { guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("header"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, constrainIfNeeded: true) else { return nil } - molecule.setWithJSON(moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, additionalData: nil) return molecule } @@ -46,7 +46,6 @@ public class MoleculeStackTemplate: ThreeLayerViewController { guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("footer"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, constrainIfNeeded: true) else { return nil } - molecule.setWithJSON(moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, additionalData: nil) return molecule } @@ -60,22 +59,18 @@ public class MoleculeStackTemplate: ThreeLayerViewController { public override func modulesToListenFor() -> [Any]? { // Get all of the molecules that need modules. - return modulesNeeded().modules + return modulesNeeded().modules as? [Any] } - // MARK: - Module Molecule Handling - func modulesNeeded() -> (modules: [String]?, errors: [MVMCoreErrorObject]?) { - var modules: [String]? = [] - var errors: [MVMCoreErrorObject]? = [] + /// Gets the modules needed. + func modulesNeeded() -> (modules: NSMutableArray?, errors: NSMutableArray?) { + let modules: NSMutableArray = [] + let errors: NSMutableArray = [] let delegate = delegateObject() as? MVMCoreUIDelegateObject - - let _ = MVMCoreUIMoleculeMappingObject.getMoleculeJSON(for: loadObject?.pageJSON?.optionalDictionaryForKey("header"), delegateObject: delegate, moduleNames: &modules, errors: &errors) - let _ = MVMCoreUIMoleculeMappingObject.getMoleculeJSON(for: loadObject?.pageJSON?.optionalDictionaryForKey("footer"), delegateObject: delegate, moduleNames: &modules, errors: &errors) - if let molecules = loadObject?.pageJSON?.optionalArrayForChainOfKeysOrIndexes(["moleculeStack",KeyMolecules]) as? [[AnyHashable: Any]] { - for molecule in molecules { - let _ = MVMCoreUIMoleculeMappingObject.getMoleculeJSON(for: molecule, delegateObject: delegate, moduleNames: &modules, errors: &errors) - } - } - return (modules?.count ?? 0 > 0 ? modules : nil, errors?.count ?? 0 > 0 ? errors : nil) + MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: loadObject?.pageJSON?.optionalDictionaryForKey("header"), delegateObject: delegate, moduleList: modules, errorList: errors) + MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: loadObject?.pageJSON?.optionalDictionaryForKey("footer"), delegateObject: delegate, moduleList: modules, errorList: errors) + MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: loadObject?.pageJSON?.optionalDictionaryForKey("moleculeStack"), delegateObject: delegate, moduleList: modules, errorList: errors) + modulesRequired = modules + return (modules.count > 0 ? modules : nil, errors.count > 0 ? errors : nil) } }