swift 3 从父级调用函数 ViewController
swift 3 call function from parent ViewController
我有一个 ViewController,这个视图容器有一个 class,它创建了 2 个容器视图,并为第一个容器添加了一个 table,为第二个容器添加了一个 HashtagPicker。
hashTagPicker 有一个函数,只要选定的 hashTag 发生更改,就会调用该函数。
问题:我想在标签更改时调用更新table函数。我如何从包含容器的 class 中定义的主题标签 class 调用函数?
您可以使用上述答案中提到的委托。或者您可以使用通知。所以这是一个使用通知的解决方案。
首先在你的 parent viewController 的 viewDidLoad
中注册一个通知,像这样
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ParentViewController.someActionToBePerformed), name: "myNotification", object: nil)
在您的 parent viewController 中创建一个与上面名称相同的函数,这样它就会像
func someActionToBePerformed () {
// this will be called when hashTag is changed
// do something when hashTag is changed
}
现在您可以简单地从您的标签 viewController
post 通知。当你想要这样的时候。
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "myNotification"), object: nil)
我个人更喜欢委托方法而不是通知 - 后一种解决方案几乎总是会导致架构混乱。可悲的是,委托方法的示例(也是公认的答案)甚至更糟——它基本上为内存泄漏提供了机会。我会解释。在公认的解决方案中,ParentView
持有对 HashtagPicker
的强引用,反过来,HastagPicker
持有对 ParentView
的强引用,这会创建一个保留循环并意味着这两个控制器都不会被 ARC 拾取并被取消初始化。因此,例如,如果您从其他视图呈现 ParentView
并且您继续前往 ParentView
并返回,您将不断产生 ParentView
的新实例(和 HashtagPicker
) 旧的还在占用内存。
现在,这应该如何完成。我将使用与接受的答案中完全相同的名称。
协议应该这样定义:
// note the ": class" part
protocol HashTagPickerDelegate: class {
func picked(hashtag: String)
}
如果我们指定class
,则意味着该协议只能在类上使用。这将允许使用创建弱引用,否则这是不可能的。
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")
}
}
现在我们有一个对委托的弱引用,所以没有保留周期,ARC 可以很好地清理一切!
我将把其余的代码放入其中作为完整答案:
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!
}
}
你可以使用这个(没有通知,没有委托)
func exitButtonTapped() {
if let pdfVC : YourParnetViewController = self.parent as? YourParnetViewController {
pdfVC.removeBlurEffect()
self.removeFromParentViewController()
self.view.removeFromSuperview()
}
}
我有一个 ViewController,这个视图容器有一个 class,它创建了 2 个容器视图,并为第一个容器添加了一个 table,为第二个容器添加了一个 HashtagPicker。
hashTagPicker 有一个函数,只要选定的 hashTag 发生更改,就会调用该函数。
问题:我想在标签更改时调用更新table函数。我如何从包含容器的 class 中定义的主题标签 class 调用函数?
您可以使用上述答案中提到的委托。或者您可以使用通知。所以这是一个使用通知的解决方案。
首先在你的 parent viewController 的 viewDidLoad
中注册一个通知,像这样
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ParentViewController.someActionToBePerformed), name: "myNotification", object: nil)
在您的 parent viewController 中创建一个与上面名称相同的函数,这样它就会像
func someActionToBePerformed () {
// this will be called when hashTag is changed
// do something when hashTag is changed
}
现在您可以简单地从您的标签 viewController
post 通知。当你想要这样的时候。
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "myNotification"), object: nil)
我个人更喜欢委托方法而不是通知 - 后一种解决方案几乎总是会导致架构混乱。可悲的是,委托方法的示例(也是公认的答案)甚至更糟——它基本上为内存泄漏提供了机会。我会解释。在公认的解决方案中,ParentView
持有对 HashtagPicker
的强引用,反过来,HastagPicker
持有对 ParentView
的强引用,这会创建一个保留循环并意味着这两个控制器都不会被 ARC 拾取并被取消初始化。因此,例如,如果您从其他视图呈现 ParentView
并且您继续前往 ParentView
并返回,您将不断产生 ParentView
的新实例(和 HashtagPicker
) 旧的还在占用内存。
现在,这应该如何完成。我将使用与接受的答案中完全相同的名称。
协议应该这样定义:
// note the ": class" part
protocol HashTagPickerDelegate: class {
func picked(hashtag: String)
}
如果我们指定class
,则意味着该协议只能在类上使用。这将允许使用创建弱引用,否则这是不可能的。
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")
}
}
现在我们有一个对委托的弱引用,所以没有保留周期,ARC 可以很好地清理一切!
我将把其余的代码放入其中作为完整答案:
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!
}
}
你可以使用这个(没有通知,没有委托)
func exitButtonTapped() {
if let pdfVC : YourParnetViewController = self.parent as? YourParnetViewController {
pdfVC.removeBlurEffect()
self.removeFromParentViewController()
self.view.removeFromSuperview()
}
}