From 335ec160b506f33d81550a128956485a5c23b2da Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 13 Mar 2020 10:04:47 -0400 Subject: [PATCH 01/17] swift --- MVMCoreUI.xcodeproj/project.pbxproj | 52 ++-- .../Atoms/TextFields/TextEntryField.swift | 2 +- .../ProgrammaticScrollViewController.swift | 56 ++++ .../ProgrammaticTableViewController.swift | 81 +++++ .../ScrollingViewController.swift | 109 +++++++ .../ThreeLayerTableViewController.swift | 27 +- .../ThreeLayerViewController.swift | 27 +- .../BaseControllers/ViewController.swift | 286 +++++++++++++++++- ...MVMCoreUITabBarPageControlViewController.m | 2 +- .../New/FormHolderProtocol.swift | 2 - .../MFProgrammaticScrollViewController.h} | 4 +- .../MFProgrammaticScrollViewController.m} | 8 +- .../MFProgrammaticTableViewController.h | 0 .../MFProgrammaticTableViewController.m | 0 .../Controllers}/MFScrollingViewController.h | 0 .../Controllers}/MFScrollingViewController.m | 0 .../Controllers}/MFViewController+Form.swift | 0 .../Controllers}/MFViewController+Model.swift | 0 .../Controllers}/MFViewController.h | 0 .../Controllers}/MFViewController.m | 0 .../MVMCoreUIStackableViewController.h | 4 +- .../MVMCoreUIStackableViewController.m | 0 MVMCoreUI/MVMCoreUI.h | 2 +- .../ModelProtocols/PageModelProtocol.swift | 1 + .../Items/DropDownFilterTableViewCell.swift | 7 +- .../NavigationItemModelProtocol.swift | 17 ++ .../OtherHandlers/MVMCoreUILoggingHandler.h | 6 +- .../OtherHandlers/MVMCoreUILoggingHandler.m | 6 +- .../Templates/ListPageTemplateModel.swift | 1 + .../Templates/ModalMoleculeListTemplate.swift | 8 +- .../ModalMoleculeStackTemplate.swift | 8 +- .../Templates/MoleculeListTemplate.swift | 51 +--- .../Templates/MoleculeStackTemplate.swift | 27 +- .../StackCenteredPageTemplateModel.swift | 1 + .../Templates/StackPageTemplateModel.swift | 1 + MVMCoreUI/Templates/TemplateProtocol.swift | 2 +- .../ThreeLayerPageTemplateModel.swift | 1 + MVMCoreUI/Templates/ThreeLayerTemplate.swift | 15 +- 38 files changed, 639 insertions(+), 175 deletions(-) create mode 100644 MVMCoreUI/BaseControllers/ProgrammaticScrollViewController.swift create mode 100644 MVMCoreUI/BaseControllers/ProgrammaticTableViewController.swift create mode 100644 MVMCoreUI/BaseControllers/ScrollingViewController.swift rename MVMCoreUI/{BaseControllers/ProgrammaticScrollViewController.h => Legacy/Controllers/MFProgrammaticScrollViewController.h} (61%) rename MVMCoreUI/{BaseControllers/ProgrammaticScrollViewController.m => Legacy/Controllers/MFProgrammaticScrollViewController.m} (92%) rename MVMCoreUI/{BaseControllers => Legacy/Controllers}/MFProgrammaticTableViewController.h (100%) rename MVMCoreUI/{BaseControllers => Legacy/Controllers}/MFProgrammaticTableViewController.m (100%) rename MVMCoreUI/{BaseControllers => Legacy/Controllers}/MFScrollingViewController.h (100%) rename MVMCoreUI/{BaseControllers => Legacy/Controllers}/MFScrollingViewController.m (100%) rename MVMCoreUI/{BaseControllers => Legacy/Controllers}/MFViewController+Form.swift (100%) rename MVMCoreUI/{BaseControllers => Legacy/Controllers}/MFViewController+Model.swift (100%) rename MVMCoreUI/{BaseControllers => Legacy/Controllers}/MFViewController.h (100%) rename MVMCoreUI/{BaseControllers => Legacy/Controllers}/MFViewController.m (100%) rename MVMCoreUI/{BaseControllers => Legacy/Controllers}/MVMCoreUIStackableViewController.h (95%) rename MVMCoreUI/{BaseControllers => Legacy/Controllers}/MVMCoreUIStackableViewController.m (100%) create mode 100644 MVMCoreUI/Molecules/NavigationItemModelProtocol.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index b5985e36..7aa2b2dd 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -178,6 +178,7 @@ C7F8012123E8303200396FBD /* ListRVWheel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7F8012023E8303200396FBD /* ListRVWheel.swift */; }; C7F8012323E846C300396FBD /* ListRVWheelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7F8012223E846C300396FBD /* ListRVWheelModel.swift */; }; D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */; }; + D20FB165241A5D75004AFC3A /* NavigationItemModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20FB164241A5D75004AFC3A /* NavigationItemModelProtocol.swift */; }; D213347723843825008E41B3 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = D213347623843825008E41B3 /* Line.swift */; }; D21EE53C23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21EE53B23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift */; }; D224798A2314445E003FCCF9 /* LabelToggle.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22479892314445E003FCCF9 /* LabelToggle.swift */; }; @@ -285,11 +286,11 @@ D29DF28421E7AB24003B2FB9 /* MVMCoreUICommonViewsUtility.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF28221E7AB24003B2FB9 /* MVMCoreUICommonViewsUtility.h */; settings = {ATTRIBUTES = (Public, ); }; }; D29DF28B21E7AC2B003B2FB9 /* ViewConstrainingView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF28721E7AC2B003B2FB9 /* ViewConstrainingView.h */; settings = {ATTRIBUTES = (Public, ); }; }; D29DF28C21E7AC2B003B2FB9 /* ViewConstrainingView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF28821E7AC2B003B2FB9 /* ViewConstrainingView.m */; }; - D29DF29521E7ADB8003B2FB9 /* ProgrammaticScrollViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF28D21E7ADB8003B2FB9 /* ProgrammaticScrollViewController.m */; }; + D29DF29521E7ADB8003B2FB9 /* MFProgrammaticScrollViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF28D21E7ADB8003B2FB9 /* MFProgrammaticScrollViewController.m */; }; D29DF29621E7ADB8003B2FB9 /* StackableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF28E21E7ADB8003B2FB9 /* StackableViewController.m */; }; D29DF29721E7ADB8003B2FB9 /* MFScrollingViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF28F21E7ADB8003B2FB9 /* MFScrollingViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; D29DF29821E7ADB8003B2FB9 /* MFScrollingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF29021E7ADB8003B2FB9 /* MFScrollingViewController.m */; }; - D29DF29921E7ADB8003B2FB9 /* ProgrammaticScrollViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF29121E7ADB8003B2FB9 /* ProgrammaticScrollViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D29DF29921E7ADB8003B2FB9 /* MFProgrammaticScrollViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF29121E7ADB8003B2FB9 /* MFProgrammaticScrollViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; D29DF29A21E7ADB8003B2FB9 /* MFProgrammaticTableViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF29221E7ADB8003B2FB9 /* MFProgrammaticTableViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; D29DF29B21E7ADB9003B2FB9 /* StackableViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF29321E7ADB8003B2FB9 /* StackableViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; D29DF29C21E7ADB9003B2FB9 /* MFProgrammaticTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF29421E7ADB8003B2FB9 /* MFProgrammaticTableViewController.m */; }; @@ -342,6 +343,9 @@ D2A638FD22CA98280052ED1F /* HeadlineBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A638FC22CA98280052ED1F /* HeadlineBody.swift */; }; D2A6390122CBB1820052ED1F /* Carousel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A6390022CBB1820052ED1F /* Carousel.swift */; }; D2A6390522CBCE160052ED1F /* MoleculeCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A6390422CBCE160052ED1F /* MoleculeCollectionViewCell.swift */; }; + D2A92882241AAB67004E01C6 /* ScrollingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A92881241AAB67004E01C6 /* ScrollingViewController.swift */; }; + D2A92884241ACB25004E01C6 /* ProgrammaticScrollViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A92883241ACB25004E01C6 /* ProgrammaticScrollViewController.swift */; }; + D2A92886241ACD99004E01C6 /* ProgrammaticTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A92885241ACD99004E01C6 /* ProgrammaticTableViewController.swift */; }; D2B18B7F2360913400A9AEDC /* Control.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2B18B7E2360913400A9AEDC /* Control.swift */; }; D2B18B812360945C00A9AEDC /* View.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2B18B802360945C00A9AEDC /* View.swift */; }; D2B18B922361E65A00A9AEDC /* CoreUIObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2B18B912361E65A00A9AEDC /* CoreUIObject.swift */; }; @@ -539,6 +543,7 @@ C7F8012023E8303200396FBD /* ListRVWheel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListRVWheel.swift; sourceTree = ""; }; C7F8012223E846C300396FBD /* ListRVWheelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRVWheelModel.swift; sourceTree = ""; }; D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoButtonView.swift; sourceTree = ""; }; + D20FB164241A5D75004AFC3A /* NavigationItemModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationItemModelProtocol.swift; sourceTree = ""; }; D213347623843825008E41B3 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = ""; }; D21EE53B23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSLayoutConstraintAxis+Extension.swift"; sourceTree = ""; }; D22479892314445E003FCCF9 /* LabelToggle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelToggle.swift; sourceTree = ""; }; @@ -666,11 +671,11 @@ D29DF28221E7AB24003B2FB9 /* MVMCoreUICommonViewsUtility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUICommonViewsUtility.h; sourceTree = ""; }; D29DF28721E7AC2B003B2FB9 /* ViewConstrainingView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewConstrainingView.h; sourceTree = ""; }; D29DF28821E7AC2B003B2FB9 /* ViewConstrainingView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewConstrainingView.m; sourceTree = ""; }; - D29DF28D21E7ADB8003B2FB9 /* ProgrammaticScrollViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProgrammaticScrollViewController.m; sourceTree = ""; }; + D29DF28D21E7ADB8003B2FB9 /* MFProgrammaticScrollViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFProgrammaticScrollViewController.m; sourceTree = ""; }; D29DF28E21E7ADB8003B2FB9 /* StackableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StackableViewController.m; sourceTree = ""; }; D29DF28F21E7ADB8003B2FB9 /* MFScrollingViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFScrollingViewController.h; sourceTree = ""; }; D29DF29021E7ADB8003B2FB9 /* MFScrollingViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFScrollingViewController.m; sourceTree = ""; }; - D29DF29121E7ADB8003B2FB9 /* ProgrammaticScrollViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProgrammaticScrollViewController.h; sourceTree = ""; }; + D29DF29121E7ADB8003B2FB9 /* MFProgrammaticScrollViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFProgrammaticScrollViewController.h; sourceTree = ""; }; D29DF29221E7ADB8003B2FB9 /* MFProgrammaticTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFProgrammaticTableViewController.h; sourceTree = ""; }; D29DF29321E7ADB8003B2FB9 /* StackableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StackableViewController.h; sourceTree = ""; }; D29DF29421E7ADB8003B2FB9 /* MFProgrammaticTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFProgrammaticTableViewController.m; sourceTree = ""; }; @@ -717,6 +722,9 @@ D2A638FC22CA98280052ED1F /* HeadlineBody.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBody.swift; sourceTree = ""; }; D2A6390022CBB1820052ED1F /* Carousel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Carousel.swift; sourceTree = ""; }; D2A6390422CBCE160052ED1F /* MoleculeCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeCollectionViewCell.swift; sourceTree = ""; }; + D2A92881241AAB67004E01C6 /* ScrollingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollingViewController.swift; sourceTree = ""; }; + D2A92883241ACB25004E01C6 /* ProgrammaticScrollViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgrammaticScrollViewController.swift; sourceTree = ""; }; + D2A92885241ACD99004E01C6 /* ProgrammaticTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgrammaticTableViewController.swift; sourceTree = ""; }; D2B18B7E2360913400A9AEDC /* Control.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Control.swift; sourceTree = ""; }; D2B18B802360945C00A9AEDC /* View.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = View.swift; sourceTree = ""; }; D2B18B912361E65A00A9AEDC /* CoreUIObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreUIObject.swift; sourceTree = ""; }; @@ -927,8 +935,20 @@ D213347423842FE3008E41B3 /* Controllers */ = { isa = PBXGroup; children = ( + D29DF16021E69996003B2FB9 /* MFViewController.h */, + D29DF15F21E69996003B2FB9 /* MFViewController.m */, + 017BEB3B2361EA1D0024EF95 /* MFViewController+Model.swift */, + 011D9627240EFA1E000E3791 /* MFViewController+Form.swift */, + D29DF28F21E7ADB8003B2FB9 /* MFScrollingViewController.h */, + D29DF29021E7ADB8003B2FB9 /* MFScrollingViewController.m */, + D29DF29121E7ADB8003B2FB9 /* MFProgrammaticScrollViewController.h */, + D29DF28D21E7ADB8003B2FB9 /* MFProgrammaticScrollViewController.m */, D29DF29321E7ADB8003B2FB9 /* StackableViewController.h */, D29DF28E21E7ADB8003B2FB9 /* StackableViewController.m */, + D29DF29221E7ADB8003B2FB9 /* MFProgrammaticTableViewController.h */, + D29DF29421E7ADB8003B2FB9 /* MFProgrammaticTableViewController.m */, + D22D1F542204CE5D0077CEC0 /* MVMCoreUIStackableViewController.h */, + D22D1F552204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m */, D29770F021F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsViewController.h */, D29770F121F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsViewController.m */, D29770EF21F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsTableViewController.h */, @@ -1269,6 +1289,7 @@ 017BEB47236230DB0024EF95 /* MoleculeViewProtocol.swift */, 017BEB49236235BA0024EF95 /* ModelMoleculeViewProtocol.swift */, D260105723CF9CC500764D80 /* Doughnut */, + D20FB164241A5D75004AFC3A /* NavigationItemModelProtocol.swift */, ); path = Molecules; sourceTree = ""; @@ -1276,23 +1297,14 @@ D29DF10F21E67A7D003B2FB9 /* BaseControllers */ = { isa = PBXGroup; children = ( - D29DF16021E69996003B2FB9 /* MFViewController.h */, - D29DF15F21E69996003B2FB9 /* MFViewController.m */, - 017BEB3B2361EA1D0024EF95 /* MFViewController+Model.swift */, - 011D9627240EFA1E000E3791 /* MFViewController+Form.swift */, - D29DF28F21E7ADB8003B2FB9 /* MFScrollingViewController.h */, - D29DF29021E7ADB8003B2FB9 /* MFScrollingViewController.m */, - D29DF29121E7ADB8003B2FB9 /* ProgrammaticScrollViewController.h */, - D29DF28D21E7ADB8003B2FB9 /* ProgrammaticScrollViewController.m */, - D29DF29221E7ADB8003B2FB9 /* MFProgrammaticTableViewController.h */, - D29DF29421E7ADB8003B2FB9 /* MFProgrammaticTableViewController.m */, - D22D1F542204CE5D0077CEC0 /* MVMCoreUIStackableViewController.h */, - D22D1F552204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m */, D29DF2CC21E7C104003B2FB9 /* MFLoadingViewController.h */, D29DF2CD21E7C104003B2FB9 /* MFLoadingViewController.m */, D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */, D2E1FADE2268B8E700AEFD8C /* ThreeLayerTableViewController.swift */, D2C521A823EDE79E00CA2634 /* ViewController.swift */, + D2A92881241AAB67004E01C6 /* ScrollingViewController.swift */, + D2A92883241ACB25004E01C6 /* ProgrammaticScrollViewController.swift */, + D2A92885241ACD99004E01C6 /* ProgrammaticTableViewController.swift */, ); path = BaseControllers; sourceTree = ""; @@ -1618,7 +1630,7 @@ D29DF2A921E7B2F9003B2FB9 /* MVMCoreUIConstants.h in Headers */, 0198F7A62256A80B0066C936 /* MFRadioButton.h in Headers */, D22D1F1A220341F60077CEC0 /* MVMCoreUICheckBox.h in Headers */, - D29DF29921E7ADB8003B2FB9 /* ProgrammaticScrollViewController.h in Headers */, + D29DF29921E7ADB8003B2FB9 /* MFProgrammaticScrollViewController.h in Headers */, D29DF11C21E684A9003B2FB9 /* MVMCoreUISplitViewController.h in Headers */, D29DF29B21E7ADB9003B2FB9 /* StackableViewController.h in Headers */, D29770F421F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsViewController.h in Headers */, @@ -1821,6 +1833,7 @@ D2E2A99823D8D63C000B42E6 /* ActionDetailWithImageModel.swift in Sources */, D2E2A99D23DA3217000B42E6 /* UIStackViewAlignment+Extension.swift in Sources */, 01EB369423609801006832FA /* HeadlineBodyModel.swift in Sources */, + D2A92884241ACB25004E01C6 /* ProgrammaticScrollViewController.swift in Sources */, 0A21DB7F235DECC500C160A2 /* EntryField.swift in Sources */, D2E2A99F23E07F8A000B42E6 /* PillButton.swift in Sources */, D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */, @@ -1874,6 +1887,7 @@ D2D6CD4022E78C1A00D701B8 /* Scroller.swift in Sources */, 0A7EF85F23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift in Sources */, 011D959B240451E3000E3791 /* RuleRequiredModel.swift in Sources */, + D2A92886241ACD99004E01C6 /* ProgrammaticTableViewController.swift in Sources */, 01509D952327ED1900EF99AA /* HeadlineBodyLinkToggle.swift in Sources */, 31BE15CB23D8924D00452370 /* CheckboxLabelModel.swift in Sources */, D260105523CEA7DC00764D80 /* MVMCoreUISwitch+Model.swift in Sources */, @@ -1946,7 +1960,7 @@ D2A6390122CBB1820052ED1F /* Carousel.swift in Sources */, D29DF2C721E7BF57003B2FB9 /* MFTabBarInteractor.m in Sources */, C7F8012123E8303200396FBD /* ListRVWheel.swift in Sources */, - D29DF29521E7ADB8003B2FB9 /* ProgrammaticScrollViewController.m in Sources */, + D29DF29521E7ADB8003B2FB9 /* MFProgrammaticScrollViewController.m in Sources */, D2FB151B23A2B65B00C20E10 /* MoleculeContainer.swift in Sources */, D2A638FD22CA98280052ED1F /* HeadlineBody.swift in Sources */, D29DF16121E69996003B2FB9 /* MFViewController.m in Sources */, @@ -1956,9 +1970,11 @@ D2E1FAE12268E81D00AEFD8C /* MoleculeListTemplate.swift in Sources */, 525019E72406853600EED91C /* ListFourColumnDataUsageDivider.swift in Sources */, 0AE98BB323FF0934004C5109 /* ExternalLinkModel.swift in Sources */, + D20FB165241A5D75004AFC3A /* NavigationItemModelProtocol.swift in Sources */, DB06250B2293456500B72DD3 /* LeftRightLabelView.swift in Sources */, 0A21DB89235E06EF00C160A2 /* MFMdnTextField.m in Sources */, D224798A2314445E003FCCF9 /* LabelToggle.swift in Sources */, + D2A92882241AAB67004E01C6 /* ScrollingViewController.swift in Sources */, D22D1F47220496A30077CEC0 /* MVMCoreUISwitch.m in Sources */, C695A67F23C9830600BFB94E /* UnOrderedListModel.swift in Sources */, 0AE98BB523FF18D2004C5109 /* Arrow.swift in Sources */, diff --git a/MVMCoreUI/Atoms/TextFields/TextEntryField.swift b/MVMCoreUI/Atoms/TextFields/TextEntryField.swift index 993aed59..c3aa19c6 100644 --- a/MVMCoreUI/Atoms/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/TextEntryField.swift @@ -311,7 +311,7 @@ import UIKit uiTextFieldDelegate = delegateObject?.uiTextFieldDelegate observingTextFieldDelegate = delegateObject?.observingTextFieldDelegate - MVMCoreUICommonViewsUtility.addDismissToolbar(textField, delegate: uiTextFieldDelegate) + //MVMCoreUICommonViewsUtility.addDismissToolbar(textField, delegate: uiTextFieldDelegate) } } diff --git a/MVMCoreUI/BaseControllers/ProgrammaticScrollViewController.swift b/MVMCoreUI/BaseControllers/ProgrammaticScrollViewController.swift new file mode 100644 index 00000000..10583b14 --- /dev/null +++ b/MVMCoreUI/BaseControllers/ProgrammaticScrollViewController.swift @@ -0,0 +1,56 @@ +// +// ProgrammaticScrollViewController.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 3/12/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +open class ProgrammaticScrollViewController: ScrollingViewController { + public var topConstraint: NSLayoutConstraint? + public var bottomConstraint: NSLayoutConstraint? + + public override init(with scrollView: UIScrollView) { + super.init(with: scrollView) + } + + public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { + super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) + } + + required public init?(coder: NSCoder) { + super.init(coder: coder) + } + + open override func loadView() { + + let view = UIView() + view.backgroundColor = .white + + let scrollView = UIScrollView() + scrollView.backgroundColor = .clear + scrollView.translatesAutoresizingMaskIntoConstraints = true + view.addSubview(scrollView) + + // Sets the constraints for the scroll view + let constraints = NSLayoutConstraint.constraintPinSubview(toSuperview: scrollView) + topConstraint = constraints?[ConstraintTop] as? NSLayoutConstraint + bottomConstraint = constraints?[ConstraintBot] as? NSLayoutConstraint + + let contentView = MVMCoreUICommonViewsUtility.commonView() + scrollView.addSubview(contentView) + + // Sets the constraints for the content view + NSLayoutConstraint.constraintPinSubview(toSuperview: contentView) + + // Super will set later. + contentWidthConstraint = contentView.widthAnchor.constraint(equalToConstant: 320.0) + contentWidthConstraint?.isActive = true + + self.contentView = contentView + self.scrollView = scrollView + self.view = view + } +} diff --git a/MVMCoreUI/BaseControllers/ProgrammaticTableViewController.swift b/MVMCoreUI/BaseControllers/ProgrammaticTableViewController.swift new file mode 100644 index 00000000..4e262398 --- /dev/null +++ b/MVMCoreUI/BaseControllers/ProgrammaticTableViewController.swift @@ -0,0 +1,81 @@ +// +// ProgrammaticTableViewController.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 3/12/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +open class ProgrammaticTableViewController: ProgrammaticScrollViewController, UITableViewDelegate, UITableViewDataSource { + @IBOutlet public var tableView: UITableView! + + public init(with tableView: UITableView) { + self.tableView = tableView + super.init(with: tableView) + } + + required public init?(coder: NSCoder) { + super.init(coder: coder) + } + + public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { + super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) + } + + open override func loadView() { + let view = UIView() + view.backgroundColor = .white + + let tableView = createTableView() + tableView.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(tableView) + + // Sets the constraints for the scroll view + let constraints = NSLayoutConstraint.constraintPinSubview(toSuperview: tableView) + topConstraint = constraints?[ConstraintTop] as? NSLayoutConstraint + bottomConstraint = constraints?[ConstraintBot] as? NSLayoutConstraint + + self.tableView = tableView + scrollView = tableView + self.view = view + } + + /// This class should create the table view that will be used here. Subclass this for different table styles. + open func createTableView() -> UITableView { + let tableView = UITableView(frame: .zero, style: .grouped) + tableView.backgroundColor = .clear + tableView.separatorStyle = UITableViewCell.SeparatorStyle.none + tableView.delegate = self + tableView.dataSource = self + tableView.insetsContentViewsToSafeArea = false + return tableView + } + + // Registers classes and nibs. Can subclass for different nibs. Can call super and then add new ones after as well. + open func registerWithTable() {} + + /// Sets the table to have no section headers or footers. + open func setNoSectionHeadersFooters() { + tableView.sectionHeaderHeight = CGFloat.leastNormalMagnitude + tableView.sectionFooterHeight = CGFloat.leastNormalMagnitude + } + + /// For subclassing, returns the number of sections for table. This function calls numberOfSectionsForTableview aftre ensuring the table is setup properly. + open func getNumberOfSections() -> Int { + return 1 + } + + open func numberOfSections(in tableView: UITableView) -> Int { + return tableView.bounds.width > 1 ? getNumberOfSections() : 0 + } + + open func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return 0 + } + + open func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + return UITableViewCell() + } +} diff --git a/MVMCoreUI/BaseControllers/ScrollingViewController.swift b/MVMCoreUI/BaseControllers/ScrollingViewController.swift new file mode 100644 index 00000000..2e4eceef --- /dev/null +++ b/MVMCoreUI/BaseControllers/ScrollingViewController.swift @@ -0,0 +1,109 @@ +// +// ScrollingViewController.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 3/12/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +open class ScrollingViewController: ViewController { + public var dismissKeyboardTapGesture: UITapGestureRecognizer? + @IBOutlet public var scrollView: UIScrollView! + public var contentView: UIView? + public var contentWidthConstraint: NSLayoutConstraint? + + private var keyboardNotificationsAdded = false + private var keyboardIsShowing = false + private var preKeyboardContentInset: UIEdgeInsets? + + public init(with scrollView: UIScrollView) { + self.scrollView = scrollView + super.init(nibName: nil, bundle: nil) + } + + required public init?(coder: NSCoder) { + super.init(coder: coder) + } + + public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { + super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) + } + + // MARK: - View Life Cycle + open override func viewDidLoad() { + super.viewDidLoad() + + // Adds the tap gesture to dismiss the keyboard. + dismissKeyboardTapGesture = UITapGestureRecognizer(target: self, action: #selector(dismissFieldInput(sender:))) + view.addGestureRecognizer(dismissKeyboardTapGesture!) + dismissKeyboardTapGesture?.isEnabled = false + scrollView.alwaysBounceVertical = false + scrollView.delegate = self + } + + open override func updateViewConstraints() { + super.updateViewConstraints() + // Sets the width of the content to the width of the screen. + contentWidthConstraint?.constant = view.bounds.width - scrollView.contentInset.left - scrollView.contentInset.right + } + + open override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + view.setNeedsUpdateConstraints() + view.layoutSubviews() + } + + open override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + registerForKeyboardNotifications() + } + + // MARK: - Keyboard Handling + open func registerForKeyboardNotifications() { + if !keyboardNotificationsAdded { + keyboardNotificationsAdded = true + NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil) + } + } + + open func unregisterForKeyboardNotifications() { + if keyboardNotificationsAdded { + NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil) + NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil) + keyboardNotificationsAdded = false + } + } + + @objc open func keyboardWillShow(notification: Notification) { + // Stores the current scroll insets if the keyboard was hidden. + if !keyboardIsShowing { + preKeyboardContentInset = scrollView.contentInset + } + keyboardIsShowing = true + + // Enables the tap gesture. + dismissKeyboardTapGesture?.isEnabled = true + + MVMCoreUIUtility.setScrollViewInsetForKeyboardShow(notification, scrollView: scrollView, viewController: self) { [weak self] () -> CGRect in + return self?.rectToScrollToWhenKeyboardPopsUp() ?? .zero + } + } + + @objc open func keyboardWillBeHidden(notification: Notification) { + keyboardIsShowing = false + + // Disables the tap gesture. + dismissKeyboardTapGesture?.isEnabled = false + + MVMCoreUIUtility.setScrollViewInsetForKeyboardHide(notification, scrollView: scrollView, viewController: self, contentInset: preKeyboardContentInset ?? scrollView.contentInset) + } + + open func rectToScrollToWhenKeyboardPopsUp() -> CGRect? { + guard let field = selectedField, + let parent = selectedField?.superview else { return nil } + return scrollView.convert(field.frame, from: parent) + } +} diff --git a/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift b/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift index ae3d2fac..2fba0e07 100644 --- a/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift +++ b/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift @@ -9,7 +9,7 @@ import UIKit import MVMAnimationFramework -open class ThreeLayerTableViewController: MFProgrammaticTableViewController { +open class ThreeLayerTableViewController: ProgrammaticTableViewController { // The three main views private var topView: UIView? private var bottomView: UIView? @@ -36,17 +36,17 @@ open class ThreeLayerTableViewController: MFProgrammaticTableViewController { self.tableView?.reloadData() } - open override func newDataBuildScreen() { - super.newDataBuildScreen() + open override func handleNewData() { createViewForTableHeader() createViewForTableFooter() tableView?.reloadData() + super.handleNewData() } override open func viewDidLoad() { super.viewDidLoad() - setToHaveNoSectionHeadersFooters() // Do any additional setup after loading the view. + setNoSectionHeadersFooters() } //MARK: - Spacing @@ -227,26 +227,7 @@ open class ThreeLayerTableViewController: MFProgrammaticTableViewController { return view } - //MARK: - Scrollview - open override func scrollViewDidScroll(_ scrollView: UIScrollView) { - // To stop handscroll animation if animating after scroll - stopHandScrollAnimation(true) - } - deinit { tableView?.delegate = nil } - - //MARK: - Animation - open override func setupIntroAnimations() { - if let topView = topView, topView.subviews.count > 0 { - introAnimationManager?.addAnimation(animation: MVMAnimations.fadeUpAnimation(view: topView)) - } - if let tableView = tableView { - introAnimationManager?.addAnimation(animation: MVMAnimations.animateTableViewFadeInCells(tableView: tableView)) - } - if let bottomView = bottomView, bottomView.subviews.count > 0 { - introAnimationManager?.addAnimation(animation: MVMAnimations.fadeUpAnimation(view: bottomView)) - } - } } diff --git a/MVMCoreUI/BaseControllers/ThreeLayerViewController.swift b/MVMCoreUI/BaseControllers/ThreeLayerViewController.swift index ea6923c5..bf557814 100644 --- a/MVMCoreUI/BaseControllers/ThreeLayerViewController.swift +++ b/MVMCoreUI/BaseControllers/ThreeLayerViewController.swift @@ -61,21 +61,25 @@ open class ThreeLayerViewController: ProgrammaticScrollViewController { } } - open override func newDataBuildScreen() { - super.newDataBuildScreen() - + open override func handleNewData() { // Removes the views topView?.removeFromSuperview() middleView?.removeFromSuperview() bottomView?.removeFromSuperview() safeAreaView?.removeFromSuperview() - MVMCoreUIStackableViewController.remove(contentView?.subviews) + if let subViews = contentView?.subviews { + for view in subViews { + view.removeFromSuperview() + } + } // Reset constraints bottomConstraint?.isActive = true heightConstraint?.isActive = false setupLayers() + + super.handleNewData() } //MARK:-Functions to subclass @@ -241,18 +245,3 @@ extension ThreeLayerViewController { } } } - -//MARK:-Animation -extension ThreeLayerViewController { - open override func setupIntroAnimations() { - if let topView = topView, topView.subviews.count > 0 { - introAnimationManager?.addAnimation(animation: MVMAnimations.fadeUpAnimation(view: topView)) - } - if let middleView = middleView, middleView.subviews.count > 0 { - introAnimationManager?.addAnimation(animation: MVMAnimations.fadeUpAnimation(view: middleView)) - } - if let bottomView = bottomView, bottomView.subviews.count > 0 { - introAnimationManager?.addAnimation(animation: MVMAnimations.fadeUpAnimation(view: bottomView)) - } - } -} diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index 1bb06324..96b56ce4 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -8,19 +8,110 @@ import UIKit -@objcMembers open class ViewController: UIViewController, MVMCoreViewControllerProtocol { +open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMCoreViewManagerViewControllerProtocol, MoleculeDelegateProtocol, FormHolderProtocol, MVMCoreActionDelegateProtocol, UITextFieldDelegate, UITextViewDelegate { public var pageType: String? public var loadObject: MVMCoreLoadObject? public var pageModel: PageModelProtocol? + + /// Set if this page is containted in a manager. + public var manager: (UIViewController & MVMCoreViewManagerProtocol)? + + public var selfDelegateObject: MVMCoreUIDelegateObject? + public func delegateObject() -> DelegateObject? { + if selfDelegateObject == nil { + selfDelegateObject = MVMCoreUIDelegateObject.create(withDelegateForAll: self) + } + return selfDelegateObject + } + + public var formValidator: FormValidator? + + public var needsUpdateUI = true + private var observingForResponses = false + private var initialLoadFinished = false + private var previousScreenSize = CGSize.zero + + public var selectedField: UIView? - // MARK: Response handling - public func shouldFinishProcessingLoad(_ loadObject: MVMCoreLoadObject, error: AutoreleasingUnsafeMutablePointer) -> Bool { + /// Checks if the screen width has changed + open func screenSizeChanged() -> Bool { + return MVMCoreGetterUtility.cgfequalwiththreshold(previousScreenSize.width, view.bounds.size.width, 0.1) + } + + // MARK: - Response handling + open func observeForResponseJSONUpdates() { + guard !observingForResponses, + (pagesToListenFor()?.count ?? 0 > 0 || modulesToListenFor()?.count ?? 0 > 0) else { return } + observingForResponses = true + NotificationCenter.default.addObserver(self, selector: #selector(responseJSONUpdated(notification:)), name: NSNotification.Name(rawValue: NotificationResponseLoaded), object: nil) + } + + open func stopObservingForResponseJSONUpdates() { + guard observingForResponses else { return } + NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NotificationResponseLoaded), object: nil) + observingForResponses = false + } + + open func pagesToListenFor() -> [String]? { + guard let pageType = loadObject?.pageType else { return nil } + return [pageType] + } + + open func modulesToListenFor() -> [String]? { + return loadObject?.requestParameters?.modules as? [String] + } + + @objc open func responseJSONUpdated(notification: Notification) { + // Checks for a page we are listening for. + var newData = false + if let pagesLoaded = notification.userInfo?.optionalDictionaryForKey(KeyPageMap), + let pageType = pagesToListenFor()?.first(where: { (pageTypeListened) -> Bool in + guard let page = pagesLoaded.optionalDictionaryForKey(pageTypeListened), + let pageType = page.optionalStringForKey(KeyPageType), + pageType == pageTypeListened else { return false } + return true + }) { + newData = true + loadObject?.pageJSON = pagesLoaded.optionalDictionaryForKey(pageType) + } + + // Checks for modules we are listening for. + if let modulesLoaded = notification.userInfo?.optionalDictionaryForKey(KeyModuleMap), + let modulesListened = modulesToListenFor() { + for moduleName in modulesListened { + if let module = modulesLoaded.optionalDictionaryForKey(moduleName) { + newData = true + var currentModules = loadObject?.modulesJSON ?? [:] + currentModules.updateValue(module, forKey: moduleName) + loadObject?.modulesJSON = currentModules + } + } + } + + guard newData else { return } + do { + try parsePageJSON() + MVMCoreDispatchUtility.performBlock(onMainThread: { + self.handleNewDataAndUpdateUI() + }) + } catch { + if let coreError = MVMCoreErrorObject.createErrorObject(for: error, location: "updateJSON for pageType: \(String(describing: pageType))") { + MVMCoreLoggingHandler.shared()?.addError(toLog: coreError) + } + } + } + + open func shouldFinishProcessingLoad(_ loadObject: MVMCoreLoadObject, error: AutoreleasingUnsafeMutablePointer) -> Bool { pageType = loadObject.pageType self.loadObject = loadObject + // Verifies all modules needed are loaded. + guard MFViewController.verifyRequiredModulesLoaded(for: loadObject, error: error) else { return false } + // Parse the model for the page. do { try parsePageJSON() + return true } catch let parsingError { // Log all parsing errors and fail load. if let errorObject = MVMCoreErrorObject.createErrorObject(for: parsingError, location: MVMCoreLoadHandler.sharedGlobal()?.errorLocation(forRequest: loadObject)) { @@ -29,15 +120,12 @@ import UIKit } return false } - - // Verifies all modules needed are loaded. - return MFViewController.verifyRequiredModulesLoaded(for: loadObject, error: error) } - @objc func parsePageJSON() throws { + open func parsePageJSON() throws { } - public class func verifyRequiredModulesLoaded(for loadObject: MVMCoreLoadObject?, error: inout MVMCoreErrorObject?) -> Bool { + open class func verifyRequiredModulesLoaded(for loadObject: MVMCoreLoadObject?, error: inout MVMCoreErrorObject?) -> Bool { guard let pageType = loadObject?.pageType, var modulesRequired = MVMCoreUIViewControllerMappingObject.shared()?.modulesRequired(forPageType: pageType) else { return true } guard let loadedModules = loadObject?.modulesJSON else { return false } @@ -58,17 +146,28 @@ import UIKit return true } - open func setNavigationItem() { + open func set(navigationItem: UINavigationItem) { navigationItem.title = pageModel?.screenHeading navigationItem.accessibilityLabel = pageModel?.screenHeading } - - open func newDataBuildScreen() { - // TODO atomize the navigation item - setNavigationItem() + + /// Calls processNewData and then sets the ui to update with updateView + open func handleNewDataAndUpdateUI() { + handleNewData() + self.needsUpdateUI = true + self.view.setNeedsLayout() } + /// Processes any new data. Called after the page is loaded the first time and on response updates for this page, + open func handleNewData() { + // TODO atomize the navigation item + set(navigationItem: navigationItem) + formValidator?.validate() + } + + // MARK: - View lifecycle open func initialLoad() { + observeForResponseJSONUpdates() } open func updateViews() { @@ -78,5 +177,166 @@ import UIKit super.viewDidLoad() // Do any additional setup after loading the view. + MVMCoreLoggingHandler.logDebugMessage(withDelegate: "View Controller Loaded : \(self)") + + viewRespectsSystemMinimumLayoutMargins = false + + // Presents from the bottom. + modalPresentationStyle = MVMCoreGetterUtility.isOnIPad() ? UIModalPresentationStyle.formSheet : UIModalPresentationStyle.overCurrentContext + + // Do some initial loading. + if !initialLoadFinished { + initialLoadFinished = true + initialLoad() + } + + // Handle data on load + handleNewData() + + view.setNeedsLayout() + } + + open override func viewDidLayoutSubviews() { + // Add to fix a constraint bug where the width is zero and things get messed up. + guard isViewLoaded, + view.bounds.width > 1 else { + super.viewDidLayoutSubviews() + return + } + if needsUpdateUI || screenSizeChanged() { + updateViews() + needsUpdateUI = false + } + super.viewDidLayoutSubviews() + } + + open override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + // Update the navigation bar ui when view is appearing unless in a manager. The manager is expected to handle. + if manager == nil { + set(navigationItem: navigationItem) + } + } + + open override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + + if manager == nil { + MVMCoreUISession.sharedGlobal()?.currentPageType = pageType + MVMCoreUILoggingHandler.shared()?.defaultLogPageState(forController: self) + } + } + + deinit { + stopObservingForResponseJSONUpdates() + MVMCoreLoggingHandler.logDebugMessage(withDelegate: "View Controller Deallocated : \(self)") + } + + open override var supportedInterfaceOrientations: UIInterfaceOrientationMask { + return MVMCoreGetterUtility.isOnIPad() ? UIInterfaceOrientationMask.all : UIInterfaceOrientationMask.portrait + } + + open override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { + super.viewWillTransition(to: size, with: coordinator) + + // Updates the detail view width + coordinator.animate(alongsideTransition: { (UIViewControllerTransitionCoordinatorContext) in + }) { (UIViewControllerTransitionCoordinatorContext) in + self.view.setNeedsLayout() + } + } + + // MARK: - MVMCoreViewManagerViewControllerProtocol + open func viewControllerReady(inManager manager: UIViewController & MVMCoreViewManagerProtocol) { + if initialLoadFinished { + set(navigationItem: manager.navigationItem) + } + MVMCoreUISession.sharedGlobal()?.currentPageType = pageType + MVMCoreUILoggingHandler.shared()?.defaultLogPageState(forController: self) + } + + // MARK: - MVMCoreActionDelegateProtocol + open func handleOpenPage(for requestParameters: MVMCoreRequestParameters, actionInformation: [AnyHashable : Any]?, additionalData: [AnyHashable : Any]?) { + formValidator?.addFormParams(requestParameters: requestParameters) + requestParameters.parentPageType = loadObject?.pageJSON?.optionalStringForKey("parentPageType") + MVMCoreActionHandler.defaultHandleOpenPage(for: requestParameters, additionalData: additionalData, delegateObject: selfDelegateObject) + } + + // MARK: - MoleculeDelegateProtocol + 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 + } + + // Test to see if needed. + open func moleculeLayoutUpdated(_ molecule: UIView & MVMCoreUIMoleculeViewProtocol) { + + } + open func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) { + + } + open func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) { + + } + + // MARK: - UITextFieldDelegate (Check if this is still needed) + // To Remove TextFields Bug: Keyboard is not dismissing after reaching textfield max length limit + open func textFieldShouldReturn(_ textField: UITextField) -> Bool { + textField.resignFirstResponder() + return true + } + + open func textFieldDidBeginEditing(_ textField: UITextField) { + selectedField = textField + + // TODO: Make this into a protocol + if UIAccessibility.isVoiceOverRunning { + if let toolBar = textField.inputAccessoryView as? UIToolbar, let _ = toolBar.items?.last, let pickerView = textField.inputView as? UIPickerView { + view.accessibilityElements = [pickerView, toolBar] + } + DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { + UIAccessibility.post(notification: UIAccessibility.Notification.layoutChanged, argument: textField.inputView) + } + } + } + + open func textFieldDidEndEditing(_ textField: UITextField, reason: UITextField.DidEndEditingReason) { + if textField === selectedField { + if UIAccessibility.isVoiceOverRunning { + view.accessibilityElements = nil + UIAccessibility.post(notification: UIAccessibility.Notification.layoutChanged, argument: textField) + } + selectedField = nil + } + } + + @objc open func dismissFieldInput(sender: Any?) { + selectedField?.resignFirstResponder() + } + + // MARK: - UITextViewDelegate (Check if this is still needed) + open func textViewDidBeginEditing(_ textView: UITextView) { + selectedField = textView + } + + open func textViewDidEndEditing(_ textView: UITextView) { + if textView === selectedField { + selectedField = nil + } } } diff --git a/MVMCoreUI/Containers/TabBarController/MVMCoreUITabBarPageControlViewController.m b/MVMCoreUI/Containers/TabBarController/MVMCoreUITabBarPageControlViewController.m index cb48eb54..d700e57f 100644 --- a/MVMCoreUI/Containers/TabBarController/MVMCoreUITabBarPageControlViewController.m +++ b/MVMCoreUI/Containers/TabBarController/MVMCoreUITabBarPageControlViewController.m @@ -227,7 +227,7 @@ self.selectedIndex = i; [tabbar selectIndex:self.selectedIndex animated:NO]; - if ([self.viewController respondsToSelector:@selector(shouldCacheInManager)] && [((UIViewController *)self.viewController) shouldCacheInManager]) { + if (![self.viewController respondsToSelector:@selector(shouldCacheInManager)] || [((UIViewController *)self.viewController) shouldCacheInManager]) { [viewControllers addObject:self.viewController]; } else { [viewControllers addObject:[NSNull null]]; diff --git a/MVMCoreUI/FormUIHelpers/New/FormHolderProtocol.swift b/MVMCoreUI/FormUIHelpers/New/FormHolderProtocol.swift index 57c41a21..1e2f5522 100644 --- a/MVMCoreUI/FormUIHelpers/New/FormHolderProtocol.swift +++ b/MVMCoreUI/FormUIHelpers/New/FormHolderProtocol.swift @@ -12,6 +12,4 @@ import Foundation //Protocol for Validation public protocol FormHolderProtocol: NSObjectProtocol { var formValidator: FormValidator? { get set } - /// Should call formValidator's validate method - func validate() } diff --git a/MVMCoreUI/BaseControllers/ProgrammaticScrollViewController.h b/MVMCoreUI/Legacy/Controllers/MFProgrammaticScrollViewController.h similarity index 61% rename from MVMCoreUI/BaseControllers/ProgrammaticScrollViewController.h rename to MVMCoreUI/Legacy/Controllers/MFProgrammaticScrollViewController.h index 9e486066..f152b932 100644 --- a/MVMCoreUI/BaseControllers/ProgrammaticScrollViewController.h +++ b/MVMCoreUI/Legacy/Controllers/MFProgrammaticScrollViewController.h @@ -1,5 +1,5 @@ // -// ProgrammaticScrollViewController.h +// MFProgrammaticScrollViewController.h // myverizon // // Created by Scott Pfeil on 1/26/16. @@ -8,7 +8,7 @@ #import -@interface ProgrammaticScrollViewController : MFScrollingViewController +@interface MFProgrammaticScrollViewController : MFScrollingViewController @end diff --git a/MVMCoreUI/BaseControllers/ProgrammaticScrollViewController.m b/MVMCoreUI/Legacy/Controllers/MFProgrammaticScrollViewController.m similarity index 92% rename from MVMCoreUI/BaseControllers/ProgrammaticScrollViewController.m rename to MVMCoreUI/Legacy/Controllers/MFProgrammaticScrollViewController.m index 2bfeb35d..5152ec79 100644 --- a/MVMCoreUI/BaseControllers/ProgrammaticScrollViewController.m +++ b/MVMCoreUI/Legacy/Controllers/MFProgrammaticScrollViewController.m @@ -1,21 +1,21 @@ // -// ProgrammaticScrollViewController.m +// MFProgrammaticScrollViewController.m // myverizon // // Created by Scott Pfeil on 1/26/16. // Copyright © 2016 Verizon Wireless. All rights reserved. // -#import "ProgrammaticScrollViewController.h" +#import "MFProgrammaticScrollViewController.h" @import MVMCore.NSDictionary_MFConvenience; #import "NSLayoutConstraint+MFConvenience.h" #import "MVMCoreUICommonViewsUtility.h" -@interface ProgrammaticScrollViewController () +@interface MFProgrammaticScrollViewController () @end -@implementation ProgrammaticScrollViewController +@implementation MFProgrammaticScrollViewController - (void)loadView { diff --git a/MVMCoreUI/BaseControllers/MFProgrammaticTableViewController.h b/MVMCoreUI/Legacy/Controllers/MFProgrammaticTableViewController.h similarity index 100% rename from MVMCoreUI/BaseControllers/MFProgrammaticTableViewController.h rename to MVMCoreUI/Legacy/Controllers/MFProgrammaticTableViewController.h diff --git a/MVMCoreUI/BaseControllers/MFProgrammaticTableViewController.m b/MVMCoreUI/Legacy/Controllers/MFProgrammaticTableViewController.m similarity index 100% rename from MVMCoreUI/BaseControllers/MFProgrammaticTableViewController.m rename to MVMCoreUI/Legacy/Controllers/MFProgrammaticTableViewController.m diff --git a/MVMCoreUI/BaseControllers/MFScrollingViewController.h b/MVMCoreUI/Legacy/Controllers/MFScrollingViewController.h similarity index 100% rename from MVMCoreUI/BaseControllers/MFScrollingViewController.h rename to MVMCoreUI/Legacy/Controllers/MFScrollingViewController.h diff --git a/MVMCoreUI/BaseControllers/MFScrollingViewController.m b/MVMCoreUI/Legacy/Controllers/MFScrollingViewController.m similarity index 100% rename from MVMCoreUI/BaseControllers/MFScrollingViewController.m rename to MVMCoreUI/Legacy/Controllers/MFScrollingViewController.m diff --git a/MVMCoreUI/BaseControllers/MFViewController+Form.swift b/MVMCoreUI/Legacy/Controllers/MFViewController+Form.swift similarity index 100% rename from MVMCoreUI/BaseControllers/MFViewController+Form.swift rename to MVMCoreUI/Legacy/Controllers/MFViewController+Form.swift diff --git a/MVMCoreUI/BaseControllers/MFViewController+Model.swift b/MVMCoreUI/Legacy/Controllers/MFViewController+Model.swift similarity index 100% rename from MVMCoreUI/BaseControllers/MFViewController+Model.swift rename to MVMCoreUI/Legacy/Controllers/MFViewController+Model.swift diff --git a/MVMCoreUI/BaseControllers/MFViewController.h b/MVMCoreUI/Legacy/Controllers/MFViewController.h similarity index 100% rename from MVMCoreUI/BaseControllers/MFViewController.h rename to MVMCoreUI/Legacy/Controllers/MFViewController.h diff --git a/MVMCoreUI/BaseControllers/MFViewController.m b/MVMCoreUI/Legacy/Controllers/MFViewController.m similarity index 100% rename from MVMCoreUI/BaseControllers/MFViewController.m rename to MVMCoreUI/Legacy/Controllers/MFViewController.m diff --git a/MVMCoreUI/BaseControllers/MVMCoreUIStackableViewController.h b/MVMCoreUI/Legacy/Controllers/MVMCoreUIStackableViewController.h similarity index 95% rename from MVMCoreUI/BaseControllers/MVMCoreUIStackableViewController.h rename to MVMCoreUI/Legacy/Controllers/MVMCoreUIStackableViewController.h index 0c702925..12d02f43 100644 --- a/MVMCoreUI/BaseControllers/MVMCoreUIStackableViewController.h +++ b/MVMCoreUI/Legacy/Controllers/MVMCoreUIStackableViewController.h @@ -6,9 +6,9 @@ // Copyright © 2019 Verizon Wireless. All rights reserved. // -#import +#import -@interface MVMCoreUIStackableViewController : ProgrammaticScrollViewController +@interface MVMCoreUIStackableViewController : MFProgrammaticScrollViewController // An array of ui elements that will be spaced out on the screen top to bottom from index 0 to formUIArray.count. @property (nullable, strong, nonatomic) NSArray *formUIArray; diff --git a/MVMCoreUI/BaseControllers/MVMCoreUIStackableViewController.m b/MVMCoreUI/Legacy/Controllers/MVMCoreUIStackableViewController.m similarity index 100% rename from MVMCoreUI/BaseControllers/MVMCoreUIStackableViewController.m rename to MVMCoreUI/Legacy/Controllers/MVMCoreUIStackableViewController.m diff --git a/MVMCoreUI/MVMCoreUI.h b/MVMCoreUI/MVMCoreUI.h index 5e8c92cc..22707550 100644 --- a/MVMCoreUI/MVMCoreUI.h +++ b/MVMCoreUI/MVMCoreUI.h @@ -48,7 +48,7 @@ FOUNDATION_EXPORT const unsigned char MVMCoreUIVersionString[]; #pragma mark - BaseControllers #import #import -#import +#import #import #import #import diff --git a/MVMCoreUI/Models/ModelProtocols/PageModelProtocol.swift b/MVMCoreUI/Models/ModelProtocols/PageModelProtocol.swift index 34b58818..7f50873e 100644 --- a/MVMCoreUI/Models/ModelProtocols/PageModelProtocol.swift +++ b/MVMCoreUI/Models/ModelProtocols/PageModelProtocol.swift @@ -13,4 +13,5 @@ public protocol PageModelProtocol { var pageType: String { get set } var screenHeading: String? { get set } var isAtomicTabs: Bool? { get set } + var navigationItem: NavigationItemModelProtocol? { get set } } diff --git a/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift b/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift index f9b9d976..0661e3ed 100644 --- a/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift +++ b/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift @@ -29,15 +29,14 @@ import UIKit guard newValue != oldValue, let self = self, let index = self.dropDown.pickerData.firstIndex(of: newValue), - let dropListItemJSON = (self.listItemModel as? DropDownListItemModel).toJSON(), - let json2d = dropListItemJSON.optionalArrayForKey("molecules") as? [[[AnyHashable: Any]]] + let molecules2D = (self.listItemModel as? DropDownListItemModel)?.molecules else { return } if self.previousIndex != NSNotFound { - self.delegateObject?.moleculeDelegate?.removeMolecules(json2d[self.previousIndex], sender: self, animation: .fade) + self.delegateObject?.moleculeDelegate?.removeMolecules(molecules2D[self.previousIndex], sender: self, animation: .fade) } - self.delegateObject?.moleculeDelegate?.addMolecules(json2d[index], sender: self, animation: .fade) + self.delegateObject?.moleculeDelegate?.addMolecules(molecules2D[index], sender: self, animation: .fade) self.previousIndex = index } } diff --git a/MVMCoreUI/Molecules/NavigationItemModelProtocol.swift b/MVMCoreUI/Molecules/NavigationItemModelProtocol.swift new file mode 100644 index 00000000..acddb931 --- /dev/null +++ b/MVMCoreUI/Molecules/NavigationItemModelProtocol.swift @@ -0,0 +1,17 @@ +// +// NavigationItemModelProtocol.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 3/12/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public protocol NavigationItemModelProtocol: ModelProtocol { + +} + +public protocol NavigationItemButtonModelProtocol { + +} diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.h b/MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.h index 003d67f8..9fec90f5 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.h +++ b/MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.h @@ -14,11 +14,11 @@ NS_ASSUME_NONNULL_BEGIN @interface MVMCoreUILoggingHandler : MVMCoreLoggingHandler // Page State Logging -- (void)defaultLogPageStateForController:(nonnull MFViewController *)controller; +- (void)defaultLogPageStateForController:(nonnull id )controller; // Action Logging -- (void)defaultLogActionForController:(nonnull MFViewController *)controller actionInformation:(nullable NSDictionary *)actionInformation additionalData:(nullable NSDictionary *)additionalData; -- (nullable NSDictionary *)defaultGetActionTrackDataDictionaryForController:(nonnull MFViewController *)controller actionInformation:(nullable NSDictionary *)actionInformation additionalData:(nullable NSDictionary *)additionalData; +- (void)defaultLogActionForController:(nonnull id )controller actionInformation:(nullable NSDictionary *)actionInformation additionalData:(nullable NSDictionary *)additionalData; +- (nullable NSDictionary *)defaultGetActionTrackDataDictionaryForController:(nonnull id )controller actionInformation:(nullable NSDictionary *)actionInformation additionalData:(nullable NSDictionary *)additionalData; @end diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.m b/MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.m index 6395fbcc..0c694cce 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.m @@ -10,13 +10,13 @@ @implementation MVMCoreUILoggingHandler -- (void)defaultLogPageStateForController:(nonnull MFViewController *)controller { +- (void)defaultLogPageStateForController:(nonnull id )controller { } -- (void)defaultLogActionForController:(nonnull MFViewController *)controller actionInformation:(nullable NSDictionary *)actionInformation additionalData:(nullable NSDictionary *)additionalData { +- (void)defaultLogActionForController:(nonnull id )controller actionInformation:(nullable NSDictionary *)actionInformation additionalData:(nullable NSDictionary *)additionalData { } -- (nullable NSDictionary *)defaultGetActionTrackDataDictionaryForController:(nonnull MFViewController *)controller actionInformation:(nullable NSDictionary *)actionInformation additionalData:(nullable NSDictionary *)additionalData { +- (nullable NSDictionary *)defaultGetActionTrackDataDictionaryForController:(nonnull id )controller actionInformation:(nullable NSDictionary *)actionInformation additionalData:(nullable NSDictionary *)additionalData { return nil; } diff --git a/MVMCoreUI/Templates/ListPageTemplateModel.swift b/MVMCoreUI/Templates/ListPageTemplateModel.swift index 12c300f9..99e87809 100644 --- a/MVMCoreUI/Templates/ListPageTemplateModel.swift +++ b/MVMCoreUI/Templates/ListPageTemplateModel.swift @@ -22,6 +22,7 @@ import Foundation public var pageType: String public var screenHeading: String? public var isAtomicTabs: Bool? + public var navigationItem: NavigationItemModelProtocol? public var header: MoleculeModelProtocol? public var molecules: [ListItemModelProtocol & MoleculeModelProtocol]? diff --git a/MVMCoreUI/Templates/ModalMoleculeListTemplate.swift b/MVMCoreUI/Templates/ModalMoleculeListTemplate.swift index 6dae1700..303ceba1 100644 --- a/MVMCoreUI/Templates/ModalMoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/ModalMoleculeListTemplate.swift @@ -10,11 +10,13 @@ import UIKit open class ModalMoleculeListTemplate: MoleculeListTemplate { - override open func newDataBuildScreen() { - super.newDataBuildScreen() + override open func handleNewData() { MVMCoreUICommonViewsUtility.addCloseButton(to: view, action: {[weak self] _ in - self?.dismiss() + if let _ = self { + MVMCoreNavigationHandler.shared()?.removeCurrentViewController() + } }, verticalCentered: false) + super.handleNewData() } } diff --git a/MVMCoreUI/Templates/ModalMoleculeStackTemplate.swift b/MVMCoreUI/Templates/ModalMoleculeStackTemplate.swift index 9f1ea9b9..b50400a7 100644 --- a/MVMCoreUI/Templates/ModalMoleculeStackTemplate.swift +++ b/MVMCoreUI/Templates/ModalMoleculeStackTemplate.swift @@ -10,10 +10,12 @@ import UIKit open class ModalMoleculeStackTemplate: MoleculeStackTemplate { - override open func newDataBuildScreen() { - super.newDataBuildScreen() + override open func handleNewData() { + super.handleNewData() MVMCoreUICommonViewsUtility.addCloseButton(to: view, action: {[weak self] _ in - self?.dismiss() + if let _ = self { + MVMCoreNavigationHandler.shared()?.removeCurrentViewController() + } }, verticalCentered: false) } diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index 1ea13b4c..722e90a7 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -12,12 +12,6 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol //-------------------------------------------------- // MARK: - Stored Properties //-------------------------------------------------- - - public var formValidator: FormValidator? - public func validate() { - // Can override - } - public var moleculesInfo: [(identifier: String, class: AnyClass, molecule: (ListItemModelProtocol & MoleculeModelProtocol))]? var observer: NSKeyValueObservation? @@ -27,13 +21,8 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol //-------------------------------------------------- // MARK: - Computed Properties //-------------------------------------------------- - - open override func parsePageJSON(_ error: NSErrorPointer) { - do { - try parseTemplateJSON() - } catch let parseError { - error?.pointee = parseError as NSError - } + open override func parsePageJSON() throws { + try parseTemplateJSON() } open override var loadObject: MVMCoreLoadObject? { @@ -90,10 +79,10 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol return true } - open override func newDataBuildScreen() { - super.newDataBuildScreen() + open override func handleNewData() { setup() registerWithTable() + super.handleNewData() } //-------------------------------------------------- @@ -109,7 +98,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol } } - open override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { + open func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { guard let moleculeInfo = moleculesInfo?[indexPath.row], let estimatedHeight = (moleculeInfo.class as? ModelMoleculeViewProtocol.Type)?.estimatedHeight(with: moleculeInfo.molecule, delegateObject() as? MVMCoreUIDelegateObject) else { return 0 } @@ -127,47 +116,33 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol let cell = tableView.dequeueReusableCell(withIdentifier: moleculeInfo.identifier) else { return UITableViewCell() } - let delegate = delegateObject() as? MVMCoreUIDelegateObject let moleculeCell = cell as? MVMCoreUIMoleculeViewProtocol moleculeCell?.reset?() if let protocolCell = cell as? MoleculeListCellProtocol { - protocolCell.setLines(with: templateModel?.line, delegateObject: delegate, additionalData: nil, indexPath: indexPath) + protocolCell.setLines(with: templateModel?.line, delegateObject: selfDelegateObject, additionalData: nil, indexPath: indexPath) } - (moleculeCell as? ModelMoleculeViewProtocol)?.set(with: moleculeInfo.molecule, delegate, nil) + (moleculeCell as? ModelMoleculeViewProtocol)?.set(with: moleculeInfo.molecule, selfDelegateObject, nil) moleculeCell?.updateView(tableView.bounds.width) return cell } - open override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { + open func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { if let protocolCell = cell as? MoleculeListCellProtocol { protocolCell.willDisplay() } } - open override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + open func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { if let cell = tableView.cellForRow(at: indexPath) as? MoleculeListCellProtocol { cell.didSelectCell(at: indexPath, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, additionalData: nil) } } - //-------------------------------------------------- - // MARK: - Cache Handling - //-------------------------------------------------- - - open override func pageTypesToListenFor() -> [Any]? { - guard let pageType = self.pageType else { return super.pageTypesToListenFor() } - return [pageType] - } - - open override func modulesToListenFor() -> [Any]? { - return loadObject?.requestParameters?.modules - } - //-------------------------------------------------- // MARK: - MoleculeDelegateProtocol //-------------------------------------------------- @@ -183,7 +158,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol } } - public override func addMolecules(_ molecules: [[AnyHashable: Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) { + public func addMolecules(_ molecules: [[AnyHashable: Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) { var tmpMolecules = [ListItemModelProtocol & MoleculeModelProtocol]() @@ -212,7 +187,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol } } - public override func removeMolecules(_ molecules: [[AnyHashable: Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) { + public func removeMolecules(_ molecules: [[AnyHashable: Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) { var tmpMolecules = [ListItemModelProtocol & MoleculeModelProtocol]() @@ -240,7 +215,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol view.layoutIfNeeded() } - public func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) { + open override func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) { // This dispatch is needed to fix a race condition that can occur if this function is called during the table setup. DispatchQueue.main.async { @@ -262,7 +237,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol } } - public func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) { + open override func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) { var indexPaths: [IndexPath] = [] //TODO: cehck for molecule protocola eqality diff --git a/MVMCoreUI/Templates/MoleculeStackTemplate.swift b/MVMCoreUI/Templates/MoleculeStackTemplate.swift index 6a895120..f68cfa1a 100644 --- a/MVMCoreUI/Templates/MoleculeStackTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeStackTemplate.swift @@ -9,20 +9,11 @@ import UIKit open class MoleculeStackTemplate: ThreeLayerViewController, TemplateProtocol { - public func validate() { - - } - - public var formValidator: FormValidator? - var observer: NSKeyValueObservation? public var templateModel: StackPageTemplateModel? - open override func parsePageJSON(_ error: NSErrorPointer) { - do { - try parseTemplateJSON() - } catch let parseError { - error?.pointee = parseError as NSError - } + + open override func parsePageJSON() throws { + try parseTemplateJSON() } open override var loadObject: MVMCoreLoadObject? { @@ -73,17 +64,7 @@ open class MoleculeStackTemplate: ThreeLayerViewController, TemplateProtocol { } // MARK: - cache handling - open override func pageTypesToListenFor() -> [Any]? { - guard let pageType = self.pageType else { - return super.pageTypesToListenFor() - } - return [pageType] - } - - open override func modulesToListenFor() -> [Any]? { - return loadObject?.requestParameters?.modules - } - + /// Adds modules from requiredModules() to the MVMCoreViewControllerMapping.requiredModules map. open func updateRequiredModules() { if let requiredModules = requiredModules(), let pageType = pageType { diff --git a/MVMCoreUI/Templates/StackCenteredPageTemplateModel.swift b/MVMCoreUI/Templates/StackCenteredPageTemplateModel.swift index 66cd0365..f3bde0e7 100644 --- a/MVMCoreUI/Templates/StackCenteredPageTemplateModel.swift +++ b/MVMCoreUI/Templates/StackCenteredPageTemplateModel.swift @@ -17,6 +17,7 @@ import Foundation public var pageType: String public var screenHeading: String? public var isAtomicTabs: Bool? + public var navigationItem: NavigationItemModelProtocol? public init(pageType: String) { self.pageType = pageType diff --git a/MVMCoreUI/Templates/StackPageTemplateModel.swift b/MVMCoreUI/Templates/StackPageTemplateModel.swift index ed94e4ef..28600453 100644 --- a/MVMCoreUI/Templates/StackPageTemplateModel.swift +++ b/MVMCoreUI/Templates/StackPageTemplateModel.swift @@ -18,6 +18,7 @@ import Foundation public var pageType: String public var screenHeading: String? public var isAtomicTabs: Bool? + public var navigationItem: NavigationItemModelProtocol? public var header: MoleculeModelProtocol? public var moleculeStack: MoleculeStackModel diff --git a/MVMCoreUI/Templates/TemplateProtocol.swift b/MVMCoreUI/Templates/TemplateProtocol.swift index fcb6bde2..f4717774 100644 --- a/MVMCoreUI/Templates/TemplateProtocol.swift +++ b/MVMCoreUI/Templates/TemplateProtocol.swift @@ -14,7 +14,7 @@ public protocol TemplateProtocol: FormHolderProtocol { var templateModel: TemplateModel? { get set } } -public extension TemplateProtocol where Self: MFViewController { +public extension TemplateProtocol where Self: ViewController { func parseTemplateJSON() throws { guard let pageJSON = self.loadObject?.pageJSON else { return } let data = try JSONSerialization.data(withJSONObject: pageJSON) diff --git a/MVMCoreUI/Templates/ThreeLayerPageTemplateModel.swift b/MVMCoreUI/Templates/ThreeLayerPageTemplateModel.swift index 5ad39c4b..fff9bdb8 100644 --- a/MVMCoreUI/Templates/ThreeLayerPageTemplateModel.swift +++ b/MVMCoreUI/Templates/ThreeLayerPageTemplateModel.swift @@ -18,6 +18,7 @@ import Foundation public var pageType: String public var screenHeading: String? public var isAtomicTabs: Bool? + public var navigationItem: NavigationItemModelProtocol? public var header: MoleculeModelProtocol? public var middle: MoleculeModelProtocol? diff --git a/MVMCoreUI/Templates/ThreeLayerTemplate.swift b/MVMCoreUI/Templates/ThreeLayerTemplate.swift index 148d102d..0f400027 100644 --- a/MVMCoreUI/Templates/ThreeLayerTemplate.swift +++ b/MVMCoreUI/Templates/ThreeLayerTemplate.swift @@ -12,17 +12,10 @@ import UIKit public func validate() { } - - public var formValidator: FormValidator? - public var templateModel: ThreeLayerPageTemplateModel? - open override func parsePageJSON(_ error: NSErrorPointer) { - do { - try parseTemplateJSON() - } catch let parseError { - error?.pointee = parseError as NSError - } + open override func parsePageJSON() throws { + try parseTemplateJSON() } override open func viewDidLoad() { @@ -31,8 +24,8 @@ import UIKit // Do any additional setup after loading the view. } - open override func newDataBuildScreen() { - super.newDataBuildScreen() + open override func handleNewData() { + super.handleNewData() heightConstraint?.isActive = true } From 2d3eb3351ba0aad42f389f913f7b3a32cb5a8834 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 13 Mar 2020 11:59:34 -0400 Subject: [PATCH 02/17] legacy navigation logic --- .../BaseControllers/ViewController.swift | 127 ++++++++++++++++-- 1 file changed, 115 insertions(+), 12 deletions(-) diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index 96b56ce4..c2b6f55a 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -32,6 +32,26 @@ open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMC private var previousScreenSize = CGSize.zero public var selectedField: UIView? + + public var masterShouldBeAccessible: Bool = false { + didSet { + if let manager = manager as? MFViewController { + manager.masterShouldBeAccessible = masterShouldBeAccessible + } else if MVMCoreUISplitViewController.main()?.getCurrentVisibleController() == self { + MVMCoreUISplitViewController.main()?.setLeftPanelIsAccessible(masterShouldBeAccessible, for: self) + } + } + } + + public var supportShouldBeAccessible: Bool = false { + didSet { + if let manager = manager as? MFViewController { + manager.supportShouldBeAccessible = supportShouldBeAccessible + } else if MVMCoreUISplitViewController.main()?.getCurrentVisibleController() == self { + MVMCoreUISplitViewController.main()?.setRightPanelIsAccessible(supportShouldBeAccessible, for: self) + } + } + } /// Checks if the screen width has changed open func screenSizeChanged() -> Bool { @@ -105,7 +125,7 @@ open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMC pageType = loadObject.pageType self.loadObject = loadObject - // Verifies all modules needed are loaded. + // Verifies all modules needed are loaded. TODO: change to ViewController guard MFViewController.verifyRequiredModulesLoaded(for: loadObject, error: error) else { return false } // Parse the model for the page. @@ -146,11 +166,6 @@ open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMC return true } - open func set(navigationItem: UINavigationItem) { - navigationItem.title = pageModel?.screenHeading - navigationItem.accessibilityLabel = pageModel?.screenHeading - } - /// Calls processNewData and then sets the ui to update with updateView open func handleNewDataAndUpdateUI() { handleNewData() @@ -161,9 +176,100 @@ open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMC /// Processes any new data. Called after the page is loaded the first time and on response updates for this page, open func handleNewData() { // TODO atomize the navigation item - set(navigationItem: navigationItem) + set(navigationController: navigationController) formValidator?.validate() } + + // MARK: - Navigation Item (Move to model base) + open func set(navigationController: UINavigationController?) { + navigationItem.title = pageModel?.screenHeading + navigationItem.accessibilityLabel = pageModel?.screenHeading + guard let navigationController = navigationController else { + MVMCoreUISession.sharedGlobal()?.splitViewController?.parent?.setNeedsStatusBarAppearanceUpdate() + return + } + navigationController.setNavigationBarHidden(isNavigationBarHidden(), animated: true) + UIColor.setBackgroundColor(forNavigationBar: navigationBarColor(), navigationBar: navigationController.navigationBar, transparent: navigationBarTransparent()) + + let tint = navigationBarTintColor() ?? .black + navigationController.navigationBar.tintColor = tint + + // Have the navigation title match the tint color + navigationController.navigationBar.titleTextAttributes?.updateValue(navigationBarTintColor, forKey: .foregroundColor) + + if navigationController == MVMCoreUISplitViewController.main()?.navigationController { + // Update icons if main navigation controller. + MVMCoreUISession.sharedGlobal()?.splitViewController?.setupPanels() + let master = masterShouldBeAccessible + masterShouldBeAccessible = master + let support = supportShouldBeAccessible + supportShouldBeAccessible = support + + showBottomProgressBar() + MVMCoreUISession.sharedGlobal()?.splitViewController?.setNavigationIconColor(tint) + + // Update separator. + MVMCoreUISession.sharedGlobal()?.navigationController?.separatorView?.isHidden = /*self is MVMCoreUITabBarPageControlViewController ||*/ manager != nil || loadObject?.requestParameters?.tabWasPressed ?? false == true + } + } + + open func navigationBarColor() -> UIColor { + return .white + } + + open func isNavigationBarHidden() -> Bool { + return false + } + + open func navigationBarTransparent() -> Bool { + return false + } + + open func navigationBarTintColor() -> UIColor? { + return nil + } + + open func isMasterInitiallyAccessible() -> Bool { + if loadObject?.pageJSON?.boolForKey(KeyHideMainMenu) ?? false { + return false + } + return MVMCoreUISession.sharedGlobal()?.launchAppLoadedSuccessfully ?? false + } + + open func isSupportInitiallyAccessible() -> Bool { + if loadObject?.pageJSON?.boolForKey(KeyHideMainMenu) ?? false { + return false + } + return (MVMCoreUISession.sharedGlobal()?.launchAppLoadedSuccessfully ?? false) || showRightPanelForScreenBeforeLaunchApp() + } + + open func showRightPanelForScreenBeforeLaunchApp() -> Bool { + return loadObject?.pageJSON?.lenientBoolForKey("showRightPanel") ?? false + } + + open func isOverridingRightButton() -> Bool { + guard let rightPanelLink = loadObject?.pageJSON?.optionalDictionaryForKey("rightPanelButtonLink") else { + return false + } + MVMCoreActionHandler.shared()?.handleAction(with: rightPanelLink, additionalData: nil, delegateObject: delegateObject()) + return true + } + + open func isOverridingLeftButton() -> Bool { + guard let leftPanelLink = loadObject?.pageJSON?.optionalDictionaryForKey("leftPanelButtonLink") else { + return false + } + MVMCoreActionHandler.shared()?.handleAction(with: leftPanelLink, additionalData: nil, delegateObject: delegateObject()) + return true + } + + open func showBottomProgressBar() { + if MVMCoreUISplitViewController.main()?.getCurrentVisibleController() == self, + let progressString = loadObject?.pageJSON?.optionalStringForKey(KeyProgressPercent), + let progress = Float(progressString) { + MVMCoreUISplitViewController.main()?.setBottomProgressBarProgress(progress / Float(100)) + } + } // MARK: - View lifecycle open func initialLoad() { @@ -215,7 +321,7 @@ open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMC // Update the navigation bar ui when view is appearing unless in a manager. The manager is expected to handle. if manager == nil { - set(navigationItem: navigationItem) + set(navigationController: navigationController) } } @@ -250,7 +356,7 @@ open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMC // MARK: - MVMCoreViewManagerViewControllerProtocol open func viewControllerReady(inManager manager: UIViewController & MVMCoreViewManagerProtocol) { if initialLoadFinished { - set(navigationItem: manager.navigationItem) + set(navigationController: manager.navigationController) } MVMCoreUISession.sharedGlobal()?.currentPageType = pageType MVMCoreUILoggingHandler.shared()?.defaultLogPageState(forController: self) @@ -285,13 +391,10 @@ open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMC // Test to see if needed. open func moleculeLayoutUpdated(_ molecule: UIView & MVMCoreUIMoleculeViewProtocol) { - } open func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) { - } open func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) { - } // MARK: - UITextFieldDelegate (Check if this is still needed) From 7793bcfcb6be81d3c53a5a749f2392da0f847ac8 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 13 Mar 2020 13:31:33 -0400 Subject: [PATCH 03/17] update index functions --- .../BaseControllers/ViewController.swift | 10 +-- .../AccordionMoleculeTableViewCell.swift | 14 ++-- .../Items/DropDownFilterTableViewCell.swift | 8 +- .../Molecules/Items/TabsTableViewCell.swift | 18 ++--- .../ModelMoleculeDelegateProtocol.swift | 37 ++------- .../Templates/MoleculeListTemplate.swift | 78 +++---------------- 6 files changed, 37 insertions(+), 128 deletions(-) diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index 919703b3..7aca8f01 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -391,13 +391,11 @@ open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMC return nil } - // Test to see if needed. + // Needed otherwise when subclassed, the extension gets called. open func moleculeLayoutUpdated(_ molecule: UIView & MVMCoreUIMoleculeViewProtocol) {} - open func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) {} - open func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) {} - open func addMolecules(_ molecules: [[AnyHashable: Any]], indexPath: IndexPath, animation: UITableView.RowAnimation) {} - open func addMolecules(_ molecules: [[AnyHashable: Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) {} - open func removeMolecules(_ molecules: [[AnyHashable: Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) {} + open func getIndexPath(for molecule: ListItemModelProtocol & MoleculeModelProtocol) -> IndexPath? { return nil } + open func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], indexPath: IndexPath, animation: UITableView.RowAnimation) {} + open func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], animation: UITableView.RowAnimation) {} // MARK: - UITextFieldDelegate (Check if this is still needed) // To Remove TextFields Bug: Keyboard is not dismissing after reaching textfield max length limit diff --git a/MVMCoreUI/Molecules/Items/AccordionMoleculeTableViewCell.swift b/MVMCoreUI/Molecules/Items/AccordionMoleculeTableViewCell.swift index 714c7dd9..a7970861 100644 --- a/MVMCoreUI/Molecules/Items/AccordionMoleculeTableViewCell.swift +++ b/MVMCoreUI/Molecules/Items/AccordionMoleculeTableViewCell.swift @@ -32,18 +32,14 @@ import UIKit override public func didSelectCell(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { accordionButton.isSelected = !accordionButton.isSelected accordionButton.setTitle(accordionButton.isSelected ? "-" : "+", for: .normal) - guard let model = accordionListItemModel else { - return - } - - guard let json = model.toJSON(), - let molecules = json.optionalArrayForKey("molecules") as? [[AnyHashable: Any]] - else { return } + guard let model = accordionListItemModel else { return } if accordionButton.isSelected { - delegateObject?.moleculeDelegate?.addMolecules(molecules, sender: self, animation: .automatic) + if let indexPath = delegateObject?.moleculeDelegate?.getIndexPath(for: model) { + delegateObject?.moleculeDelegate?.addMolecules(model.molecules, indexPath: indexPath, animation: .automatic) + } } else { - delegateObject?.moleculeDelegate?.removeMolecules(molecules, sender: self, animation: .automatic) + delegateObject?.moleculeDelegate?.removeMolecules(model.molecules, animation: .automatic) } if (accordionListItemModel?.hideLineWhenExpanded ?? false) && (self.bottomSeparatorView?.shouldBeVisible() ?? false) { diff --git a/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift b/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift index 0661e3ed..aa581ba1 100644 --- a/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift +++ b/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift @@ -29,14 +29,16 @@ import UIKit guard newValue != oldValue, let self = self, let index = self.dropDown.pickerData.firstIndex(of: newValue), - let molecules2D = (self.listItemModel as? DropDownListItemModel)?.molecules + let model = self.listItemModel as? DropDownListItemModel else { return } if self.previousIndex != NSNotFound { - self.delegateObject?.moleculeDelegate?.removeMolecules(molecules2D[self.previousIndex], sender: self, animation: .fade) + self.delegateObject?.moleculeDelegate?.removeMolecules(model.molecules[self.previousIndex], animation: .fade) } - self.delegateObject?.moleculeDelegate?.addMolecules(molecules2D[index], sender: self, animation: .fade) + if let indexPath = self.delegateObject?.moleculeDelegate?.getIndexPath(for: model) { + self.delegateObject?.moleculeDelegate?.addMolecules(model.molecules[index], indexPath: indexPath, animation: .fade) + } self.previousIndex = index } } diff --git a/MVMCoreUI/Molecules/Items/TabsTableViewCell.swift b/MVMCoreUI/Molecules/Items/TabsTableViewCell.swift index da700a28..cb6ee755 100644 --- a/MVMCoreUI/Molecules/Items/TabsTableViewCell.swift +++ b/MVMCoreUI/Molecules/Items/TabsTableViewCell.swift @@ -54,23 +54,19 @@ import UIKit extension TabsTableViewCell: TopTabbarDelegate { public func shouldSelectItem(at index: Int, topTabbar: TopTabbar) -> Bool { - if let model = tabsListItemModel, - let json = model.toJSON(), - let json2d = json.optionalArrayForKey("molecules") as? [[[AnyHashable: Any]]] { - let molecules = json2d[topTabbar.selectedIndex] - delegateObject?.moleculeDelegate?.removeMolecules(molecules, sender: self, animation: index < tabs.selectedIndex ? .right : .left) + if let model = tabsListItemModel { + let molecules = model.molecules[topTabbar.selectedIndex] + delegateObject?.moleculeDelegate?.removeMolecules(molecules, animation: index < tabs.selectedIndex ? .right : .left) } previousTabIndex = tabs.selectedIndex return true } public func topTabbar(_ topTabbar: TopTabbar, didSelectItemAt index: Int) { - if let model = tabsListItemModel, - let json = model.toJSON(), - let json2d = json.optionalArrayForKey("molecules") as? [[[AnyHashable: Any]]] { - let molecules = json2d[index] - delegateObject?.moleculeDelegate?.addMolecules(molecules, sender: self, animation: index < previousTabIndex ? .left : .right) - } + guard let model = tabsListItemModel, + let indexPath = delegateObject?.moleculeDelegate?.getIndexPath(for: model) else { return } + let molecules = model.molecules[index] + delegateObject?.moleculeDelegate?.addMolecules(molecules, indexPath: indexPath, animation: index < previousTabIndex ? .left : .right) } } diff --git a/MVMCoreUI/OtherHandlers/ModelMoleculeDelegateProtocol.swift b/MVMCoreUI/OtherHandlers/ModelMoleculeDelegateProtocol.swift index eb175c3a..435e5a24 100644 --- a/MVMCoreUI/OtherHandlers/ModelMoleculeDelegateProtocol.swift +++ b/MVMCoreUI/OtherHandlers/ModelMoleculeDelegateProtocol.swift @@ -18,39 +18,16 @@ public protocol MoleculeDelegateProtocol { func moleculeLayoutUpdated(_ molecule: UIView & MVMCoreUIMoleculeViewProtocol) //optional /// Asks the delegate to add or remove molecules. - //optional - func addMolecules(_ molecules: [[AnyHashable : Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) - func addMolecules(_ molecules: [[AnyHashable : Any]], indexPath: IndexPath, animation: UITableView.RowAnimation) - - func removeMolecules(_ molecules: [[AnyHashable : Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) - - //optional - func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) - func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) + func getIndexPath(for molecule: ListItemModelProtocol & MoleculeModelProtocol) -> IndexPath? + func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], indexPath: IndexPath, animation: UITableView.RowAnimation) + func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], animation: UITableView.RowAnimation) } extension MoleculeDelegateProtocol { - public func moleculeLayoutUpdated(_ molecule: UIView & MVMCoreUIMoleculeViewProtocol) { - // Do Nothing - } - public func addMolecules(_ molecules: [[AnyHashable : Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) { - // Do nothing - } + public func moleculeLayoutUpdated(_ molecule: UIView & MVMCoreUIMoleculeViewProtocol) {} - public func addMolecules(_ molecules: [[AnyHashable : Any]], indexPath: IndexPath, animation: UITableView.RowAnimation) { - // Do nothing - } - - public func removeMolecules(_ molecules: [[AnyHashable : Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) { - // Do nothing - } - - public func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) { - // Do nothing - } - - public func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) { - // Do nothing - } + public func getIndexPath(for molecule: ListItemModelProtocol & MoleculeModelProtocol) -> IndexPath? { return nil } + public func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], indexPath: IndexPath, animation: UITableView.RowAnimation) {} + public func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], animation: UITableView.RowAnimation) {} } diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index 8871db4d..ca56b4af 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -158,77 +158,18 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol } } - open override func addMolecules(_ molecules: [[AnyHashable: Any]], indexPath: IndexPath, animation: UITableView.RowAnimation) { - - var tmpMolecules = [ListItemModelProtocol & MoleculeModelProtocol]() - - molecules.forEach { molecule in - if let data = try? JSONSerialization.data(withJSONObject: molecule), let listItemModel = try? JSONDecoder().decode(MoleculeListItemModel.self, from: data) { - tmpMolecules.append(listItemModel) - } - } - - DispatchQueue.main.async { - var indexPaths: [IndexPath] = [] - - for molecule in tmpMolecules { - if let info = self.getMoleculeInfo(with: molecule) { - self.tableView?.register(info.class, forCellReuseIdentifier: info.identifier) - let index = indexPath.row + 1 + indexPaths.count - self.moleculesInfo?.insert(info, at: index) - indexPaths.append(IndexPath(row: index, section: 0)) - } - } - - self.tableView?.insertRows(at: indexPaths, with: animation) - self.updateViewConstraints() - self.view.layoutIfNeeded() - } + open override func getIndexPath(for molecule: ListItemModelProtocol & MoleculeModelProtocol) -> IndexPath? { + guard let index = moleculesInfo?.firstIndex(where: { (moleculeInfo) -> Bool in + //TODO: cehck for molecule protocola eqality + let json = moleculeInfo.molecule.toJSON() + return json == molecule.toJSON() + }) else { return nil } + return IndexPath(row: index, section: 0) } - open override func addMolecules(_ molecules: [[AnyHashable: Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) { - - DispatchQueue.main.async { [weak self] in - guard let indexPath = self?.tableView?.indexPath(for: sender) else { return } - DispatchQueue.global().async { - self?.addMolecules(molecules, indexPath: indexPath, animation: animation) - } - } - } - - open override func removeMolecules(_ molecules: [[AnyHashable: Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) { - - var tmpMolecules = [ListItemModelProtocol & MoleculeModelProtocol]() - - molecules.forEach { molecule in - if let data = try? JSONSerialization.data(withJSONObject: molecule), - let listItemModel = try? JSONDecoder().decode(MoleculeListItemModel.self, from: data) { - tmpMolecules.append(listItemModel) - } - } - - var indexPaths: [IndexPath] = [] - - //TODO: cehck for molecule protocola eqality - - for molecule in tmpMolecules { - if let removeIndex = moleculesInfo?.firstIndex(where: { molecule.toJSON() == $0.molecule.toJSON() }) { - - moleculesInfo?.remove(at: removeIndex) - indexPaths.append(IndexPath(row: removeIndex + indexPaths.count, section: 0)) - } - } - - tableView?.deleteRows(at: indexPaths, with: animation) - updateViewConstraints() - view.layoutIfNeeded() - } - - open override func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) { - + open override func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], indexPath: IndexPath, animation: UITableView.RowAnimation) { // This dispatch is needed to fix a race condition that can occur if this function is called during the table setup. DispatchQueue.main.async { - guard let indexPath = self.tableView?.indexPath(for: sender) else { return } var indexPaths: [IndexPath] = [] for molecule in molecules { @@ -246,8 +187,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol } } - open override func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) { - + open override func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], animation: UITableView.RowAnimation) { var indexPaths: [IndexPath] = [] //TODO: cehck for molecule protocola eqality From 87fb08fb723f92620abfa4b017bd4e4d5bb22ff2 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Mon, 16 Mar 2020 09:15:49 -0400 Subject: [PATCH 04/17] Navigation model --- MVMCoreUI.xcodeproj/project.pbxproj | 4 + .../BaseControllers/ViewController.swift | 86 ++++++-------- .../FormUIHelpers/New/FormProtocol.swift | 3 +- .../TemplateModelProtocol.swift | 2 +- .../NavigationItemModelProtocol.swift | 108 +++++++++++++++++- .../Templates/MoleculeListTemplate.swift | 3 +- .../Templates/MoleculeStackTemplate.swift | 3 +- .../Templates/StackPageTemplateModel.swift | 32 ++---- MVMCoreUI/Templates/TemplateModel.swift | 50 ++++++++ MVMCoreUI/Templates/TemplateProtocol.swift | 8 +- MVMCoreUI/Templates/ThreeLayerTemplate.swift | 3 +- 11 files changed, 212 insertions(+), 90 deletions(-) create mode 100644 MVMCoreUI/Templates/TemplateModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 2f9e8526..5b09bfb8 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -196,6 +196,7 @@ D22D1F47220496A30077CEC0 /* MVMCoreUISwitch.m in Sources */ = {isa = PBXBuildFile; fileRef = D22D1F45220496A30077CEC0 /* MVMCoreUISwitch.m */; }; D22D1F562204CE5D0077CEC0 /* MVMCoreUIStackableViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = D22D1F542204CE5D0077CEC0 /* MVMCoreUIStackableViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; D22D1F572204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D22D1F552204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m */; }; + D22D8393241C27B100D3DF69 /* TemplateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22D8392241C27B100D3DF69 /* TemplateModel.swift */; }; D243859923A16B1800332775 /* Container.swift in Sources */ = {isa = PBXBuildFile; fileRef = D243859823A16B1800332775 /* Container.swift */; }; D256E9932412880000360572 /* Header.swift in Sources */ = {isa = PBXBuildFile; fileRef = D256E9922412880000360572 /* Header.swift */; }; D260105323CEA61600764D80 /* ToggleModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D260105223CEA61600764D80 /* ToggleModel.swift */; }; @@ -563,6 +564,7 @@ D22D1F45220496A30077CEC0 /* MVMCoreUISwitch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUISwitch.m; sourceTree = ""; }; D22D1F542204CE5D0077CEC0 /* MVMCoreUIStackableViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIStackableViewController.h; sourceTree = ""; }; D22D1F552204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIStackableViewController.m; sourceTree = ""; }; + D22D8392241C27B100D3DF69 /* TemplateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateModel.swift; sourceTree = ""; }; D243859823A16B1800332775 /* Container.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Container.swift; sourceTree = ""; }; D256E9922412880000360572 /* Header.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Header.swift; sourceTree = ""; }; D260105223CEA61600764D80 /* ToggleModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToggleModel.swift; sourceTree = ""; }; @@ -1237,6 +1239,7 @@ isa = PBXGroup; children = ( 012A88AC238C418100FE3DA1 /* TemplateProtocol.swift */, + D22D8392241C27B100D3DF69 /* TemplateModel.swift */, 014AA72823C5059B006F3E93 /* StackPageTemplateModel.swift */, D2A5146022121FBF00345BFB /* MoleculeStackTemplate.swift */, 942C378D2412F5B60066E45E /* ModalMoleculeStackTemplate.swift */, @@ -2033,6 +2036,7 @@ D29DF26C21E6AA0B003B2FB9 /* FLAnimatedImage.m in Sources */, D28A839123CD4FD400DFE4FC /* CornerLabelsModel.swift in Sources */, 012A88F123985E0100FE3DA1 /* Color.swift in Sources */, + D22D8393241C27B100D3DF69 /* TemplateModel.swift in Sources */, 012A889C23889E8400FE3DA1 /* TemplateModelProtocol.swift in Sources */, D29770FC21F7C77400B2F0D0 /* MVMCoreUITextFieldView.m in Sources */, 52267A0723FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift in Sources */, diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index 7aca8f01..080c48c2 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -32,26 +32,6 @@ open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMC private var previousScreenSize = CGSize.zero public var selectedField: UIView? - - public var masterShouldBeAccessible: Bool = false { - didSet { - if let manager = manager as? MFViewController { - manager.masterShouldBeAccessible = masterShouldBeAccessible - } else if MVMCoreUISplitViewController.main()?.getCurrentVisibleController() == self { - MVMCoreUISplitViewController.main()?.setLeftPanelIsAccessible(masterShouldBeAccessible, for: self) - } - } - } - - public var supportShouldBeAccessible: Bool = false { - didSet { - if let manager = manager as? MFViewController { - manager.supportShouldBeAccessible = supportShouldBeAccessible - } else if MVMCoreUISplitViewController.main()?.getCurrentVisibleController() == self { - MVMCoreUISplitViewController.main()?.setRightPanelIsAccessible(supportShouldBeAccessible, for: self) - } - } - } /// Checks if the screen width has changed open func screenSizeChanged() -> Bool { @@ -143,6 +123,24 @@ open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMC } open func parsePageJSON() throws { + if pageModel?.navigationItem == nil { + let navigationModel = NavigationItemModel() + if navigationModel.title == nil { + navigationModel.title = pageModel?.screenHeading + } + if navigationModel.showLeftPanelButton == nil { + navigationModel.showLeftPanelButton = isMasterInitiallyAccessible() + } + if navigationModel.showRightPanelButton == nil { + navigationModel.showRightPanelButton = isSupportInitiallyAccessible() + } + pageModel?.navigationItem = navigationModel + } + if self.formValidator == nil, + let model = pageModel as? FormHolderModelProtocol { + let rules = model.formRules + self.formValidator = FormValidator(rules) + } } open class func verifyRequiredModulesLoaded(for loadObject: MVMCoreLoadObject?, error: inout MVMCoreErrorObject?) -> Bool { @@ -175,37 +173,35 @@ open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMC /// Processes any new data. Called after the page is loaded the first time and on response updates for this page, open func handleNewData() { - // TODO atomize the navigation item - set(navigationController: navigationController) formValidator?.validate() } // MARK: - Navigation Item (Move to model base) open func set(navigationController: UINavigationController?) { - navigationItem.title = pageModel?.screenHeading - navigationItem.accessibilityLabel = pageModel?.screenHeading - guard let navigationController = navigationController else { + guard let navigationItemModel = pageModel?.navigationItem, + let navigationController = navigationController else { MVMCoreUISession.sharedGlobal()?.splitViewController?.parent?.setNeedsStatusBarAppearanceUpdate() return } - navigationController.setNavigationBarHidden(isNavigationBarHidden(), animated: true) - UIColor.setBackgroundColor(forNavigationBar: navigationBarColor(), navigationBar: navigationController.navigationBar, transparent: navigationBarTransparent()) + navigationItem.title = navigationItemModel.title + navigationItem.accessibilityLabel = navigationItemModel.title - let tint = navigationBarTintColor() ?? .black + navigationController.setNavigationBarHidden(navigationItemModel.hidden, animated: true) + UIColor.setBackgroundColor(forNavigationBar: navigationItemModel.backgroundColor?.uiColor ?? .white, navigationBar: navigationController.navigationBar, transparent: navigationItemModel.transparent) + + let tint = navigationItemModel.tintColor.uiColor navigationController.navigationBar.tintColor = tint // Have the navigation title match the tint color - navigationController.navigationBar.titleTextAttributes?.updateValue(navigationBarTintColor, forKey: .foregroundColor) + navigationController.navigationBar.titleTextAttributes?.updateValue(tint, forKey: .foregroundColor) - if navigationController == MVMCoreUISplitViewController.main()?.navigationController { - // Update icons if main navigation controller. + // Update icons if main navigation controller. + if navigationController == MVMCoreUISplitViewController.main()?.navigationController, + MVMCoreUISplitViewController.main()?.getCurrentVisibleController() == self { MVMCoreUISession.sharedGlobal()?.splitViewController?.setupPanels() - let master = masterShouldBeAccessible - masterShouldBeAccessible = master - let support = supportShouldBeAccessible - supportShouldBeAccessible = support - - showBottomProgressBar() + MVMCoreUISplitViewController.main()?.setLeftPanelIsAccessible(navigationItemModel.showLeftPanelButton ?? false, for: self) + MVMCoreUISplitViewController.main()?.setRightPanelIsAccessible(navigationItemModel.showRightPanelButton ?? false, for: self) + showBottomProgressBar() MVMCoreUISession.sharedGlobal()?.splitViewController?.setNavigationIconColor(tint) // Update separator. @@ -213,22 +209,6 @@ open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMC } } - open func navigationBarColor() -> UIColor { - return .white - } - - open func isNavigationBarHidden() -> Bool { - return false - } - - open func navigationBarTransparent() -> Bool { - return false - } - - open func navigationBarTintColor() -> UIColor? { - return nil - } - open func isMasterInitiallyAccessible() -> Bool { if loadObject?.pageJSON?.boolForKey(KeyHideMainMenu) ?? false { return false diff --git a/MVMCoreUI/FormUIHelpers/New/FormProtocol.swift b/MVMCoreUI/FormUIHelpers/New/FormProtocol.swift index bef7f547..1e096372 100644 --- a/MVMCoreUI/FormUIHelpers/New/FormProtocol.swift +++ b/MVMCoreUI/FormUIHelpers/New/FormProtocol.swift @@ -9,7 +9,6 @@ import Foundation //Protocol for Validation -public protocol FormProtocol: class { +public protocol FormHolderModelProtocol: class { var formRules: [FormGroupRule]? { get set } - var formValidator: FormValidator? { get set } } diff --git a/MVMCoreUI/Models/ModelProtocols/TemplateModelProtocol.swift b/MVMCoreUI/Models/ModelProtocols/TemplateModelProtocol.swift index a981ec64..646123e1 100644 --- a/MVMCoreUI/Models/ModelProtocols/TemplateModelProtocol.swift +++ b/MVMCoreUI/Models/ModelProtocols/TemplateModelProtocol.swift @@ -9,7 +9,7 @@ import Foundation -public protocol TemplateModelProtocol: PageModelProtocol, ModelProtocol, FormProtocol { +public protocol TemplateModelProtocol: PageModelProtocol, ModelProtocol, FormHolderModelProtocol { var template: String { get } } diff --git a/MVMCoreUI/Molecules/NavigationItemModelProtocol.swift b/MVMCoreUI/Molecules/NavigationItemModelProtocol.swift index acddb931..24b375fe 100644 --- a/MVMCoreUI/Molecules/NavigationItemModelProtocol.swift +++ b/MVMCoreUI/Molecules/NavigationItemModelProtocol.swift @@ -8,10 +8,112 @@ import Foundation -public protocol NavigationItemModelProtocol: ModelProtocol { - +public protocol NavigationItemModelProtocol: MoleculeModelProtocol { + var title: String? { get set } + var titleView: MoleculeModelProtocol? { get set } + var hidden: Bool { get set } + var backgroundColor: Color? { get set } + var transparent: Bool { get set } + var tintColor: Color { get set } + var systemBackButton: Bool? { get set } + var showLeftPanelButton: Bool? { get set } + var showRightPanelButton: Bool? { get set } + var additionalLeftItems: [NavigationItemButtonModel]? { get set } + var additionalRightItems: [NavigationItemButtonModel]? { get set } } -public protocol NavigationItemButtonModelProtocol { +public class NavigationItemButtonModel: Codable { + var imageName: String + var action: ActionModelProtocol + public init(with imageName: String, action: ActionModelProtocol) { + self.imageName = imageName + self.action = action + } + + private enum CodingKeys: String, CodingKey { + case imageName + case action + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + imageName = try typeContainer.decode(String.self, forKey: .imageName) + action = try typeContainer.decodeModel(codingKey: .action) + } + + open func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(imageName, forKey: .imageName) + try container.encodeModel(action, forKey: .action) + } +} + +public class NavigationItemModel: NavigationItemModelProtocol { + public class var identifier: String { + return "navigationItem" + } + + public var title: String? + public var titleView: MoleculeModelProtocol? + public var hidden: Bool + public var backgroundColor: Color? + public var transparent: Bool + public var tintColor: Color + public var systemBackButton: Bool? + public var showLeftPanelButton: Bool? + public var showRightPanelButton: Bool? + public var additionalLeftItems: [NavigationItemButtonModel]? + public var additionalRightItems: [NavigationItemButtonModel]? + + init() { + hidden = false + transparent = false + backgroundColor = Color(uiColor: .white) + tintColor = Color(uiColor: .black) + } + + private enum CodingKeys: String, CodingKey { + case title + case titleView + case hidden + case backgroundColor + case transparent + case tintColor + case systemBackButton + case showLeftPanelButton + case showRightPanelButton + case additionalLeftItems + case additionalRightItems + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + title = try typeContainer.decodeIfPresent(String.self, forKey: .title) + titleView = try typeContainer.decodeModelIfPresent(codingKey: .titleView) + hidden = try typeContainer.decodeIfPresent(Bool.self, forKey: .hidden) ?? false + backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) ?? Color(uiColor: .white) + transparent = try typeContainer.decodeIfPresent(Bool.self, forKey: .transparent) ?? false + tintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .tintColor) ?? Color(uiColor: .black) + systemBackButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .systemBackButton) ?? false + showLeftPanelButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .showLeftPanelButton) + showRightPanelButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .showRightPanelButton) + additionalLeftItems = try typeContainer.decodeIfPresent([NavigationItemButtonModel].self, forKey: .additionalLeftItems) + additionalRightItems = try typeContainer.decodeIfPresent([NavigationItemButtonModel].self, forKey: .additionalRightItems) + } + + open func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encodeIfPresent(title, forKey: .title) + try container.encodeModelIfPresent(titleView, forKey: .titleView) + try container.encode(hidden, forKey: .hidden) + try container.encode(backgroundColor, forKey: .backgroundColor) + try container.encode(transparent, forKey: .transparent) + try container.encode(tintColor, forKey: .tintColor) + try container.encodeIfPresent(systemBackButton, forKey: .systemBackButton) + try container.encode(showLeftPanelButton, forKey: .showLeftPanelButton) + try container.encode(showRightPanelButton, forKey: .showRightPanelButton) + try container.encodeIfPresent(additionalLeftItems, forKey: .additionalLeftItems) + try container.encodeIfPresent(additionalRightItems, forKey: .additionalRightItems) + } } diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index ca56b4af..8cff8cd8 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -22,7 +22,8 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol // MARK: - Computed Properties //-------------------------------------------------- open override func parsePageJSON() throws { - try parseTemplateJSON() + try parseTemplate(json: loadObject?.pageJSON) + try super.parsePageJSON() } open override var loadObject: MVMCoreLoadObject? { diff --git a/MVMCoreUI/Templates/MoleculeStackTemplate.swift b/MVMCoreUI/Templates/MoleculeStackTemplate.swift index f68cfa1a..c8d807cc 100644 --- a/MVMCoreUI/Templates/MoleculeStackTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeStackTemplate.swift @@ -13,7 +13,8 @@ open class MoleculeStackTemplate: ThreeLayerViewController, TemplateProtocol { public var templateModel: StackPageTemplateModel? open override func parsePageJSON() throws { - try parseTemplateJSON() + try parseTemplate(json: loadObject?.pageJSON) + try super.parsePageJSON() } open override var loadObject: MVMCoreLoadObject? { diff --git a/MVMCoreUI/Templates/StackPageTemplateModel.swift b/MVMCoreUI/Templates/StackPageTemplateModel.swift index 28600453..2b683d98 100644 --- a/MVMCoreUI/Templates/StackPageTemplateModel.swift +++ b/MVMCoreUI/Templates/StackPageTemplateModel.swift @@ -9,55 +9,39 @@ import Foundation -@objcMembers public class StackPageTemplateModel: TemplateModelProtocol { - public var formRules: [FormGroupRule]? - public var formValidator: FormValidator? - - public static var identifier: String = "stack" - - public var pageType: String - public var screenHeading: String? - public var isAtomicTabs: Bool? - public var navigationItem: NavigationItemModelProtocol? +@objcMembers public class StackPageTemplateModel: TemplateModel { + public override class var identifier: String { + return "stack" + } public var header: MoleculeModelProtocol? public var moleculeStack: MoleculeStackModel public var footer: MoleculeModelProtocol? public init(pageType: String, moleculeStack: MoleculeStackModel) { - self.pageType = pageType self.moleculeStack = moleculeStack + super.init(pageType: pageType) } private enum CodingKeys: String, CodingKey { - case pageType - case screenHeading case header case footer case stack - case isAtomicTabs - case formRules } required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - pageType = try typeContainer.decode(String.self, forKey: .pageType) moleculeStack = try typeContainer.decode(MoleculeStackModel.self, forKey: .stack) - screenHeading = try typeContainer.decodeIfPresent(String.self, forKey: .screenHeading) - isAtomicTabs = try typeContainer.decodeIfPresent(Bool.self, forKey: .isAtomicTabs) header = try typeContainer.decodeModelIfPresent(codingKey: .header) footer = try typeContainer.decodeModelIfPresent(codingKey: .footer) - formRules = try typeContainer.decodeIfPresent([FormGroupRule].self, forKey: .formRules) + try super.init(from: decoder) } - public func encode(to encoder: Encoder) throws { + public override func encode(to encoder: Encoder) throws { + try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(pageType, forKey: .pageType) try container.encode(moleculeStack, forKey: .stack) - try container.encodeIfPresent(screenHeading, forKey: .screenHeading) - try container.encodeIfPresent(isAtomicTabs, forKey: .isAtomicTabs) try container.encodeModelIfPresent(header, forKey: .header) try container.encodeModelIfPresent(footer, forKey: .footer) - try container.encodeIfPresent(formRules, forKey: .formRules) } } diff --git a/MVMCoreUI/Templates/TemplateModel.swift b/MVMCoreUI/Templates/TemplateModel.swift new file mode 100644 index 00000000..850ba80b --- /dev/null +++ b/MVMCoreUI/Templates/TemplateModel.swift @@ -0,0 +1,50 @@ +// +// TemplateModel.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 3/13/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers public class TemplateModel: TemplateModelProtocol { + public class var identifier: String { + return "" + } + public var pageType: String + public var screenHeading: String? + public var isAtomicTabs: Bool? + public var navigationItem: NavigationItemModelProtocol? + public var formRules: [FormGroupRule]? + + public init(pageType: String) { + self.pageType = pageType + } + + private enum CodingKeys: String, CodingKey { + case pageType + case screenHeading + case isAtomicTabs + case formRules + case navigationItem + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + pageType = try typeContainer.decode(String.self, forKey: .pageType) + screenHeading = try typeContainer.decodeIfPresent(String.self, forKey: .screenHeading) + isAtomicTabs = try typeContainer.decodeIfPresent(Bool.self, forKey: .isAtomicTabs) + formRules = try typeContainer.decodeIfPresent([FormGroupRule].self, forKey: .formRules) + navigationItem = try typeContainer.decodeModelIfPresent(codingKey: .navigationItem) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(pageType, forKey: .pageType) + try container.encodeIfPresent(screenHeading, forKey: .screenHeading) + try container.encodeIfPresent(isAtomicTabs, forKey: .isAtomicTabs) + try container.encodeIfPresent(formRules, forKey: .formRules) + try container.encodeModelIfPresent(navigationItem, forKey: .navigationItem) + } +} diff --git a/MVMCoreUI/Templates/TemplateProtocol.swift b/MVMCoreUI/Templates/TemplateProtocol.swift index f4717774..78b304b0 100644 --- a/MVMCoreUI/Templates/TemplateProtocol.swift +++ b/MVMCoreUI/Templates/TemplateProtocol.swift @@ -15,16 +15,16 @@ public protocol TemplateProtocol: FormHolderProtocol { } public extension TemplateProtocol where Self: ViewController { - func parseTemplateJSON() throws { - guard let pageJSON = self.loadObject?.pageJSON else { return } + func parseTemplate(json: [AnyHashable: Any]?) throws { + guard let pageJSON = json else { return } let data = try JSONSerialization.data(withJSONObject: pageJSON) let decoder = JSONDecoder() let templateModel = try decoder.decode(TemplateModel.self, from: data) - + self.templateModel = templateModel + if self.formValidator == nil { let rules = templateModel.formRules self.formValidator = FormValidator(rules) } - self.templateModel = templateModel } } diff --git a/MVMCoreUI/Templates/ThreeLayerTemplate.swift b/MVMCoreUI/Templates/ThreeLayerTemplate.swift index 0f400027..19859667 100644 --- a/MVMCoreUI/Templates/ThreeLayerTemplate.swift +++ b/MVMCoreUI/Templates/ThreeLayerTemplate.swift @@ -15,7 +15,8 @@ import UIKit public var templateModel: ThreeLayerPageTemplateModel? open override func parsePageJSON() throws { - try parseTemplateJSON() + try parseTemplate(json: loadObject?.pageJSON) + try super.parsePageJSON() } override open func viewDidLoad() { From 2c6f9667a50accebbdfa2416921e062cc1f51b90 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Mon, 16 Mar 2020 16:47:39 -0400 Subject: [PATCH 05/17] small changes --- MVMCoreUI.xcodeproj/project.pbxproj | 12 ++++++++---- .../MVMControllerModelProtocol.swift | 13 +++++++++++++ MVMCoreUI/BaseControllers/ViewController.swift | 8 ++++---- ...Protocol.swift => FormHolderModelProtocol.swift} | 6 +++--- .../FormUIHelpers/New/FormHolderProtocol.swift | 3 +-- .../ModelProtocols/TemplateModelProtocol.swift | 2 +- MVMCoreUI/Templates/TemplateModel.swift | 2 +- MVMCoreUI/Templates/TemplateProtocol.swift | 10 +++------- MVMCoreUI/Templates/ThreeLayerTemplate.swift | 3 --- 9 files changed, 34 insertions(+), 25 deletions(-) create mode 100644 MVMCoreUI/BaseControllers/MVMControllerModelProtocol.swift rename MVMCoreUI/FormUIHelpers/New/{FormProtocol.swift => FormHolderModelProtocol.swift} (50%) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 5b09bfb8..da20838e 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -15,7 +15,7 @@ 011B58F223A2AE2C0085F53C /* DropDownListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011B58F123A2AE2C0085F53C /* DropDownListItemModel.swift */; }; 011D958524042432000E3791 /* RulesProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D958424042432000E3791 /* RulesProtocol.swift */; }; 011D958724042492000E3791 /* FormFieldProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D958624042492000E3791 /* FormFieldProtocol.swift */; }; - 011D95892404249B000E3791 /* FormProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D95882404249B000E3791 /* FormProtocol.swift */; }; + 011D95892404249B000E3791 /* FormHolderModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D95882404249B000E3791 /* FormHolderModelProtocol.swift */; }; 011D959B240451E3000E3791 /* RuleRequiredModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D959A240451E3000E3791 /* RuleRequiredModel.swift */; }; 011D959D2404536F000E3791 /* RuleAnyValueChangedModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D959C2404536F000E3791 /* RuleAnyValueChangedModel.swift */; }; 011D959F240453A1000E3791 /* RuleAllValueChangedModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D959E240453A1000E3791 /* RuleAllValueChangedModel.swift */; }; @@ -197,6 +197,7 @@ D22D1F562204CE5D0077CEC0 /* MVMCoreUIStackableViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = D22D1F542204CE5D0077CEC0 /* MVMCoreUIStackableViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; D22D1F572204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D22D1F552204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m */; }; D22D8393241C27B100D3DF69 /* TemplateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22D8392241C27B100D3DF69 /* TemplateModel.swift */; }; + D236E5B7242007C500C38625 /* MVMControllerModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D236E5B6242007C500C38625 /* MVMControllerModelProtocol.swift */; }; D243859923A16B1800332775 /* Container.swift in Sources */ = {isa = PBXBuildFile; fileRef = D243859823A16B1800332775 /* Container.swift */; }; D256E9932412880000360572 /* Header.swift in Sources */ = {isa = PBXBuildFile; fileRef = D256E9922412880000360572 /* Header.swift */; }; D260105323CEA61600764D80 /* ToggleModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D260105223CEA61600764D80 /* ToggleModel.swift */; }; @@ -393,7 +394,7 @@ 011B58F123A2AE2C0085F53C /* DropDownListItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropDownListItemModel.swift; sourceTree = ""; }; 011D958424042432000E3791 /* RulesProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RulesProtocol.swift; sourceTree = ""; }; 011D958624042492000E3791 /* FormFieldProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormFieldProtocol.swift; sourceTree = ""; }; - 011D95882404249B000E3791 /* FormProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormProtocol.swift; sourceTree = ""; }; + 011D95882404249B000E3791 /* FormHolderModelProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormHolderModelProtocol.swift; sourceTree = ""; }; 011D959A240451E3000E3791 /* RuleRequiredModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleRequiredModel.swift; sourceTree = ""; }; 011D959C2404536F000E3791 /* RuleAnyValueChangedModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleAnyValueChangedModel.swift; sourceTree = ""; }; 011D959E240453A1000E3791 /* RuleAllValueChangedModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleAllValueChangedModel.swift; sourceTree = ""; }; @@ -565,6 +566,7 @@ D22D1F542204CE5D0077CEC0 /* MVMCoreUIStackableViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIStackableViewController.h; sourceTree = ""; }; D22D1F552204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIStackableViewController.m; sourceTree = ""; }; D22D8392241C27B100D3DF69 /* TemplateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateModel.swift; sourceTree = ""; }; + D236E5B6242007C500C38625 /* MVMControllerModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMControllerModelProtocol.swift; sourceTree = ""; }; D243859823A16B1800332775 /* Container.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Container.swift; sourceTree = ""; }; D256E9922412880000360572 /* Header.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Header.swift; sourceTree = ""; }; D260105223CEA61600764D80 /* ToggleModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToggleModel.swift; sourceTree = ""; }; @@ -797,7 +799,7 @@ isa = PBXGroup; children = ( 011D958A24042794000E3791 /* Rules */, - 011D95882404249B000E3791 /* FormProtocol.swift */, + 011D95882404249B000E3791 /* FormHolderModelProtocol.swift */, 011D95AC2406BB57000E3791 /* FormHolderProtocol.swift */, 011D95AA2405C553000E3791 /* FormItemProtocol.swift */, 011D958624042492000E3791 /* FormFieldProtocol.swift */, @@ -1306,6 +1308,7 @@ D29DF10F21E67A7D003B2FB9 /* BaseControllers */ = { isa = PBXGroup; children = ( + D236E5B6242007C500C38625 /* MVMControllerModelProtocol.swift */, D29DF2CC21E7C104003B2FB9 /* MFLoadingViewController.h */, D29DF2CD21E7C104003B2FB9 /* MFLoadingViewController.m */, D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */, @@ -1815,6 +1818,7 @@ 01004F3022721C3800991ECC /* RadioButton.swift in Sources */, D268C70E238C22D7007F2C1C /* DropDownFilterTableViewCell.swift in Sources */, 017BEB3C2361EA1D0024EF95 /* MFViewController+Model.swift in Sources */, + D236E5B7242007C500C38625 /* MVMControllerModelProtocol.swift in Sources */, D282AAB4223FDDAE00C46919 /* MFLoadImageView.swift in Sources */, D29DF11721E6805F003B2FB9 /* UIColor+MFConvenience.m in Sources */, D2B18B7F2360913400A9AEDC /* Control.swift in Sources */, @@ -2025,7 +2029,7 @@ 943784F6236B77BB006A1E82 /* GraphViewAnimationHandler.swift in Sources */, 011D95A1240453D0000E3791 /* RuleEqualsModel.swift in Sources */, D29DF2AA21E7B2F9003B2FB9 /* MVMCoreUIConstants.m in Sources */, - 011D95892404249B000E3791 /* FormProtocol.swift in Sources */, + 011D95892404249B000E3791 /* FormHolderModelProtocol.swift in Sources */, 948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */, 013F801923FB4A8E00AD8013 /* UIContentMode+Extension.swift in Sources */, D2A5146122121FBF00345BFB /* MoleculeStackTemplate.swift in Sources */, diff --git a/MVMCoreUI/BaseControllers/MVMControllerModelProtocol.swift b/MVMCoreUI/BaseControllers/MVMControllerModelProtocol.swift new file mode 100644 index 00000000..579a612e --- /dev/null +++ b/MVMCoreUI/BaseControllers/MVMControllerModelProtocol.swift @@ -0,0 +1,13 @@ +// +// MVMControllerModelProtocol.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 3/16/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public protocol MVMControllerModelProtocol: TemplateModelProtocol, FormHolderModelProtocol { + +} diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index 080c48c2..e44ab353 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -11,7 +11,7 @@ import UIKit open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMCoreViewManagerViewControllerProtocol, MoleculeDelegateProtocol, FormHolderProtocol, MVMCoreActionDelegateProtocol, UITextFieldDelegate, UITextViewDelegate { public var pageType: String? public var loadObject: MVMCoreLoadObject? - public var pageModel: PageModelProtocol? + public var pageModel: MVMControllerModelProtocol? /// Set if this page is containted in a manager. public var manager: (UIViewController & MVMCoreViewManagerProtocol)? @@ -123,6 +123,7 @@ open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMC } open func parsePageJSON() throws { + // Convert legacy to navigation model. if pageModel?.navigationItem == nil { let navigationModel = NavigationItemModel() if navigationModel.title == nil { @@ -136,9 +137,8 @@ open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMC } pageModel?.navigationItem = navigationModel } - if self.formValidator == nil, - let model = pageModel as? FormHolderModelProtocol { - let rules = model.formRules + if self.formValidator == nil { + let rules = pageModel?.formRules self.formValidator = FormValidator(rules) } } diff --git a/MVMCoreUI/FormUIHelpers/New/FormProtocol.swift b/MVMCoreUI/FormUIHelpers/New/FormHolderModelProtocol.swift similarity index 50% rename from MVMCoreUI/FormUIHelpers/New/FormProtocol.swift rename to MVMCoreUI/FormUIHelpers/New/FormHolderModelProtocol.swift index 1e096372..a9428a2b 100644 --- a/MVMCoreUI/FormUIHelpers/New/FormProtocol.swift +++ b/MVMCoreUI/FormUIHelpers/New/FormHolderModelProtocol.swift @@ -1,14 +1,14 @@ // -// Validatable.swift +// FormHolderModelProtocol.swift // MVMCoreUI // // Created by Suresh, Kamlesh on 2/5/20. // Copyright © 2020 Verizon Wireless. All rights reserved. // +// A protocol for the model of the delegate object that holds the form validator. The rules are stored in the model. import Foundation -//Protocol for Validation -public protocol FormHolderModelProtocol: class { +public protocol FormHolderModelProtocol { var formRules: [FormGroupRule]? { get set } } diff --git a/MVMCoreUI/FormUIHelpers/New/FormHolderProtocol.swift b/MVMCoreUI/FormUIHelpers/New/FormHolderProtocol.swift index 1e2f5522..26bceac4 100644 --- a/MVMCoreUI/FormUIHelpers/New/FormHolderProtocol.swift +++ b/MVMCoreUI/FormUIHelpers/New/FormHolderProtocol.swift @@ -5,11 +5,10 @@ // Created by Suresh, Kamlesh on 2/26/20. // Copyright © 2020 Verizon Wireless. All rights reserved. // +// A delegate object that holds the form validator. import Foundation - -//Protocol for Validation public protocol FormHolderProtocol: NSObjectProtocol { var formValidator: FormValidator? { get set } } diff --git a/MVMCoreUI/Models/ModelProtocols/TemplateModelProtocol.swift b/MVMCoreUI/Models/ModelProtocols/TemplateModelProtocol.swift index 646123e1..3ed37d6b 100644 --- a/MVMCoreUI/Models/ModelProtocols/TemplateModelProtocol.swift +++ b/MVMCoreUI/Models/ModelProtocols/TemplateModelProtocol.swift @@ -9,7 +9,7 @@ import Foundation -public protocol TemplateModelProtocol: PageModelProtocol, ModelProtocol, FormHolderModelProtocol { +public protocol TemplateModelProtocol: PageModelProtocol, ModelProtocol { var template: String { get } } diff --git a/MVMCoreUI/Templates/TemplateModel.swift b/MVMCoreUI/Templates/TemplateModel.swift index 850ba80b..053d45fc 100644 --- a/MVMCoreUI/Templates/TemplateModel.swift +++ b/MVMCoreUI/Templates/TemplateModel.swift @@ -8,7 +8,7 @@ import Foundation -@objcMembers public class TemplateModel: TemplateModelProtocol { +@objcMembers public class TemplateModel: MVMControllerModelProtocol { public class var identifier: String { return "" } diff --git a/MVMCoreUI/Templates/TemplateProtocol.swift b/MVMCoreUI/Templates/TemplateProtocol.swift index 78b304b0..4d494fe4 100644 --- a/MVMCoreUI/Templates/TemplateProtocol.swift +++ b/MVMCoreUI/Templates/TemplateProtocol.swift @@ -9,22 +9,18 @@ import Foundation -public protocol TemplateProtocol: FormHolderProtocol { +public protocol TemplateProtocol: class { associatedtype TemplateModel: TemplateModelProtocol var templateModel: TemplateModel? { get set } } -public extension TemplateProtocol where Self: ViewController { +public extension TemplateProtocol where Self: ViewController { func parseTemplate(json: [AnyHashable: Any]?) throws { guard let pageJSON = json else { return } let data = try JSONSerialization.data(withJSONObject: pageJSON) let decoder = JSONDecoder() let templateModel = try decoder.decode(TemplateModel.self, from: data) self.templateModel = templateModel - - if self.formValidator == nil { - let rules = templateModel.formRules - self.formValidator = FormValidator(rules) - } + self.pageModel = templateModel as? MVMControllerModelProtocol } } diff --git a/MVMCoreUI/Templates/ThreeLayerTemplate.swift b/MVMCoreUI/Templates/ThreeLayerTemplate.swift index 19859667..ba35c971 100644 --- a/MVMCoreUI/Templates/ThreeLayerTemplate.swift +++ b/MVMCoreUI/Templates/ThreeLayerTemplate.swift @@ -9,9 +9,6 @@ import UIKit @objcMembers open class ThreeLayerTemplate: ThreeLayerViewController, TemplateProtocol { - public func validate() { - - } public var templateModel: ThreeLayerPageTemplateModel? open override func parsePageJSON() throws { From f4f5d8dc84c87e43cf552eafe539e08e6c21b4c7 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Mon, 16 Mar 2020 19:41:50 -0400 Subject: [PATCH 06/17] fixes --- MVMCoreUI/Atoms/Views/MFLoadImageView.swift | 2 +- .../ThreeLayerTableViewController.swift | 2 +- .../BaseControllers/ViewController.swift | 42 +++++++++---------- .../Templates/ListPageTemplateModel.swift | 2 +- .../Templates/MoleculeListTemplate.swift | 2 +- .../StackCenteredPageTemplateModel.swift | 2 +- .../ThreeLayerPageTemplateModel.swift | 2 +- 7 files changed, 27 insertions(+), 27 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/MFLoadImageView.swift b/MVMCoreUI/Atoms/Views/MFLoadImageView.swift index e61a5af3..d8415d2d 100644 --- a/MVMCoreUI/Atoms/Views/MFLoadImageView.swift +++ b/MVMCoreUI/Atoms/Views/MFLoadImageView.swift @@ -181,7 +181,7 @@ import UIKit let widthWillChange = !MVMCoreGetterUtility.cgfequal(widthConstraint?.constant ?? 0, width ?? 0) let heightWillChange = !MVMCoreGetterUtility.cgfequal(heightConstraint?.constant ?? 0, height ?? 0) let sizeWillChange = (width == nil || height == nil) && !(size?.equalTo(imageView.image?.size ?? CGSize.zero) ?? false) - let heightChangeFromSpinner = ((height ?? size?.height) ?? 0) < loadingSpinnerHeightConstraint?.constant ?? CGFloat.leastNormalMagnitude + let heightChangeFromSpinner = (heightConstraint?.isActive ?? false) ? false : ((height ?? size?.height) ?? 0) < loadingSpinnerHeightConstraint?.constant ?? CGFloat.leastNormalMagnitude return widthWillChange || heightWillChange || sizeWillChange || heightChangeFromSpinner } diff --git a/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift b/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift index 2fba0e07..0a7f4e55 100644 --- a/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift +++ b/MVMCoreUI/BaseControllers/ThreeLayerTableViewController.swift @@ -37,10 +37,10 @@ open class ThreeLayerTableViewController: ProgrammaticTableViewController { } open override func handleNewData() { + super.handleNewData() createViewForTableHeader() createViewForTableFooter() tableView?.reloadData() - super.handleNewData() } override open func viewDidLoad() { diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index e44ab353..12169a7c 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -123,24 +123,6 @@ open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMC } open func parsePageJSON() throws { - // Convert legacy to navigation model. - if pageModel?.navigationItem == nil { - let navigationModel = NavigationItemModel() - if navigationModel.title == nil { - navigationModel.title = pageModel?.screenHeading - } - if navigationModel.showLeftPanelButton == nil { - navigationModel.showLeftPanelButton = isMasterInitiallyAccessible() - } - if navigationModel.showRightPanelButton == nil { - navigationModel.showRightPanelButton = isSupportInitiallyAccessible() - } - pageModel?.navigationItem = navigationModel - } - if self.formValidator == nil { - let rules = pageModel?.formRules - self.formValidator = FormValidator(rules) - } } open class func verifyRequiredModulesLoaded(for loadObject: MVMCoreLoadObject?, error: inout MVMCoreErrorObject?) -> Bool { @@ -173,7 +155,24 @@ open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMC /// Processes any new data. Called after the page is loaded the first time and on response updates for this page, open func handleNewData() { - formValidator?.validate() + // Convert legacy to navigation model. + if pageModel?.navigationItem == nil { + let navigationModel = NavigationItemModel() + if navigationModel.title == nil { + navigationModel.title = pageModel?.screenHeading + } + if navigationModel.showLeftPanelButton == nil { + navigationModel.showLeftPanelButton = isMasterInitiallyAccessible() + } + if navigationModel.showRightPanelButton == nil { + navigationModel.showRightPanelButton = isSupportInitiallyAccessible() + } + pageModel?.navigationItem = navigationModel + } + if self.formValidator == nil { + let rules = pageModel?.formRules + self.formValidator = FormValidator(rules) + } } // MARK: - Navigation Item (Move to model base) @@ -257,6 +256,7 @@ open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMC } open func updateViews() { + formValidator?.validate() } override open func viewDidLoad() { @@ -312,7 +312,7 @@ open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMC if manager == nil { MVMCoreUISession.sharedGlobal()?.currentPageType = pageType - MVMCoreUILoggingHandler.shared()?.defaultLogPageState(forController: self) + //MVMCoreUILoggingHandler.shared()?.defaultLogPageState(forController: self) } } @@ -341,7 +341,7 @@ open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMC set(navigationController: manager.navigationController) } MVMCoreUISession.sharedGlobal()?.currentPageType = pageType - MVMCoreUILoggingHandler.shared()?.defaultLogPageState(forController: self) + //MVMCoreUILoggingHandler.shared()?.defaultLogPageState(forController: self) } // MARK: - MVMCoreActionDelegateProtocol diff --git a/MVMCoreUI/Templates/ListPageTemplateModel.swift b/MVMCoreUI/Templates/ListPageTemplateModel.swift index 99e87809..db25742b 100644 --- a/MVMCoreUI/Templates/ListPageTemplateModel.swift +++ b/MVMCoreUI/Templates/ListPageTemplateModel.swift @@ -8,7 +8,7 @@ import Foundation -@objcMembers public class ListPageTemplateModel: TemplateModelProtocol { +@objcMembers public class ListPageTemplateModel: MVMControllerModelProtocol { public var formRules: [FormGroupRule]? public var formValidator: FormValidator? diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index 8cff8cd8..84b88fd4 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -81,9 +81,9 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol } open override func handleNewData() { + super.handleNewData() setup() registerWithTable() - super.handleNewData() } //-------------------------------------------------- diff --git a/MVMCoreUI/Templates/StackCenteredPageTemplateModel.swift b/MVMCoreUI/Templates/StackCenteredPageTemplateModel.swift index f3bde0e7..49fb67c5 100644 --- a/MVMCoreUI/Templates/StackCenteredPageTemplateModel.swift +++ b/MVMCoreUI/Templates/StackCenteredPageTemplateModel.swift @@ -8,7 +8,7 @@ import Foundation -@objcMembers public class StackCenteredPageTemplateModel: TemplateModelProtocol { +@objcMembers public class StackCenteredPageTemplateModel: MVMControllerModelProtocol { public var formRules: [FormGroupRule]? public var formValidator: FormValidator? diff --git a/MVMCoreUI/Templates/ThreeLayerPageTemplateModel.swift b/MVMCoreUI/Templates/ThreeLayerPageTemplateModel.swift index fff9bdb8..b745cb0f 100644 --- a/MVMCoreUI/Templates/ThreeLayerPageTemplateModel.swift +++ b/MVMCoreUI/Templates/ThreeLayerPageTemplateModel.swift @@ -8,7 +8,7 @@ import Foundation -@objcMembers public class ThreeLayerPageTemplateModel: TemplateModelProtocol { +@objcMembers public class ThreeLayerPageTemplateModel: MVMControllerModelProtocol { public var formRules: [FormGroupRule]? public var formValidator: FormValidator? From ddfeb9cd359a11823a921cbb9e9dcad74bd7dc2c Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Tue, 17 Mar 2020 09:35:14 -0400 Subject: [PATCH 07/17] merge --- .../FormUIHelpers/FormHolderModelProtocol.swift | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 MVMCoreUI/FormUIHelpers/FormHolderModelProtocol.swift diff --git a/MVMCoreUI/FormUIHelpers/FormHolderModelProtocol.swift b/MVMCoreUI/FormUIHelpers/FormHolderModelProtocol.swift new file mode 100644 index 00000000..a9428a2b --- /dev/null +++ b/MVMCoreUI/FormUIHelpers/FormHolderModelProtocol.swift @@ -0,0 +1,14 @@ +// +// FormHolderModelProtocol.swift +// MVMCoreUI +// +// Created by Suresh, Kamlesh on 2/5/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// +// A protocol for the model of the delegate object that holds the form validator. The rules are stored in the model. + +import Foundation + +public protocol FormHolderModelProtocol { + var formRules: [FormGroupRule]? { get set } +} From 8243820f854c6d5a44c036d0924ae0a05ccf37bd Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Tue, 17 Mar 2020 13:48:34 -0400 Subject: [PATCH 08/17] track action fixes --- .../BaseControllers/ViewController.swift | 23 ++++++++++++++----- .../Items/DropDownFilterTableViewCell.swift | 4 +--- .../Templates/MoleculeListTemplate.swift | 2 ++ 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index 12169a7c..80662cad 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -8,9 +8,9 @@ import UIKit -open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMCoreViewManagerViewControllerProtocol, MoleculeDelegateProtocol, FormHolderProtocol, MVMCoreActionDelegateProtocol, UITextFieldDelegate, UITextViewDelegate { - public var pageType: String? - public var loadObject: MVMCoreLoadObject? +@objc open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMCoreViewManagerViewControllerProtocol, MoleculeDelegateProtocol, FormHolderProtocol, MVMCoreActionDelegateProtocol, UITextFieldDelegate, UITextViewDelegate { + @objc public var pageType: String? + @objc public var loadObject: MVMCoreLoadObject? public var pageModel: MVMControllerModelProtocol? /// Set if this page is containted in a manager. @@ -208,6 +208,7 @@ open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMC } } + // Eventually will be moved to server open func isMasterInitiallyAccessible() -> Bool { if loadObject?.pageJSON?.boolForKey(KeyHideMainMenu) ?? false { return false @@ -215,6 +216,7 @@ open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMC return MVMCoreUISession.sharedGlobal()?.launchAppLoadedSuccessfully ?? false } + // Eventually will be moved to server open func isSupportInitiallyAccessible() -> Bool { if loadObject?.pageJSON?.boolForKey(KeyHideMainMenu) ?? false { return false @@ -226,6 +228,7 @@ open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMC return loadObject?.pageJSON?.lenientBoolForKey("showRightPanel") ?? false } + // Eventually will be moved to separate button in navigation item model open func isOverridingRightButton() -> Bool { guard let rightPanelLink = loadObject?.pageJSON?.optionalDictionaryForKey("rightPanelButtonLink") else { return false @@ -234,6 +237,7 @@ open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMC return true } + // Eventually will be moved to separate button in navigation item model open func isOverridingLeftButton() -> Bool { guard let leftPanelLink = loadObject?.pageJSON?.optionalDictionaryForKey("leftPanelButtonLink") else { return false @@ -242,6 +246,7 @@ open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMC return true } + // Eventually will be moved to Model open func showBottomProgressBar() { if MVMCoreUISplitViewController.main()?.getCurrentVisibleController() == self, let progressString = loadObject?.pageJSON?.optionalStringForKey(KeyProgressPercent), @@ -265,6 +270,7 @@ open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMC // Do any additional setup after loading the view. MVMCoreLoggingHandler.logDebugMessage(withDelegate: "View Controller Loaded : \(self)") + // We use our own margins. viewRespectsSystemMinimumLayoutMargins = false // Presents from the bottom. @@ -278,7 +284,7 @@ open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMC // Handle data on load handleNewData() - + view.setNeedsLayout() } @@ -312,7 +318,7 @@ open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMC if manager == nil { MVMCoreUISession.sharedGlobal()?.currentPageType = pageType - //MVMCoreUILoggingHandler.shared()?.defaultLogPageState(forController: self) + MVMCoreUILoggingHandler.shared()?.defaultLogPageState(forController: self) } } @@ -340,8 +346,9 @@ open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMC if initialLoadFinished { set(navigationController: manager.navigationController) } + // Janky way to track current page. MVMCoreUISession.sharedGlobal()?.currentPageType = pageType - //MVMCoreUILoggingHandler.shared()?.defaultLogPageState(forController: self) + MVMCoreUILoggingHandler.shared()?.defaultLogPageState(forController: self) } // MARK: - MVMCoreActionDelegateProtocol @@ -351,6 +358,10 @@ open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMC MVMCoreActionHandler.defaultHandleOpenPage(for: requestParameters, additionalData: additionalData, delegateObject: selfDelegateObject) } + open func logAction(withActionInformation actionInformation: [AnyHashable : Any]?, additionalData: [AnyHashable : Any]?) { + MVMCoreUILoggingHandler.shared()?.defaultLogAction(forController: self, actionInformation: actionInformation, additionalData: additionalData) + } + // MARK: - MoleculeDelegateProtocol open func getModuleWithName(_ name: String?) -> [AnyHashable : Any]? { guard let name = name else { return nil } diff --git a/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift b/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift index 41801046..aa581ba1 100644 --- a/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift +++ b/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift @@ -29,9 +29,7 @@ import UIKit guard newValue != oldValue, let self = self, let index = self.dropDown.pickerData.firstIndex(of: newValue), - let dropListItemJSON = (self.listItemModel as? DropDownListItemModel).toJSON(), - let json2d = dropListItemJSON.optionalArrayForKey("molecules") as? [[[AnyHashable: Any]]], - !json2d.isEmpty && !(json2d.first?.isEmpty ?? false) + let model = self.listItemModel as? DropDownListItemModel else { return } if self.previousIndex != NSNotFound { diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index a539240e..bca29172 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -183,6 +183,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol } } + guard indexPaths.count > 0 else { return } self.tableView?.insertRows(at: indexPaths, with: animation) self.updateViewConstraints() self.view.layoutIfNeeded() @@ -200,6 +201,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol } } + guard indexPaths.count > 0 else { return } tableView?.deleteRows(at: indexPaths, with: animation) updateViewConstraints() view.layoutIfNeeded() From 18dcf3072f20c5fb7af4d97cb695c4ea95fece21 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Thu, 19 Mar 2020 16:28:35 -0400 Subject: [PATCH 09/17] required identifiers --- .../Actions/ActionCollapseNotificationModel.swift | 2 +- MVMCoreUI/Actions/ActionOpenPanelModel.swift | 2 +- MVMCoreUI/Actions/ActionTopAlertModel.swift | 2 +- MVMCoreUI/Atoms/TextFields/TextFieldModel.swift | 2 +- MVMCoreUI/Atoms/Views/ImageViewModel.swift | 2 +- MVMCoreUI/Atoms/Views/LeftRightLabelModel.swift | 2 +- MVMCoreUI/BaseControllers/ViewController.swift | 2 +- .../ModelProtocols/MoleculeModelProtocol.swift | 4 ++-- .../Molecules/Doughnut/DoughnutChartModel.swift | 4 ++-- .../ImageHeadlineBodyModel.swift | 2 +- .../Molecules/Items/MoleculeCollectionViewCell.swift | 5 ++--- MVMCoreUI/Molecules/Items/StackItemModel.swift | 2 +- .../LeftRightViews/ActionDetailWithImageModel.swift | 2 +- .../HeadlineBodyLinkToggleModel.swift | 2 +- .../ToggleMolecules/HeadlineBodyToggleModel.swift | 2 +- .../ToggleMolecules/LabelToggleModel.swift | 2 +- MVMCoreUI/Molecules/ScrollerModel.swift | 2 +- .../EyebrowHeadlineBodyLinkModel.swift | 2 +- .../HeadlineBodyButtonModel.swift | 2 +- .../HeadlineBodyLinkModel.swift | 2 +- .../VerticalCombinationViews/HeadlineBodyModel.swift | 2 +- .../StringAndMoleculeStack.swift | 3 +-- MVMCoreUI/Organisms/Carousel.swift | 5 ++--- MVMCoreUI/Organisms/Stack.swift | 12 +++++------- ...MCoreUIMoleculeMappingObject+ModelExtension.swift | 8 ++------ MVMCoreUI/Templates/ModalMoleculeListTemplate.swift | 4 ++-- MVMCoreUI/Templates/MoleculeListTemplate.swift | 6 ++---- 27 files changed, 38 insertions(+), 49 deletions(-) diff --git a/MVMCoreUI/Actions/ActionCollapseNotificationModel.swift b/MVMCoreUI/Actions/ActionCollapseNotificationModel.swift index 4dad156b..9a6e6793 100644 --- a/MVMCoreUI/Actions/ActionCollapseNotificationModel.swift +++ b/MVMCoreUI/Actions/ActionCollapseNotificationModel.swift @@ -10,7 +10,7 @@ import UIKit @objcMembers public class ActionCollapseNotificationModel: ActionModelProtocol { public static var identifier: String = "collapseNotification" - public var actionType: String? + public var actionType: String public var extraParameters: JSONValueDictionary? public var analyticsData: JSONValueDictionary? public var title: String? diff --git a/MVMCoreUI/Actions/ActionOpenPanelModel.swift b/MVMCoreUI/Actions/ActionOpenPanelModel.swift index ce3977d8..55fd272a 100644 --- a/MVMCoreUI/Actions/ActionOpenPanelModel.swift +++ b/MVMCoreUI/Actions/ActionOpenPanelModel.swift @@ -18,7 +18,7 @@ public class ActionOpenPanelModel: ActionModelProtocol { } public static var identifier: String = "openPanel" - public var actionType: String? + public var actionType: String = ActionOpenPanelModel.identifier public var panel: Panel public var extraParameters: JSONValueDictionary? public var analyticsData: JSONValueDictionary? diff --git a/MVMCoreUI/Actions/ActionTopAlertModel.swift b/MVMCoreUI/Actions/ActionTopAlertModel.swift index 6da64912..628633c2 100644 --- a/MVMCoreUI/Actions/ActionTopAlertModel.swift +++ b/MVMCoreUI/Actions/ActionTopAlertModel.swift @@ -10,7 +10,7 @@ import Foundation @objcMembers public class ActionTopAlertModel: ActionModelProtocol { public static var identifier: String = "topAlert" - public var actionType: String? + public var actionType: String = ActionTopAlertModel.identifier public var pageType: String public var extraParameters: JSONValueDictionary? public var analyticsData: JSONValueDictionary? diff --git a/MVMCoreUI/Atoms/TextFields/TextFieldModel.swift b/MVMCoreUI/Atoms/TextFields/TextFieldModel.swift index d901d13a..4d6f1fd0 100644 --- a/MVMCoreUI/Atoms/TextFields/TextFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/TextFieldModel.swift @@ -12,7 +12,7 @@ import UIKit public static var identifier: String = "textField" public var backgroundColor: Color? - public var moleculeName: String? = TextFieldModel.identifier + public var moleculeName: String = TextFieldModel.identifier public var editable: Bool? public var disabled: Bool? public var errorMsg: String? diff --git a/MVMCoreUI/Atoms/Views/ImageViewModel.swift b/MVMCoreUI/Atoms/Views/ImageViewModel.swift index 0f585119..d5ba0a14 100644 --- a/MVMCoreUI/Atoms/Views/ImageViewModel.swift +++ b/MVMCoreUI/Atoms/Views/ImageViewModel.swift @@ -11,7 +11,7 @@ import Foundation @objcMembers public class ImageViewModel: MoleculeModelProtocol { public static var identifier: String = "image" public var backgroundColor: Color? - public var moleculeName: String? = ImageViewModel.identifier + public var moleculeName: String = ImageViewModel.identifier public var image: String public var accessibilityText: String? public var fallbackImage: String? diff --git a/MVMCoreUI/Atoms/Views/LeftRightLabelModel.swift b/MVMCoreUI/Atoms/Views/LeftRightLabelModel.swift index 44564c93..07c534f8 100644 --- a/MVMCoreUI/Atoms/Views/LeftRightLabelModel.swift +++ b/MVMCoreUI/Atoms/Views/LeftRightLabelModel.swift @@ -14,7 +14,7 @@ import UIKit //-------------------------------------------------- public static var identifier: String = "leftRightLabelView" - public var moleculeName: String? = LeftRightLabelModel.identifier + public var moleculeName: String = LeftRightLabelModel.identifier public var backgroundColor: Color? public var leftText: LabelModel public var rightText: LabelModel? diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index 80662cad..333df798 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -186,7 +186,7 @@ import UIKit navigationItem.accessibilityLabel = navigationItemModel.title navigationController.setNavigationBarHidden(navigationItemModel.hidden, animated: true) - UIColor.setBackgroundColor(forNavigationBar: navigationItemModel.backgroundColor?.uiColor ?? .white, navigationBar: navigationController.navigationBar, transparent: navigationItemModel.transparent) + UIColor.setBackgroundColor(navigationItemModel.backgroundColor?.uiColor ?? .white, for: navigationController.navigationBar, isTransparent: navigationItemModel.transparent) let tint = navigationItemModel.tintColor.uiColor navigationController.navigationBar.tintColor = tint diff --git a/MVMCoreUI/Models/ModelProtocols/MoleculeModelProtocol.swift b/MVMCoreUI/Models/ModelProtocols/MoleculeModelProtocol.swift index 2928cf2a..913c3bd0 100644 --- a/MVMCoreUI/Models/ModelProtocols/MoleculeModelProtocol.swift +++ b/MVMCoreUI/Models/ModelProtocols/MoleculeModelProtocol.swift @@ -2,13 +2,13 @@ import Foundation public protocol MoleculeModelProtocol: ModelProtocol { - var moleculeName: String? { get } + var moleculeName: String { get } var backgroundColor: Color? { get set } } public extension MoleculeModelProtocol { - var moleculeName: String? { + var moleculeName: String { get { return Self.identifier } } diff --git a/MVMCoreUI/Molecules/Doughnut/DoughnutChartModel.swift b/MVMCoreUI/Molecules/Doughnut/DoughnutChartModel.swift index 1e5c7dce..ff9b1bf6 100644 --- a/MVMCoreUI/Molecules/Doughnut/DoughnutChartModel.swift +++ b/MVMCoreUI/Molecules/Doughnut/DoughnutChartModel.swift @@ -11,7 +11,7 @@ import Foundation @objcMembers public class DoughnutChartModel: MoleculeModelProtocol { public var backgroundColor: Color? public static var identifier: String = "doughnutChart" - public var moleculeName: String? = DoughnutChartModel.identifier + public var moleculeName: String = DoughnutChartModel.identifier public var title: LabelModel? public var subtitle: LabelModel? public var sections: [DoughnutChartItemModel] @@ -25,7 +25,7 @@ import Foundation @objcMembers public class DoughnutChartItemModel: MoleculeModelProtocol { public var backgroundColor: Color? public static var identifier: String = "doughnutChartItem" - public var moleculeName: String? = DoughnutChartItemModel.identifier + public var moleculeName: String = DoughnutChartItemModel.identifier public var label: LabelModel @Percent public var percent: CGFloat public var color: Color diff --git a/MVMCoreUI/Molecules/HorizontalCombinationViews/ImageHeadlineBodyModel.swift b/MVMCoreUI/Molecules/HorizontalCombinationViews/ImageHeadlineBodyModel.swift index f34e7b94..4ac675c5 100644 --- a/MVMCoreUI/Molecules/HorizontalCombinationViews/ImageHeadlineBodyModel.swift +++ b/MVMCoreUI/Molecules/HorizontalCombinationViews/ImageHeadlineBodyModel.swift @@ -10,7 +10,7 @@ import Foundation public struct ImageHeadlineBodyModel: MoleculeModelProtocol { public static var identifier: String = "imageHeadlineBody" - public var moleculeName: String? = ImageHeadlineBodyModel.identifier + public var moleculeName: String = ImageHeadlineBodyModel.identifier public var backgroundColor: Color? public var image: ImageViewModel public var headlineBody: HeadlineBodyModel diff --git a/MVMCoreUI/Molecules/Items/MoleculeCollectionViewCell.swift b/MVMCoreUI/Molecules/Items/MoleculeCollectionViewCell.swift index 9c63ba64..cf1779be 100644 --- a/MVMCoreUI/Molecules/Items/MoleculeCollectionViewCell.swift +++ b/MVMCoreUI/Molecules/Items/MoleculeCollectionViewCell.swift @@ -116,11 +116,10 @@ open class MoleculeCollectionViewCell: UICollectionViewCell, MVMCoreUIMoleculeVi public class func nameForReuse(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? { guard let molecule = (model as? CarouselItemModel)?.molecule, - let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(molecule) as? ModelMoleculeViewProtocol.Type, - let name = moleculeClass.nameForReuse(with: molecule, delegateObject) ?? molecule.moleculeName else { + let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(molecule) as? ModelMoleculeViewProtocol.Type else { return nil } - return name + return moleculeClass.nameForReuse(with: molecule, delegateObject) ?? molecule.moleculeName } public func updateView(_ size: CGFloat) { diff --git a/MVMCoreUI/Molecules/Items/StackItemModel.swift b/MVMCoreUI/Molecules/Items/StackItemModel.swift index 795b2983..12254fb5 100644 --- a/MVMCoreUI/Molecules/Items/StackItemModel.swift +++ b/MVMCoreUI/Molecules/Items/StackItemModel.swift @@ -10,7 +10,7 @@ import Foundation @objcMembers public class StackItemModel: ContainerModel, StackItemModelProtocol, MoleculeModelProtocol { public static var identifier: String = "simpleStackItem" - public var moleculeName: String? = StackItemModel.identifier + public var moleculeName: String = StackItemModel.identifier public var backgroundColor: Color? public var spacing: CGFloat? public var percent: Int? diff --git a/MVMCoreUI/Molecules/LeftRightViews/ActionDetailWithImageModel.swift b/MVMCoreUI/Molecules/LeftRightViews/ActionDetailWithImageModel.swift index 9dbf53c0..d617f053 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/ActionDetailWithImageModel.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/ActionDetailWithImageModel.swift @@ -10,7 +10,7 @@ import Foundation public struct ActionDetailWithImageModel: MoleculeModelProtocol { public static var identifier: String = "actionDetailWithImage" - public var moleculeName: String? = ActionDetailWithImageModel.identifier + public var moleculeName: String = ActionDetailWithImageModel.identifier public var backgroundColor: Color? public var headlineBodyButton: HeadlineBodyButtonModel public var image: ImageViewModel diff --git a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggleModel.swift b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggleModel.swift index aad8ec06..917bf5dc 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggleModel.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyLinkToggleModel.swift @@ -9,7 +9,7 @@ import Foundation public struct HeadlineBodyLinkToggleModel: MoleculeModelProtocol { public static var identifier: String = "headlineBodyLinkToggle" - public var moleculeName: String? = HeadlineBodyLinkToggleModel.identifier + public var moleculeName: String = HeadlineBodyLinkToggleModel.identifier public var backgroundColor: Color? public var headlineBodyLink: HeadlineBodyLinkModel public var toggle: ToggleModel diff --git a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggleModel.swift b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggleModel.swift index bb3391a6..800c976b 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggleModel.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/HeadlineBodyToggleModel.swift @@ -11,7 +11,7 @@ import Foundation open class HeadlineBodyToggleModel: MoleculeModelProtocol { public static var identifier: String = "headlineBodyToggle" - public var moleculeName: String? = HeadlineBodyToggleModel.identifier + public var moleculeName: String = HeadlineBodyToggleModel.identifier open var backgroundColor: Color? open var headlineBody: HeadlineBodyModel open var toggle: ToggleModel diff --git a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/LabelToggleModel.swift b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/LabelToggleModel.swift index 526ac6b9..16f292ed 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/LabelToggleModel.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/ToggleMolecules/LabelToggleModel.swift @@ -10,7 +10,7 @@ import Foundation public class LabelToggleModel: MoleculeModelProtocol { public static var identifier: String = "labelToggle" - public var moleculeName: String? = LabelToggleModel.identifier + public var moleculeName: String = LabelToggleModel.identifier public var backgroundColor: Color? public var label: LabelModel public var toggle: ToggleModel diff --git a/MVMCoreUI/Molecules/ScrollerModel.swift b/MVMCoreUI/Molecules/ScrollerModel.swift index 91dc2e1c..74256e99 100644 --- a/MVMCoreUI/Molecules/ScrollerModel.swift +++ b/MVMCoreUI/Molecules/ScrollerModel.swift @@ -10,6 +10,6 @@ import UIKit public class ScrollerModel: MoleculeContainerModel, MoleculeModelProtocol { public static var identifier: String = "scroller" - public var moleculeName: String? = ScrollerModel.identifier + public var moleculeName: String = ScrollerModel.identifier public var backgroundColor: Color? } diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift index e277f5de..0f158c2c 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift @@ -14,7 +14,7 @@ public class EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol { //-------------------------------------------------- public static var identifier: String = "eyebrowHeadlineBodyLink" - public var moleculeName: String? = EyebrowHeadlineBodyLinkModel.identifier + public var moleculeName: String = EyebrowHeadlineBodyLinkModel.identifier public var backgroundColor: Color? public var eyebrow: LabelModel? public var headline: LabelModel? diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyButtonModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyButtonModel.swift index ec97fda0..439e3aec 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyButtonModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyButtonModel.swift @@ -10,7 +10,7 @@ import Foundation public struct HeadlineBodyButtonModel: MoleculeModelProtocol { public static var identifier: String = "headlineBodyButton" - public var moleculeName: String? = HeadlineBodyButtonModel.identifier + public var moleculeName: String = HeadlineBodyButtonModel.identifier public var backgroundColor: Color? public var headlineBody: HeadlineBodyModel diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyLinkModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyLinkModel.swift index 27f0d670..4ef4018b 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyLinkModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyLinkModel.swift @@ -10,7 +10,7 @@ import Foundation public struct HeadlineBodyLinkModel: MoleculeModelProtocol { public static var identifier: String = "headlineBodyLink" - public var moleculeName: String? = HeadlineBodyLinkModel.identifier + public var moleculeName: String = HeadlineBodyLinkModel.identifier public var headlineBody: HeadlineBodyModel public var link: LinkModel public var backgroundColor: Color? diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift index 0ec98c65..e715b61e 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift @@ -10,7 +10,7 @@ import Foundation @objcMembers open class HeadlineBodyModel: MoleculeModelProtocol { public static var identifier: String = "headlineBody" - public var moleculeName: String? = HeadlineBodyModel.identifier + public var moleculeName: String = HeadlineBodyModel.identifier public var headline: LabelModel? public var body: LabelModel? public var style: String? diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeStack.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeStack.swift index 48f39fa0..56cc0447 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeStack.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/StringAndMoleculeStack/StringAndMoleculeStack.swift @@ -14,8 +14,7 @@ open class StringAndMoleculeStack: MoleculeStackView { guard let model = stackModel else { return } for stackItemModel in model.molecules { guard let stringAndMoleculeModel = stackItemModel.molecule as? StringAndMoleculeModel, - let moleculeName = stringAndMoleculeModel.molecule.moleculeName, - let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forName: moleculeName) as? (UIView & ModelMoleculeViewProtocol) else { + let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forName: stringAndMoleculeModel.molecule.moleculeName) as? (UIView & ModelMoleculeViewProtocol) else { // Throw error return } diff --git a/MVMCoreUI/Organisms/Carousel.swift b/MVMCoreUI/Organisms/Carousel.swift index ba675adf..b4fa5c24 100644 --- a/MVMCoreUI/Organisms/Carousel.swift +++ b/MVMCoreUI/Organisms/Carousel.swift @@ -158,11 +158,10 @@ open class Carousel: View { // MARK: - Convenience /// Returns the (identifier, class) of the molecule for the given map. func getMoleculeInfo(with molecule: MoleculeModelProtocol, delegateObject: MVMCoreUIDelegateObject?) -> (identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)? { - guard let className = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(molecule) , - let moleculeName = (className as? ModelMoleculeViewProtocol.Type)?.nameForReuse(with: molecule, delegateObject) ?? molecule.moleculeName else { + guard let className = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(molecule) else { return nil } - return (moleculeName, className, molecule) + return ((className as? ModelMoleculeViewProtocol.Type)?.nameForReuse(with: molecule, delegateObject) ?? molecule.moleculeName, className, molecule) } /// Sets the alignment from the string. diff --git a/MVMCoreUI/Organisms/Stack.swift b/MVMCoreUI/Organisms/Stack.swift index 8fa220ec..8e6df863 100644 --- a/MVMCoreUI/Organisms/Stack.swift +++ b/MVMCoreUI/Organisms/Stack.swift @@ -162,13 +162,11 @@ open class Stack: Container where T: (StackModelProtocol & MoleculeModelProto } var name = "stack<" for case let item in model.molecules { - if let moleculeName = item.moleculeName { - if let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping[moleculeName] as? ModelMoleculeViewProtocol.Type, - let nameForReuse = moleculeClass.nameForReuse(with: item, delegateObject) { - name.append(nameForReuse + ",") - } else { - name.append(moleculeName + ",") - } + if let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping[item.moleculeName] as? ModelMoleculeViewProtocol.Type, + let nameForReuse = moleculeClass.nameForReuse(with: item, delegateObject) { + name.append(nameForReuse + ",") + } else { + name.append(item.moleculeName + ",") } } name.append(">") diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject+ModelExtension.swift b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject+ModelExtension.swift index 8eb0c34d..a7054d4e 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject+ModelExtension.swift +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject+ModelExtension.swift @@ -16,10 +16,7 @@ public extension MVMCoreUIMoleculeMappingObject { } func getMoleculeClass(_ model: MoleculeModelProtocol) -> AnyClass? { - if let moleculeName = model.moleculeName { - return moleculeMapping.object(forKey: moleculeName) as? AnyClass - } - return nil + return moleculeMapping.object(forKey: model.moleculeName) as? AnyClass } func createMolecule(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> (UIView & MVMCoreUIMoleculeViewProtocol)? { @@ -27,8 +24,7 @@ public extension MVMCoreUIMoleculeMappingObject { } func createMolecule(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ constrainIfNeeded: Bool) -> (UIView & MVMCoreUIMoleculeViewProtocol)? { - guard let moleculeName = model.moleculeName, - let molecule = createMolecule(forName: moleculeName) else { + guard let molecule = createMolecule(forName: model.moleculeName) else { return nil } diff --git a/MVMCoreUI/Templates/ModalMoleculeListTemplate.swift b/MVMCoreUI/Templates/ModalMoleculeListTemplate.swift index 65ec0931..7c62faab 100644 --- a/MVMCoreUI/Templates/ModalMoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/ModalMoleculeListTemplate.swift @@ -13,9 +13,9 @@ open class ModalMoleculeListTemplate: MoleculeListTemplate { public var closeButton: MFCustomButton? override open func handleNewData() { - super.newDataBuildScreen() + super.handleNewData() closeButton = MVMCoreUICommonViewsUtility.addCloseButton(to: view, action: { [weak self] _ in - self?.dismiss() + MVMCoreNavigationHandler.shared()?.removeCurrentViewController() }, verticalCentered: false) } } diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index bca29172..9503a4c6 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -215,10 +215,8 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol func getMoleculeInfo(with listItem: (ListItemModelProtocol & MoleculeModelProtocol)?) -> (identifier: String, class: AnyClass, molecule: ListItemModelProtocol & MoleculeModelProtocol)? { guard let listItem = listItem, - let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(listItem), - let moleculeName = (moleculeClass as? ModelMoleculeViewProtocol.Type)?.nameForReuse(with: listItem, delegateObject() as? MVMCoreUIDelegateObject) ?? listItem.moleculeName - else { return nil } - + let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(listItem) else { return nil } + let moleculeName = (moleculeClass as? ModelMoleculeViewProtocol.Type)?.nameForReuse(with: listItem, delegateObject() as? MVMCoreUIDelegateObject) ?? listItem.moleculeName return (moleculeName, moleculeClass, listItem) } From c39e344f25c46aa4673ef1f1b57fab96c17779f7 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Mon, 23 Mar 2020 11:03:41 -0400 Subject: [PATCH 10/17] crash fix --- MVMCoreUI.xcodeproj/project.pbxproj | 10 +++++++--- .../Atoms/TextFields/TextEntryField.swift | 4 ++-- .../BaseControllers/ViewController.swift | 2 +- ...VMCoreUICommonViewsUtility+Extension.swift | 20 +++++++++++++++++++ 4 files changed, 30 insertions(+), 6 deletions(-) create mode 100644 MVMCoreUI/Utility/MVMCoreUICommonViewsUtility+Extension.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index af3081dc..5308ee86 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -213,10 +213,10 @@ D22D1F47220496A30077CEC0 /* MVMCoreUISwitch.m in Sources */ = {isa = PBXBuildFile; fileRef = D22D1F45220496A30077CEC0 /* MVMCoreUISwitch.m */; }; D22D1F562204CE5D0077CEC0 /* MVMCoreUIStackableViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = D22D1F542204CE5D0077CEC0 /* MVMCoreUIStackableViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; D22D1F572204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D22D1F552204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m */; }; + D22D8393241C27B100D3DF69 /* TemplateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22D8392241C27B100D3DF69 /* TemplateModel.swift */; }; D22D8395241FB41200D3DF69 /* UIStackView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22D8394241FB41200D3DF69 /* UIStackView+Extension.swift */; }; D236E5B4241FEB1000C38625 /* ListTwoColumnPriceDescription.swift in Sources */ = {isa = PBXBuildFile; fileRef = D236E5B2241FEB1000C38625 /* ListTwoColumnPriceDescription.swift */; }; D236E5B5241FEB1000C38625 /* ListTwoColumnPriceDescriptionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D236E5B3241FEB1000C38625 /* ListTwoColumnPriceDescriptionModel.swift */; }; - D22D8393241C27B100D3DF69 /* TemplateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22D8392241C27B100D3DF69 /* TemplateModel.swift */; }; D236E5B7242007C500C38625 /* MVMControllerModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D236E5B6242007C500C38625 /* MVMControllerModelProtocol.swift */; }; D243859923A16B1800332775 /* Container.swift in Sources */ = {isa = PBXBuildFile; fileRef = D243859823A16B1800332775 /* Container.swift */; }; D256E9932412880000360572 /* Header.swift in Sources */ = {isa = PBXBuildFile; fileRef = D256E9922412880000360572 /* Header.swift */; }; @@ -266,6 +266,7 @@ 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 */; }; + D29C94D5242901C9003813BA /* MVMCoreUICommonViewsUtility+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D29C94D4242901C9003813BA /* MVMCoreUICommonViewsUtility+Extension.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, ); }; }; @@ -603,10 +604,10 @@ D22D1F45220496A30077CEC0 /* MVMCoreUISwitch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUISwitch.m; sourceTree = ""; }; D22D1F542204CE5D0077CEC0 /* MVMCoreUIStackableViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIStackableViewController.h; sourceTree = ""; }; D22D1F552204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIStackableViewController.m; sourceTree = ""; }; + D22D8392241C27B100D3DF69 /* TemplateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateModel.swift; sourceTree = ""; }; D22D8394241FB41200D3DF69 /* UIStackView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIStackView+Extension.swift"; sourceTree = ""; }; D236E5B2241FEB1000C38625 /* ListTwoColumnPriceDescription.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListTwoColumnPriceDescription.swift; sourceTree = ""; }; D236E5B3241FEB1000C38625 /* ListTwoColumnPriceDescriptionModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListTwoColumnPriceDescriptionModel.swift; sourceTree = ""; }; - D22D8392241C27B100D3DF69 /* TemplateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateModel.swift; sourceTree = ""; }; D236E5B6242007C500C38625 /* MVMControllerModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMControllerModelProtocol.swift; sourceTree = ""; }; D243859823A16B1800332775 /* Container.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Container.swift; sourceTree = ""; }; D256E9922412880000360572 /* Header.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Header.swift; sourceTree = ""; }; @@ -655,6 +656,7 @@ 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 = ""; }; + D29C94D4242901C9003813BA /* MVMCoreUICommonViewsUtility+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MVMCoreUICommonViewsUtility+Extension.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 = ""; }; @@ -872,7 +874,7 @@ 01C74D87224298E2009C25A3 /* FormUIHelpers */ = { isa = PBXGroup; children = ( - 011D95882404249B000E3791 /* FormProtocol.swift */, + 011D95882404249B000E3791 /* FormHolderModelProtocol.swift */, 011D95AC2406BB57000E3791 /* FormHolderProtocol.swift */, 011D95AA2405C553000E3791 /* FormItemProtocol.swift */, 011D958624042492000E3791 /* FormFieldProtocol.swift */, @@ -1474,6 +1476,7 @@ D29DF13B21E6870B003B2FB9 /* Sizing */, D29DF28221E7AB24003B2FB9 /* MVMCoreUICommonViewsUtility.h */, D29DF28121E7AB23003B2FB9 /* MVMCoreUICommonViewsUtility.m */, + D29C94D4242901C9003813BA /* MVMCoreUICommonViewsUtility+Extension.swift */, D29DF14D21E693AD003B2FB9 /* MFFonts.h */, D29DF14C21E693AD003B2FB9 /* MFFonts.m */, 9458C3152406C8FD00930963 /* UIFont+FontWrapping.h */, @@ -2026,6 +2029,7 @@ 525019E52406852100EED91C /* ListFourColumnDataUsageDividerModel.swift in Sources */, 0A7EF86723D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift in Sources */, 94FB966323D797DA003D482B /* MFTextButton.m in Sources */, + D29C94D5242901C9003813BA /* MVMCoreUICommonViewsUtility+Extension.swift in Sources */, D260105323CEA61600764D80 /* ToggleModel.swift in Sources */, 014AA72523C501E2006F3E93 /* ContainerModel.swift in Sources */, 0A7EF86523D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift in Sources */, diff --git a/MVMCoreUI/Atoms/TextFields/TextEntryField.swift b/MVMCoreUI/Atoms/TextFields/TextEntryField.swift index 4c56036e..33f75604 100644 --- a/MVMCoreUI/Atoms/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/TextEntryField.swift @@ -19,7 +19,7 @@ import UIKit } -@objcMembers open class TextEntryField: EntryField, UITextFieldDelegate { +@objcMembers open class TextEntryField: EntryField, UITextFieldDelegate, ObservingTextFieldDelegate { //-------------------------------------------------- // MARK: - Outlets //-------------------------------------------------- @@ -311,7 +311,7 @@ import UIKit uiTextFieldDelegate = delegateObject?.uiTextFieldDelegate observingTextFieldDelegate = delegateObject?.observingTextFieldDelegate - //MVMCoreUICommonViewsUtility.addDismissToolbar(textField, delegate: uiTextFieldDelegate) + textField.inputAccessoryView = MVMCoreUICommonViewsUtility.getToolbarWithDoneButton(delegate: observingTextFieldDelegate ?? self) } } diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index 333df798..7e1141ba 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -8,7 +8,7 @@ import UIKit -@objc open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMCoreViewManagerViewControllerProtocol, MoleculeDelegateProtocol, FormHolderProtocol, MVMCoreActionDelegateProtocol, UITextFieldDelegate, UITextViewDelegate { +@objc open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMCoreViewManagerViewControllerProtocol, MoleculeDelegateProtocol, FormHolderProtocol, MVMCoreActionDelegateProtocol, UITextFieldDelegate, UITextViewDelegate, ObservingTextFieldDelegate { @objc public var pageType: String? @objc public var loadObject: MVMCoreLoadObject? public var pageModel: MVMControllerModelProtocol? diff --git a/MVMCoreUI/Utility/MVMCoreUICommonViewsUtility+Extension.swift b/MVMCoreUI/Utility/MVMCoreUICommonViewsUtility+Extension.swift new file mode 100644 index 00000000..70c84d40 --- /dev/null +++ b/MVMCoreUI/Utility/MVMCoreUICommonViewsUtility+Extension.swift @@ -0,0 +1,20 @@ +// +// MVMCoreUICommonViewsUtility+Extension.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 3/23/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public extension MVMCoreUICommonViewsUtility { + static func getToolbarWithDoneButton(delegate: ObservingTextFieldDelegate) -> UIToolbar { + let toolbar = self.makeEmptyToolbar() + let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) + let button = UIBarButtonItem(barButtonSystemItem: .done, target: delegate, action: #selector(ObservingTextFieldDelegate.dismissFieldInput(sender:))) + button.tintColor = .black + toolbar.setItems([space, button], animated: false) + return toolbar + } +} From d05c96a9ad39516bd8957ff0f5fe1e6e791372ca Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Mon, 23 Mar 2020 11:09:08 -0400 Subject: [PATCH 11/17] digit box miss fix --- MVMCoreUI/Atoms/TextFields/DigitEntryField.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift b/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift index 53181bff..b249d89f 100644 --- a/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift @@ -338,7 +338,7 @@ import UIKit setAsSecureTextEntry(model.secureEntry) for digitBox in digitBoxes { - MVMCoreUICommonViewsUtility.addDismissToolbar(digitBox.digitField, delegate: delegateObject as? UITextFieldDelegate) + digitBox.digitField.inputAccessoryView = MVMCoreUICommonViewsUtility.getToolbarWithDoneButton(delegate: delegateObject?.observingTextFieldDelegate ?? self) } super.set(with: model, delegateObject, additionalData) From 13fc3adf09cc39241f22062d5b6e75c26aba28fc Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Mon, 23 Mar 2020 11:11:56 -0400 Subject: [PATCH 12/17] add comment --- MVMCoreUI/BaseControllers/ViewController.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index 7e1141ba..fac7a60e 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -16,6 +16,7 @@ import UIKit /// Set if this page is containted in a manager. public var manager: (UIViewController & MVMCoreViewManagerProtocol)? + // TODO: Change this logic once we convert the MVMCoreViewControllerProtocol to swift public var selfDelegateObject: MVMCoreUIDelegateObject? public func delegateObject() -> DelegateObject? { if selfDelegateObject == nil { From b49b45660c0f83b934779aff283fa8646674e65d Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Mon, 23 Mar 2020 12:32:23 -0400 Subject: [PATCH 13/17] Navigation item improvements --- .../BaseControllers/ViewController.swift | 53 +++++++------------ .../Containers/NavigationController.swift | 30 +++++++++++ .../NavigationItemModelProtocol.swift | 12 +++-- MVMCoreUI/Utility/MVMCoreUIUtility.h | 3 ++ MVMCoreUI/Utility/MVMCoreUIUtility.m | 21 ++++++++ 5 files changed, 82 insertions(+), 37 deletions(-) diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index fac7a60e..39226786 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -94,6 +94,14 @@ import UIKit try parsePageJSON() MVMCoreDispatchUtility.performBlock(onMainThread: { self.handleNewDataAndUpdateUI() + // If the screen is showing, can update the navigation controller. + if let navigationController = self.manager?.navigationController, + self.manager!.getCurrentViewController() == self { + self.set(navigationController: navigationController) + } else if let navigationController = self.navigationController, + self == MVMCoreUIUtility.getCurrentVisibleController() { + self.set(navigationController: navigationController) + } }) } catch { if let coreError = MVMCoreErrorObject.createErrorObject(for: error, location: "updateJSON for pageType: \(String(describing: pageType))") { @@ -156,20 +164,15 @@ import UIKit /// Processes any new data. Called after the page is loaded the first time and on response updates for this page, open func handleNewData() { - // Convert legacy to navigation model. - if pageModel?.navigationItem == nil { - let navigationModel = NavigationItemModel() - if navigationModel.title == nil { - navigationModel.title = pageModel?.screenHeading - } - if navigationModel.showLeftPanelButton == nil { - navigationModel.showLeftPanelButton = isMasterInitiallyAccessible() - } - if navigationModel.showRightPanelButton == nil { - navigationModel.showRightPanelButton = isSupportInitiallyAccessible() - } - pageModel?.navigationItem = navigationModel + // TODO: remove legacy. Temporary, convert legacy to navigation model. + var navigationModel = pageModel?.navigationItem ?? NavigationItemModel() + navigationModel.title = pageModel?.screenHeading + navigationModel.showLeftPanelButton = isMasterInitiallyAccessible() + navigationModel.showRightPanelButton = isSupportInitiallyAccessible() + if /*(self as? MVMCoreUITabBarPageControlViewController) != nil ||*/ manager != nil || loadObject?.requestParameters?.tabWasPressed ?? false == true { + navigationModel.line = LineModel(type: .none) } + pageModel?.navigationItem = navigationModel if self.formValidator == nil { let rules = pageModel?.formRules self.formValidator = FormValidator(rules) @@ -183,30 +186,12 @@ import UIKit MVMCoreUISession.sharedGlobal()?.splitViewController?.parent?.setNeedsStatusBarAppearanceUpdate() return } - navigationItem.title = navigationItemModel.title - navigationItem.accessibilityLabel = navigationItemModel.title - - navigationController.setNavigationBarHidden(navigationItemModel.hidden, animated: true) - UIColor.setBackgroundColor(navigationItemModel.backgroundColor?.uiColor ?? .white, for: navigationController.navigationBar, isTransparent: navigationItemModel.transparent) - - let tint = navigationItemModel.tintColor.uiColor - navigationController.navigationBar.tintColor = tint - - // Have the navigation title match the tint color - navigationController.navigationBar.titleTextAttributes?.updateValue(tint, forKey: .foregroundColor) - - // Update icons if main navigation controller. if navigationController == MVMCoreUISplitViewController.main()?.navigationController, - MVMCoreUISplitViewController.main()?.getCurrentVisibleController() == self { + navigationController.topViewController == self { MVMCoreUISession.sharedGlobal()?.splitViewController?.setupPanels() - MVMCoreUISplitViewController.main()?.setLeftPanelIsAccessible(navigationItemModel.showLeftPanelButton ?? false, for: self) - MVMCoreUISplitViewController.main()?.setRightPanelIsAccessible(navigationItemModel.showRightPanelButton ?? false, for: self) - showBottomProgressBar() - MVMCoreUISession.sharedGlobal()?.splitViewController?.setNavigationIconColor(tint) - - // Update separator. - MVMCoreUISession.sharedGlobal()?.navigationController?.separatorView?.isHidden = /*self is MVMCoreUITabBarPageControlViewController ||*/ manager != nil || loadObject?.requestParameters?.tabWasPressed ?? false == true + showBottomProgressBar() } + NavigationController.set(navigationController: navigationController, navigationItemModel: navigationItemModel, viewController: self) } // Eventually will be moved to server diff --git a/MVMCoreUI/Containers/NavigationController.swift b/MVMCoreUI/Containers/NavigationController.swift index 6e18e427..74aadca7 100644 --- a/MVMCoreUI/Containers/NavigationController.swift +++ b/MVMCoreUI/Containers/NavigationController.swift @@ -39,4 +39,34 @@ import UIKit MVMCoreUISession.sharedGlobal()?.setup(asStandardLoadViewDelegate: navigationController) return navigationController } + + public static func set(navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol, viewController: (UIViewController & MVMCoreViewControllerProtocol)) { + viewController.navigationItem.title = navigationItemModel.title + viewController.navigationItem.accessibilityLabel = navigationItemModel.title + viewController.navigationItem.hidesBackButton = !navigationItemModel.systemBackButton + + navigationController.setNavigationBarHidden(navigationItemModel.hidden, animated: true) + UIColor.setBackgroundColor(navigationItemModel.backgroundColor?.uiColor ?? .white, for: navigationController.navigationBar, isTransparent: navigationItemModel.transparent) + + let tint = navigationItemModel.tintColor.uiColor + navigationController.navigationBar.tintColor = tint + + // Have the navigation title match the tint color + navigationController.navigationBar.titleTextAttributes?.updateValue(tint, forKey: .foregroundColor) + + // Update icons if main navigation controller. + if navigationController == MVMCoreUISession.sharedGlobal()?.navigationController, + navigationController.topViewController == viewController { + // Update line. + MVMCoreUISession.sharedGlobal()?.navigationController?.separatorView?.set(with: navigationItemModel.line ?? LineModel(type: .standard), viewController.delegateObject?() as? MVMCoreUIDelegateObject, nil) + } + + if navigationController == MVMCoreUISplitViewController.main()?.navigationController, + navigationController.topViewController == viewController { + // Update Panels + MVMCoreUISplitViewController.main()?.setLeftPanelIsAccessible(navigationItemModel.showLeftPanelButton ?? false, for: viewController) + MVMCoreUISplitViewController.main()?.setRightPanelIsAccessible(navigationItemModel.showRightPanelButton ?? false, for: viewController) + MVMCoreUISession.sharedGlobal()?.splitViewController?.setNavigationIconColor(tint) + } + } } diff --git a/MVMCoreUI/Molecules/NavigationItemModelProtocol.swift b/MVMCoreUI/Molecules/NavigationItemModelProtocol.swift index 24b375fe..605b6e5e 100644 --- a/MVMCoreUI/Molecules/NavigationItemModelProtocol.swift +++ b/MVMCoreUI/Molecules/NavigationItemModelProtocol.swift @@ -15,7 +15,8 @@ public protocol NavigationItemModelProtocol: MoleculeModelProtocol { var backgroundColor: Color? { get set } var transparent: Bool { get set } var tintColor: Color { get set } - var systemBackButton: Bool? { get set } + var line: LineModel? { get set } + var systemBackButton: Bool { get set } var showLeftPanelButton: Bool? { get set } var showRightPanelButton: Bool? { get set } var additionalLeftItems: [NavigationItemButtonModel]? { get set } @@ -60,7 +61,8 @@ public class NavigationItemModel: NavigationItemModelProtocol { public var backgroundColor: Color? public var transparent: Bool public var tintColor: Color - public var systemBackButton: Bool? + public var line: LineModel? + public var systemBackButton = false public var showLeftPanelButton: Bool? public var showRightPanelButton: Bool? public var additionalLeftItems: [NavigationItemButtonModel]? @@ -71,6 +73,7 @@ public class NavigationItemModel: NavigationItemModelProtocol { transparent = false backgroundColor = Color(uiColor: .white) tintColor = Color(uiColor: .black) + line = LineModel(type: .standard) } private enum CodingKeys: String, CodingKey { @@ -80,6 +83,7 @@ public class NavigationItemModel: NavigationItemModelProtocol { case backgroundColor case transparent case tintColor + case line case systemBackButton case showLeftPanelButton case showRightPanelButton @@ -95,6 +99,7 @@ public class NavigationItemModel: NavigationItemModelProtocol { backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) ?? Color(uiColor: .white) transparent = try typeContainer.decodeIfPresent(Bool.self, forKey: .transparent) ?? false tintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .tintColor) ?? Color(uiColor: .black) + line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line) systemBackButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .systemBackButton) ?? false showLeftPanelButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .showLeftPanelButton) showRightPanelButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .showRightPanelButton) @@ -110,7 +115,8 @@ public class NavigationItemModel: NavigationItemModelProtocol { try container.encode(backgroundColor, forKey: .backgroundColor) try container.encode(transparent, forKey: .transparent) try container.encode(tintColor, forKey: .tintColor) - try container.encodeIfPresent(systemBackButton, forKey: .systemBackButton) + try container.encodeIfPresent(line, forKey: .line) + try container.encode(systemBackButton, forKey: .systemBackButton) try container.encode(showLeftPanelButton, forKey: .showLeftPanelButton) try container.encode(showRightPanelButton, forKey: .showRightPanelButton) try container.encodeIfPresent(additionalLeftItems, forKey: .additionalLeftItems) diff --git a/MVMCoreUI/Utility/MVMCoreUIUtility.h b/MVMCoreUI/Utility/MVMCoreUIUtility.h index 9300de90..21c92c38 100644 --- a/MVMCoreUI/Utility/MVMCoreUIUtility.h +++ b/MVMCoreUI/Utility/MVMCoreUIUtility.h @@ -31,6 +31,9 @@ NS_ASSUME_NONNULL_BEGIN // Returns the margins for a view. + (UIEdgeInsets)getMarginsForView:(nullable UIView *)view; +/// Gets the current visible view controller. Checks presented view controllers first, and then it checks on the NavigationController in the session object. ++ (UIViewController *)getCurrentVisibleController; + #pragma mark - Setters + (void)setMarginsForView:(nullable UIView *)view leading:(CGFloat)leading top:(CGFloat)top trailing:(CGFloat)trailing bottom:(CGFloat)bottom; diff --git a/MVMCoreUI/Utility/MVMCoreUIUtility.m b/MVMCoreUI/Utility/MVMCoreUIUtility.m index b760eb36..4b0278de 100644 --- a/MVMCoreUI/Utility/MVMCoreUIUtility.m +++ b/MVMCoreUI/Utility/MVMCoreUIUtility.m @@ -10,6 +10,7 @@ #import "MVMCoreUIConstants.h" #import "MVMCoreUISession.h" #import "MVMCoreUISplitViewController.h" +#import @import MVMCore.MVMCoreNavigationHandler; @import MVMCore.MVMCoreGetterUtility; @@ -60,6 +61,26 @@ return UIEdgeInsetsMake(view.directionalLayoutMargins.top, view.directionalLayoutMargins.leading, view.directionalLayoutMargins.bottom, view.directionalLayoutMargins.trailing); } ++ (UIViewController *)getCurrentVisibleController { + UIViewController *baseViewController = [MVMCoreNavigationHandler sharedNavigationHandler].viewControllerToPresentOn ?: [UIApplication sharedApplication].keyWindow.rootViewController; + UIViewController *viewController = nil; + while (baseViewController.presentedViewController && !baseViewController.presentedViewController.isBeingDismissed) { + viewController = baseViewController.presentedViewController; + baseViewController = viewController; + } + if ([viewController isKindOfClass:[UINavigationController class]]) { + viewController = ((UINavigationController *)viewController).topViewController; + } + // if it is not presented viewcontroller, existing BAU logic will be working + if (!viewController) { + viewController = [MVMCoreUISession sharedGlobal].navigationController.topViewController; + if ([viewController conformsToProtocol:@protocol(MVMCoreViewManagerProtocol)]) { + viewController = [viewController performSelector:@selector(getCurrentViewController)]; + } + } + return viewController; +} + #pragma mark - Setters + (void)setMarginsForView:(nullable UIView *)view leading:(CGFloat)leading top:(CGFloat)top trailing:(CGFloat)trailing bottom:(CGFloat)bottom { From 776939777bdfe5367f0b3394a5977833c90b812e Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Mon, 23 Mar 2020 14:28:36 -0400 Subject: [PATCH 14/17] Retain cycle fixes --- MVMCoreUI/Atoms/Buttons/PillButton.swift | 2 +- MVMCoreUI/FormUIHelpers/FormValidator.swift | 2 +- MVMCoreUI/OtherHandlers/MVMCoreUIDelegateObject.swift | 2 +- MVMCoreUI/OtherHandlers/ModelMoleculeDelegateProtocol.swift | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atoms/Buttons/PillButton.swift b/MVMCoreUI/Atoms/Buttons/PillButton.swift index da8cf0c7..c760c0b7 100644 --- a/MVMCoreUI/Atoms/Buttons/PillButton.swift +++ b/MVMCoreUI/Atoms/Buttons/PillButton.swift @@ -130,7 +130,7 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol { self?.enableField(model.enabled) } - FormValidator.setupValidation(molecule: model, delegate: delegateObject?.formHolderDelegate) + FormValidator.setupValidation(molecule: model, delegate: delegateObject?.formHolderDelegate) } open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { diff --git a/MVMCoreUI/FormUIHelpers/FormValidator.swift b/MVMCoreUI/FormUIHelpers/FormValidator.swift index 8977fad5..0a14e027 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator.swift @@ -14,7 +14,7 @@ import MVMCore static var defaultGroupName: String = "default" var extraValidationBlock: (() -> Bool)? var formRules: [FormGroupRule]? - var delegate: FormHolderProtocol? + weak var delegate: FormHolderProtocol? var fieldMolecules: [String: FormFieldProtocol] = [:] var formActionMolecules: [FormActionFieldProtocol] = [] var radioButtonsModelByGroup: [String: RadioButtonSelectionHelper] = [:] diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIDelegateObject.swift b/MVMCoreUI/OtherHandlers/MVMCoreUIDelegateObject.swift index 54de3802..c9d5d34c 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIDelegateObject.swift +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIDelegateObject.swift @@ -13,7 +13,7 @@ open class MVMCoreUIDelegateObject: DelegateObject { public weak var buttonDelegate: ButtonDelegateProtocol? public weak var uiTextFieldDelegate: UITextFieldDelegate? public weak var observingTextFieldDelegate: ObservingTextFieldDelegate? - public var moleculeDelegate: MoleculeDelegateProtocol? + public weak var moleculeDelegate: MoleculeDelegateProtocol? open override func setAll(withDelegate delegate: Any) { super.setAll(withDelegate: delegate) diff --git a/MVMCoreUI/OtherHandlers/ModelMoleculeDelegateProtocol.swift b/MVMCoreUI/OtherHandlers/ModelMoleculeDelegateProtocol.swift index 435e5a24..07df3296 100644 --- a/MVMCoreUI/OtherHandlers/ModelMoleculeDelegateProtocol.swift +++ b/MVMCoreUI/OtherHandlers/ModelMoleculeDelegateProtocol.swift @@ -8,7 +8,7 @@ import Foundation -public protocol MoleculeDelegateProtocol { +public protocol MoleculeDelegateProtocol: AnyObject { /// returns a module for the corresponding module name. func getModuleWithName(_ name: String?) -> [AnyHashable : Any]? From 71fdc43b86aafa9fa9a464313b014a673e8fb35a Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Mon, 23 Mar 2020 14:55:26 -0400 Subject: [PATCH 15/17] typo fix --- .../BaseControllers/ProgrammaticScrollViewController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/BaseControllers/ProgrammaticScrollViewController.swift b/MVMCoreUI/BaseControllers/ProgrammaticScrollViewController.swift index 10583b14..b6ed6353 100644 --- a/MVMCoreUI/BaseControllers/ProgrammaticScrollViewController.swift +++ b/MVMCoreUI/BaseControllers/ProgrammaticScrollViewController.swift @@ -31,7 +31,7 @@ open class ProgrammaticScrollViewController: ScrollingViewController { let scrollView = UIScrollView() scrollView.backgroundColor = .clear - scrollView.translatesAutoresizingMaskIntoConstraints = true + scrollView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(scrollView) // Sets the constraints for the scroll view From 7b36f466fa862960742ecebca6871f8f8bbbc671 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Mon, 23 Mar 2020 15:01:31 -0400 Subject: [PATCH 16/17] navigation item update to fix crash --- MVMCoreUI/Models/ModelProtocols/PageModelProtocol.swift | 2 +- MVMCoreUI/Molecules/NavigationItemModelProtocol.swift | 4 ++-- MVMCoreUI/Templates/ListPageTemplateModel.swift | 2 +- MVMCoreUI/Templates/StackCenteredPageTemplateModel.swift | 2 +- MVMCoreUI/Templates/TemplateModel.swift | 2 +- MVMCoreUI/Templates/ThreeLayerPageTemplateModel.swift | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/MVMCoreUI/Models/ModelProtocols/PageModelProtocol.swift b/MVMCoreUI/Models/ModelProtocols/PageModelProtocol.swift index 7f50873e..5c53ea4e 100644 --- a/MVMCoreUI/Models/ModelProtocols/PageModelProtocol.swift +++ b/MVMCoreUI/Models/ModelProtocols/PageModelProtocol.swift @@ -13,5 +13,5 @@ public protocol PageModelProtocol { var pageType: String { get set } var screenHeading: String? { get set } var isAtomicTabs: Bool? { get set } - var navigationItem: NavigationItemModelProtocol? { get set } + var navigationItem: (NavigationItemModelProtocol & MoleculeModelProtocol)? { get set } } diff --git a/MVMCoreUI/Molecules/NavigationItemModelProtocol.swift b/MVMCoreUI/Molecules/NavigationItemModelProtocol.swift index 605b6e5e..d7df7cc9 100644 --- a/MVMCoreUI/Molecules/NavigationItemModelProtocol.swift +++ b/MVMCoreUI/Molecules/NavigationItemModelProtocol.swift @@ -8,7 +8,7 @@ import Foundation -public protocol NavigationItemModelProtocol: MoleculeModelProtocol { +public protocol NavigationItemModelProtocol { var title: String? { get set } var titleView: MoleculeModelProtocol? { get set } var hidden: Bool { get set } @@ -50,7 +50,7 @@ public class NavigationItemButtonModel: Codable { } } -public class NavigationItemModel: NavigationItemModelProtocol { +public class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtocol { public class var identifier: String { return "navigationItem" } diff --git a/MVMCoreUI/Templates/ListPageTemplateModel.swift b/MVMCoreUI/Templates/ListPageTemplateModel.swift index 57d99f26..0188a434 100644 --- a/MVMCoreUI/Templates/ListPageTemplateModel.swift +++ b/MVMCoreUI/Templates/ListPageTemplateModel.swift @@ -22,7 +22,7 @@ import Foundation public var pageType: String public var screenHeading: String? public var isAtomicTabs: Bool? - public var navigationItem: NavigationItemModelProtocol? + public var navigationItem: (NavigationItemModelProtocol & MoleculeModelProtocol)? public var header: MoleculeModelProtocol? public var molecules: [ListItemModelProtocol & MoleculeModelProtocol]? diff --git a/MVMCoreUI/Templates/StackCenteredPageTemplateModel.swift b/MVMCoreUI/Templates/StackCenteredPageTemplateModel.swift index c3a4b64e..22934239 100644 --- a/MVMCoreUI/Templates/StackCenteredPageTemplateModel.swift +++ b/MVMCoreUI/Templates/StackCenteredPageTemplateModel.swift @@ -17,7 +17,7 @@ import Foundation public var pageType: String public var screenHeading: String? public var isAtomicTabs: Bool? - public var navigationItem: NavigationItemModelProtocol? + public var navigationItem: (NavigationItemModelProtocol & MoleculeModelProtocol)? public init(pageType: String) { self.pageType = pageType diff --git a/MVMCoreUI/Templates/TemplateModel.swift b/MVMCoreUI/Templates/TemplateModel.swift index 053d45fc..786068d0 100644 --- a/MVMCoreUI/Templates/TemplateModel.swift +++ b/MVMCoreUI/Templates/TemplateModel.swift @@ -15,7 +15,7 @@ import Foundation public var pageType: String public var screenHeading: String? public var isAtomicTabs: Bool? - public var navigationItem: NavigationItemModelProtocol? + public var navigationItem: (NavigationItemModelProtocol & MoleculeModelProtocol)? public var formRules: [FormGroupRule]? public init(pageType: String) { diff --git a/MVMCoreUI/Templates/ThreeLayerPageTemplateModel.swift b/MVMCoreUI/Templates/ThreeLayerPageTemplateModel.swift index c45e7fb7..9ee830e2 100644 --- a/MVMCoreUI/Templates/ThreeLayerPageTemplateModel.swift +++ b/MVMCoreUI/Templates/ThreeLayerPageTemplateModel.swift @@ -18,7 +18,7 @@ import Foundation public var pageType: String public var screenHeading: String? public var isAtomicTabs: Bool? - public var navigationItem: NavigationItemModelProtocol? + public var navigationItem: (NavigationItemModelProtocol & MoleculeModelProtocol)? public var header: MoleculeModelProtocol? public var middle: MoleculeModelProtocol? From 8860ced85e2499bb2b2177851d22dc1cff50d880 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Mon, 23 Mar 2020 15:22:04 -0400 Subject: [PATCH 17/17] fix typo --- MVMCoreUI/Templates/MoleculeListTemplate.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index 9503a4c6..d68a1170 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -162,7 +162,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol open override func getIndexPath(for molecule: ListItemModelProtocol & MoleculeModelProtocol) -> IndexPath? { guard let index = moleculesInfo?.firstIndex(where: { (moleculeInfo) -> Bool in - //TODO: cehck for molecule protocola eqality + //TODO: check for molecule protocola eqaulity let json = moleculeInfo.molecule.toJSON() return json == molecule.toJSON() }) else { return nil } @@ -192,7 +192,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol open override func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], animation: UITableView.RowAnimation) { var indexPaths: [IndexPath] = [] - //TODO: cehck for molecule protocola eqality + //TODO: check for molecule protocola equality for molecule in molecules { if let removeIndex = moleculesInfo?.firstIndex(where: { molecule.toJSON() == $0.molecule.toJSON() }) {