From d476b9ce14a77354bfa174a2ee4c0074346601f2 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Mon, 18 May 2020 14:55:29 -0400 Subject: [PATCH] Navigation fixing --- MVMCoreUI.xcodeproj/project.pbxproj | 28 ++++++++++-- MVMCoreUI/Atomic/Atoms/Views/Line.swift | 4 ++ .../NavigationItemButtonModel.swift | 35 +++++++++++++++ .../NavigationItemModel.swift} | 43 +------------------ .../NavigationItemModelProtocol.swift | 21 +++++++++ .../PanelNavigationItemModelProtocol.swift | 14 ++++++ .../MVMControllerModelProtocol.swift | 1 + .../Containers/NavigationController.swift | 10 ++--- .../MVMCoreUISplitViewController.h | 4 +- .../MVMCoreUISplitViewController.m | 13 ++++-- 10 files changed, 116 insertions(+), 57 deletions(-) create mode 100644 MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemButtonModel.swift rename MVMCoreUI/Atomic/Molecules/{NavigationItemModelProtocol.swift => NavigationBar/NavigationItemModel.swift} (70%) create mode 100644 MVMCoreUI/Atomic/Protocols/ModelProtocols/NavigationItemModelProtocol.swift create mode 100644 MVMCoreUI/Atomic/Protocols/ModelProtocols/PanelNavigationItemModelProtocol.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index ec7e68b0..59816653 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -245,7 +245,7 @@ D2092357244FA1EF0044AD09 /* ThreeLayerModelBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2092356244FA1EF0044AD09 /* ThreeLayerModelBase.swift */; }; D20923592450ECE00044AD09 /* TableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20923582450ECE00044AD09 /* TableView.swift */; }; D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */; }; - D20FB165241A5D75004AFC3A /* NavigationItemModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20FB164241A5D75004AFC3A /* NavigationItemModelProtocol.swift */; }; + D20FB165241A5D75004AFC3A /* NavigationItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20FB164241A5D75004AFC3A /* NavigationItemModel.swift */; }; D213347723843825008E41B3 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = D213347623843825008E41B3 /* Line.swift */; }; D21B7F602437C5BC00051ABF /* MoleculeStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21B7F5E2437C5BC00051ABF /* MoleculeStackView.swift */; }; D21B7F71243BAC1600051ABF /* CollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21B7F70243BAC1600051ABF /* CollectionViewCell.swift */; }; @@ -264,6 +264,9 @@ D236E5B5241FEB1000C38625 /* ListTwoColumnPriceDescriptionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D236E5B3241FEB1000C38625 /* ListTwoColumnPriceDescriptionModel.swift */; }; D236E5B7242007C500C38625 /* MVMControllerModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D236E5B6242007C500C38625 /* MVMControllerModelProtocol.swift */; }; D243859923A16B1800332775 /* Container.swift in Sources */ = {isa = PBXBuildFile; fileRef = D243859823A16B1800332775 /* Container.swift */; }; + D2509ED12472ED9B001BFB9D /* NavigationItemModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2509ED02472ED9B001BFB9D /* NavigationItemModelProtocol.swift */; }; + D2509ED32472EDC8001BFB9D /* PanelNavigationItemModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2509ED22472EDC8001BFB9D /* PanelNavigationItemModelProtocol.swift */; }; + D2509ED62472EE2F001BFB9D /* NavigationItemButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2509ED52472EE2F001BFB9D /* NavigationItemButtonModel.swift */; }; D253BB8A24574CC5002DE544 /* StackModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D260106423D0CEA700764D80 /* StackModel.swift */; }; D253BB9C245874F8002DE544 /* BGImageMolecule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D253BB9B245874F8002DE544 /* BGImageMolecule.swift */; }; D253BB9E2458751F002DE544 /* BGImageMoleculeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D253BB9D2458751F002DE544 /* BGImageMoleculeModel.swift */; }; @@ -656,7 +659,7 @@ D2092356244FA1EF0044AD09 /* ThreeLayerModelBase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerModelBase.swift; sourceTree = ""; }; D20923582450ECE00044AD09 /* TableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableView.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 = ""; }; + D20FB164241A5D75004AFC3A /* NavigationItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationItemModel.swift; sourceTree = ""; }; D213347623843825008E41B3 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = ""; }; D21B7F5E2437C5BC00051ABF /* MoleculeStackView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeStackView.swift; sourceTree = ""; }; D21B7F70243BAC1600051ABF /* CollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionViewCell.swift; sourceTree = ""; }; @@ -675,6 +678,9 @@ D236E5B3241FEB1000C38625 /* ListTwoColumnPriceDescriptionModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListTwoColumnPriceDescriptionModel.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 = ""; }; + D2509ED02472ED9B001BFB9D /* NavigationItemModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationItemModelProtocol.swift; sourceTree = ""; }; + D2509ED22472EDC8001BFB9D /* PanelNavigationItemModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PanelNavigationItemModelProtocol.swift; sourceTree = ""; }; + D2509ED52472EE2F001BFB9D /* NavigationItemButtonModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigationItemButtonModel.swift; sourceTree = ""; }; D253BB9B245874F8002DE544 /* BGImageMolecule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageMolecule.swift; sourceTree = ""; }; D253BB9D2458751F002DE544 /* BGImageMoleculeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageMoleculeModel.swift; sourceTree = ""; }; D256E9922412880000360572 /* Header.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Header.swift; sourceTree = ""; }; @@ -852,6 +858,8 @@ 011B58EF23A2AA980085F53C /* ListItemModelProtocol.swift */, D2E2A9A223E096B1000B42E6 /* DisableableModelProtocol.swift */, D2092354244FA0FD0044AD09 /* ThreeLayerTemplateModelProtocol.swift */, + D2509ED02472ED9B001BFB9D /* NavigationItemModelProtocol.swift */, + D2509ED22472EDC8001BFB9D /* PanelNavigationItemModelProtocol.swift */, ); path = ModelProtocols; sourceTree = ""; @@ -1313,6 +1321,15 @@ path = TwoColumn; sourceTree = ""; }; + D2509ED42472EE0B001BFB9D /* NavigationBar */ = { + isa = PBXGroup; + children = ( + D2509ED52472EE2F001BFB9D /* NavigationItemButtonModel.swift */, + D20FB164241A5D75004AFC3A /* NavigationItemModel.swift */, + ); + path = NavigationBar; + sourceTree = ""; + }; D253BB9A24587023002DE544 /* OtherContainers */ = { isa = PBXGroup; children = ( @@ -1453,6 +1470,7 @@ D29DF10E21E67A77003B2FB9 /* Molecules */ = { isa = PBXGroup; children = ( + D2509ED42472EE0B001BFB9D /* NavigationBar */, D253BB9A24587023002DE544 /* OtherContainers */, D22B38E923F4E07800490EF6 /* DesignedComponents */, D22479912316A9EF003FCCF9 /* Items */, @@ -1466,7 +1484,6 @@ 012A88EB238F084D00FE3DA1 /* FooterModel.swift */, D274CA322236A78900B01B62 /* FooterView.swift */, D260105723CF9CC500764D80 /* Doughnut */, - D20FB164241A5D75004AFC3A /* NavigationItemModelProtocol.swift */, ); path = Molecules; sourceTree = ""; @@ -1920,6 +1937,7 @@ 8D3BA9BF2433789900D341BA /* ListThreeColumnInternationalDataDivider.swift in Sources */, 94C661DA23CCF4FB00D9FE5B /* UIColor+Extension.swift in Sources */, D28A838123CCB0D800DFE4FC /* AccordionListItemModel.swift in Sources */, + D2509ED62472EE2F001BFB9D /* NavigationItemButtonModel.swift in Sources */, DBC4391822442197001AB423 /* CaretView.swift in Sources */, C07065C42395677300FBF997 /* Link.swift in Sources */, 0A69F611241BDEA700F7231B /* RuleAnyRequiredModel.swift in Sources */, @@ -2119,8 +2137,10 @@ 014AA72423C501E2006F3E93 /* MoleculeContainerModel.swift in Sources */, D29DF28321E7AB24003B2FB9 /* MVMCoreUICommonViewsUtility.m in Sources */, 011B58F223A2AE2C0085F53C /* DropDownListItemModel.swift in Sources */, + D2509ED12472ED9B001BFB9D /* NavigationItemModelProtocol.swift in Sources */, 8D448E5524050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift in Sources */, 94C2D9842386F3F80006CF46 /* LabelAttributeModel.swift in Sources */, + D2509ED32472EDC8001BFB9D /* PanelNavigationItemModelProtocol.swift in Sources */, 944589212385D6E900DE9FD4 /* DashLineModel.swift in Sources */, D2E2A99623D8CF85000B42E6 /* HeadlineBodyLinkToggleModel.swift in Sources */, C6FA7D5323C77A4A00A3614A /* StringAndMoleculeStack.swift in Sources */, @@ -2160,7 +2180,7 @@ D2E1FAE12268E81D00AEFD8C /* MoleculeListTemplate.swift in Sources */, 525019E72406853600EED91C /* ListFourColumnDataUsageDivider.swift in Sources */, 0AE98BB323FF0934004C5109 /* ExternalLinkModel.swift in Sources */, - D20FB165241A5D75004AFC3A /* NavigationItemModelProtocol.swift in Sources */, + D20FB165241A5D75004AFC3A /* NavigationItemModel.swift in Sources */, AA2AD118244EE48C00BBFFE3 /* ListDeviceComplexLinkMediumModel.swift in Sources */, DB06250B2293456500B72DD3 /* LeftRightLabelView.swift in Sources */, D224798A2314445E003FCCF9 /* LabelToggle.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Atoms/Views/Line.swift b/MVMCoreUI/Atomic/Atoms/Views/Line.swift index 62550503..d34aee06 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Line.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Line.swift @@ -55,6 +55,10 @@ import UIKit public convenience init(pinTo view: UIView, edge: UIRectEdge, useMargin: Bool) { self.init(frame: .zero) + addLine(to: view, edge: edge, useMargin: useMargin) + } + + open func addLine(to view: UIView, edge: UIRectEdge, useMargin: Bool) { view.addSubview(self) NSLayoutConstraint.activate(Array(NSLayoutConstraint.pinView(toSuperview: self, useMargins: useMargin, pinTop: edge != .bottom, pinBottom: edge != .top, pinLeft: edge != .right, pinRight: edge != .left).values)) } diff --git a/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemButtonModel.swift b/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemButtonModel.swift new file mode 100644 index 00000000..9110bfe9 --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemButtonModel.swift @@ -0,0 +1,35 @@ +// +// NavigationItemButtonModel.swift +// +// +// Created by Scott Pfeil on 5/18/20. +// + +import Foundation + +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) + } +} diff --git a/MVMCoreUI/Atomic/Molecules/NavigationItemModelProtocol.swift b/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift similarity index 70% rename from MVMCoreUI/Atomic/Molecules/NavigationItemModelProtocol.swift rename to MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift index f15a847a..50ae62d6 100644 --- a/MVMCoreUI/Atomic/Molecules/NavigationItemModelProtocol.swift +++ b/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift @@ -8,48 +8,7 @@ import Foundation -public protocol NavigationItemModelProtocol { - var title: String? { get set } - var hidden: Bool { get set } - var backgroundColor: Color? { get set } - var translucent: Bool { get set } - var tintColor: Color { get set } - var line: LineModel? { get set } - var showLeftPanelButton: Bool { get set } - var showRightPanelButton: Bool { get set } - var backButton: NavigationItemButtonModel? { get set } - var additionalLeftButtons: [NavigationItemButtonModel]? { get set } - var additionalRightButtons: [NavigationItemButtonModel]? { get set } -} - -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, MoleculeModelProtocol { +public class NavigationItemModel: NavigationItemModelProtocol, PanelNavigationItemModelProtocol, MoleculeModelProtocol { public class var identifier: String { return "navigationBar" } diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/NavigationItemModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/NavigationItemModelProtocol.swift new file mode 100644 index 00000000..634539d4 --- /dev/null +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/NavigationItemModelProtocol.swift @@ -0,0 +1,21 @@ +// +// NavigationItemModelProtocol.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 5/18/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public protocol NavigationItemModelProtocol { + var title: String? { get set } + var hidden: Bool { get set } + var backgroundColor: Color? { get set } + var translucent: Bool { get set } + var tintColor: Color { get set } + var line: LineModel? { get set } + var backButton: NavigationItemButtonModel? { get set } + var additionalLeftButtons: [NavigationItemButtonModel]? { get set } + var additionalRightButtons: [NavigationItemButtonModel]? { get set } +} diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/PanelNavigationItemModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/PanelNavigationItemModelProtocol.swift new file mode 100644 index 00000000..8f599be4 --- /dev/null +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/PanelNavigationItemModelProtocol.swift @@ -0,0 +1,14 @@ +// +// PanelNavigationItemModelProtocol.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 5/18/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public protocol PanelNavigationItemModelProtocol { + var showLeftPanelButton: Bool { get set } + var showRightPanelButton: Bool { get set } +} diff --git a/MVMCoreUI/BaseControllers/MVMControllerModelProtocol.swift b/MVMCoreUI/BaseControllers/MVMControllerModelProtocol.swift index 579a612e..d6851d78 100644 --- a/MVMCoreUI/BaseControllers/MVMControllerModelProtocol.swift +++ b/MVMCoreUI/BaseControllers/MVMControllerModelProtocol.swift @@ -5,6 +5,7 @@ // Created by Scott Pfeil on 3/16/20. // Copyright © 2020 Verizon Wireless. All rights reserved. // +// A convenience aggregate for common MVM templates. import Foundation diff --git a/MVMCoreUI/Containers/NavigationController.swift b/MVMCoreUI/Containers/NavigationController.swift index f278236c..3497075f 100644 --- a/MVMCoreUI/Containers/NavigationController.swift +++ b/MVMCoreUI/Containers/NavigationController.swift @@ -40,6 +40,7 @@ import UIKit return navigationController } + /// Convenience function for setting navigation bar with model. public static func set(navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol, viewController: UIViewController) { viewController.navigationItem.title = navigationItemModel.title viewController.navigationItem.accessibilityLabel = navigationItemModel.title @@ -54,13 +55,12 @@ import UIKit // 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?.setStyle(navigationItemModel.line?.type ?? .standard) + // Update line. + if let navigationController = navigationController as? NavigationController { + navigationController.separatorView?.setStyle(navigationItemModel.line?.type ?? .standard) } + // Update icons if main navigation controller. if navigationController == MVMCoreUISplitViewController.main()?.navigationController, navigationController.topViewController == viewController { // Update Panels diff --git a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.h b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.h index 0c252a08..e70a8b8b 100644 --- a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.h +++ b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.h @@ -124,8 +124,8 @@ typedef NS_ENUM(NSInteger, MFNumberOfDrawers) { - (nullable UIImage *)imageForBackButton; // Can overide to provide other global buttons to be on the navigation bar. -- (nullable NSArray *)additionalLeftButtons; -- (nullable NSArray *)additionalRightButtons; +- (nullable NSArray *)additionalLeftButtonsForViewController:(nonnull UIViewController *)viewController; +- (nullable NSArray *)additionalRightButtonsForViewController:(nonnull UIViewController *)viewController; // The width of the panel when it is permanently extended. Default 320. - (CGFloat)leftPanelExtendedWidth; diff --git a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m index e93ad613..f5c07d04 100644 --- a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m +++ b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m @@ -106,11 +106,16 @@ CGFloat const PanelAnimationDuration = 0.2; return (width > 2000 ? MFTwoDrawer : (width > 1000 ? MFOneDrawer : MFNoDrawer)); } -- (nullable NSArray *)additionalLeftButtons { +- (nullable NSArray *)additionalLeftButtonsForViewController:(nonnull UIViewController *)viewController { + if (![viewController conformsToProtocol:@protocol(MVMCoreViewControllerProtocol)]) { + return nil; + } + UIViewController *controller = (UIViewController *)viewController; + controller.page return nil; } -- (nullable NSArray *)additionalRightButtons { +- (nullable NSArray *)additionalRightButtonsForViewController:(nonnull UIViewController *)viewController { return nil; } @@ -239,7 +244,7 @@ CGFloat const PanelAnimationDuration = 0.2; if ((accessible && !extended) && self.leftPanelButton) { [leftBarButtonItems addObject:self.leftPanelButton]; } - NSArray *extraButtons = [self additionalLeftButtons]; + NSArray *extraButtons = [self additionalLeftButtonsForViewController:(nonnull UIViewController *)viewController]; if (extraButtons) { [leftBarButtonItems addObjectsFromArray:extraButtons]; } @@ -410,7 +415,7 @@ CGFloat const PanelAnimationDuration = 0.2; if ((accessible && !extended) && self.rightPanelButton) { [navigationItems addObject:self.rightPanelButton]; } - NSArray *extraButtons = [self additionalRightButtons]; + NSArray *extraButtons = [self additionalRightButtonsForViewController:(nonnull UIViewController *)viewController]; if (extraButtons) { [navigationItems addObjectsFromArray:extraButtons]; }