1. cayozin

    Posted

    cayozin
Changes in title
+iOS Avoid duplicate view controllers with custom NavigationController
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,50 @@
+It is possible that duplicate view controllers may be accidently instantiated by the user. This is particularly a risk if the segue to a new view controller follows the response and processing of a REST request.
+
+If the view controllers are managed by a UINavigationController, we can modify its behaviour to avoid duplicate view controllers. This method assumes that only one View Controller of each class is allowed at one time.
+
+First, we provide a identifier for each Object (and therefore View Controller) based on its class.
+
+```swift
+extension NSObject {
+ var className: String {
+ get {
+ return NSStringFromClass(type(of: self))
+ }
+ }
+}
+```
+
+Then we subclass UINavigationController and override pushViewController; this method will now permit a new view controller to be added if it does not already exist and a new view controller is not already being added.
+
+```swift
+class CustomNavigationController: UINavigationController {
+
+ var isNewViewControllerBeingAdded: Bool = false
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ self.delegate = self
+ }
+
+ func contains(viewController: UIViewController) -> Bool {
+ return self.viewControllers.map{ $0.className }.contains(viewController.className)
+ }
+
+ override func pushViewController(_ viewController: UIViewController, animated: Bool) {
+ if(!self.isNewViewControllerBeingAdded && !self.contains(viewController: viewController)) {
+ self.isNewViewControllerBeingAdded = true
+ super.pushViewController(viewController, animated: animated)
+ }
+ }
+}
+```
+
+We also extend this subclass with a delegate handler, which modifies the "isNewViewControllerBeingAdded" flag upon successful addition of a view controller.
+
+```swift
+extension CustomNavigationController: UINavigationControllerDelegate {
+ func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
+ self.isNewViewControllerBeingAdded = false
+ }
+}
+```