Search code examples
iosuiviewcontrollercontainers

Calling parent controller's method from a child controller


I have a main controller A with a container that includes a child controller B, I need to invoke a method in controller A from my controller B, that's what I did to get my parent controller from B:

MainController = (WatchedViewTableViewController*)self.parentViewController.childViewControllers[1];

It worked fine at the beginning, but since my app allows other tabs to access this view controller as well, when it reaches certain hierarchy to this view controller from other tab, it results indexing the wrong MainController.

Since the app allows other tabs to redirect to this view controller as well, self.tabBarController.selectedViewController also doesn't work.

What should be the correct way to achieve it? Thanks.


Solution

  • Sounds like you need delegation Here are some links:

    The general idea is that you define a protocol. Then, you implement that protocol in your parent controller. You then have an instance of that protocol in your child controller that reference the parent controller:

        @protocol CustomMethodDelegate 
           -(void)doSomething
        @end
    
       //  Converted to Swift 5.1
       protocol CustomMethodDelegate: AnyObject {
        func doSomething()
       }
    

    Have your child controller contain a reference of that protocol to your parent view controller:

    @interface ChildViewController:UIViewController 
        @property (strong, nonatomic) id<CustomMethodDelegate> delegate;
    @end
    
    
    //  Converted to Swift 5.1
    class ChildViewController: UIViewController {
    var delegate: CustomMethodDelegate?
    

    }

    Then have your parent controller implement it:

        @interface ParentViewController:UIViewController<CustomMethodDelegate>
        @end
    
        //  Converted to Swift 5.1
       class ParentViewController: UIViewController, CustomMethodDelegate {
       }
    

    Implement doSomething in your Parent Controller: When you set it as a child view controller, set the child's delegate to parent controller

    @implementation ParentViewController
        -(void)creatingChildViewController {
            ChildViewController *controller = [self getNewChildViewController];
            controller.delegate = self;
        }
    
    #pragma mark - CustomMethodDelegate
    
        -(void)doSomething {
            NSLog(@"Something");
        }
    
    @end
    
    //  Converted to Swift 5.1
      @objc func openChildViewController() {
        guard let childViewCtrl = UIStoryboard(name: "YourMainStoryboard", 
        bundle: nil).instantiateViewController(withIdentifier: 
        "YourIdentifier") as? ChildViewController else { return }
        childViewCtrl.delegate = self
        self.present(childViewCtrl, animated: false, completion: nil)
    }
    
    // MARK: - CustomMethodDelegate
    
      func doSomething() {
        print("Something")
      }
    

    }

    And then in your child view controller you can called:

    [self.delegate doSomething];
    
     //  Converted to Swift 5.1
     delegate.doSomething()
    

    And that will call the doSomething method in your parent controller.