swift 3 call function from parent ViewController

时光总嘲笑我的痴心妄想 提交于 2021-02-08 07:38:34

问题


I have a ViewController, this view container has a class which creates 2 container views, and adds a table to the first container and a HashtagPicker for the second.

The hashTagPicker has a function which is called whenever a change to the selected hashTags happens.

question: i want to call a update table function whenever a tag is changed. How can i call a function from the hashtagclass which is defined in the class that contains the containers?


回答1:


I personally like the delegate approach over notifications - the latter solution almost always leads to confusing architecture. Sadly, the example for the delegate approach, which is also the accepted answer, is even worse - it basically opens an opportunity for memory leaks. I'll explain. In the accepted solution, ParentView is holding a strong reference to HashtagPicker and, in turn, HastagPicker is holding a strong reference to ParentView, this creates a retain cycle and means neither of the controllers will be picked up by ARC and be deinitialized. So, if you are, for example, presenting ParentView from some other view and you keep going to ParentView and back, you will keep spawning new instances of ParentView (and HashtagPicker) with old ones still occupying memory.

Now, how this should have been done. I'll use exactly the same names as in the accepted answer.

The protocol should be defined like so:

// note the ": class" part
protocol HashTagPickerDelegate: class {
  func picked(hashtag: String)
}

If we specify class, it means the protocol can only be used on classes. This will allow use to create weak reference, which otherwise would have been impossible.

class HashtagPicker: UIViewController {
  // if HashTagPickerDelegate wouldn't be limited to class, 
  // we couldn't have made a weak reference here!
  weak var delegate: HashTagPickerDelegate?

  // at some point, you call the delegate, it can be anywhere, this is just an example
  @IBAction func tappedHashtag(_ sender: Any) {
    delegate?.picked(hashtag: "bla")
  }
}

Now we have a weak reference to delegate, so there is not retain cycle and ARC can clean up everything nicely!

I'll throw in the rest of the code to have this as a complete answer:

class ParentView: UIViewController {
  func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    // we are presenting the nested controller
    if segue.identifier == "SegueHastagPickerContainer",
       let destinationController = segue.destination as? HashtagPicker {
      destinationController.delegate = self
    } 
  }
}

extension ParentView: HashTagPickerDelegate {
  func picked(hashtag: String) {
    // we just got info from the child controller, do something with it!
  }
}



回答2:


You can use delegates as mentioned in above answer. Or you can use notifications. So here is a solution using notifications.

First of all register a notification in your parent viewController's viewDidLoad like this

NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ParentViewController.someActionToBePerformed), name: "myNotification", object: nil)

Create a function in your parent viewController named same as above so it will be like

func someActionToBePerformed () {
    // this will be called when hashTag is changed
    // do something when hashTag is changed 
}

Now you can simply post notification from your Hashtag viewController. When you want like this.

NotificationCenter.default.post(name: NSNotification.Name(rawValue: "myNotification"), object: nil)



回答3:


You can use this (no notification, no delegate)

 func exitButtonTapped() {
    if let pdfVC : YourParnetViewController = self.parent as? YourParnetViewController {
        pdfVC.removeBlurEffect()
        self.removeFromParentViewController()
        self.view.removeFromSuperview()
    }
}


来源:https://stackoverflow.com/questions/40715210/swift-3-call-function-from-parent-viewcontroller

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!