如何在Swift中正确使用委托?

时间:2021-05-11 20:54:59

I read a lot about the delegates but in practice I cannot use it properly.

我读了很多关于代表的内容,但在实践中我无法正确使用它。

Description: I have A: UIViewController, B: UIView, C: UIViewController. I want to run segue from A: UIViewController to the C: UIViewController from the inside of B: UIView.

描述:我有一个:UIViewController,B:UIView,C:UIViewController。我想从A:UIViewController中运行segue到B:UIView里面的C:UIViewController。

I've tried:

protocol SegueDelegate {
    func runSegue(identifier: String)
}

class B: UIView { ... }

where in my A: UIViewController:

在我的A:UIViewController:

override func viewDidLoad() {
    B().delegate = self
}

func runSegue(identifier: String) {
    self.performSegueWithIdentifier(identifier, sender: self)
}

and trying to call it via:

并尝试通过以下方式调用它:

@IBAction func send(sender: AnyObject) {
    let a: SegueDelegate? = nil
    a!.runSegue("goToMainPage")
}

but I'm sure that I do not use it properly. Can anyone help me with it? I do not want just an answer. Please describe me it concept shortly

但我确定我没有正确使用它。任何人都可以帮助我吗?我不想只是一个答案。请尽快向我描述一下这个概念

2 个解决方案

#1


1  

Delegates are just a Design Pattern that you can use in a number of ways. You can look at the Apple Frameworks to see how and where to use delegates as examples. A table view delegate is probably the best known delegate in UIKit.

代表只是一种可以通过多种方式使用的设计模式。您可以查看Apple框架以查看如何以及在何处使用委托作为示例。表视图委托可能是UIKit中最知名的委托。

Delegates serve as a callback mechanism for code to communicate with an instance of an unknown class without knowing more than that that instance will respond to the methods of the delegate protocol.

委托充当代码的回调机制,以便与未知类的实例进行通信,而不需要知道该实例将响应委托协议的方法。

An alternative to a delegate is to use a closure (what we used to call a block in Objective-C). When to use one vs. the other is a matter of taste. There are a couple of rules of thumb, like for instance outlined here.

委托的替代方法是使用闭包(我们在Objective-C中用来调用块)。何时使用一个与另一个是一个品味问题。有几条经验法则,例如这里概述的。

What you are doing is, IMO, the proper way to use delegates. You separate the view functionality from the View Controller's functionalities via a delegate, and so the contract for your view is clear: the user needs to respond to the delegate method.

你正在做的是,IMO,使用代表的正确方法。您通过委托将视图功能与View Controller的功能分开,因此您的视图合同是明确的:用户需要响应委托方法。

Your code works and is correct. I made a quick implementation here: https://github.com/kristofvanlandschoot/DelegateUsage/tree/master

您的代码有效且正确无误。我在这里快速实现了:https://github.com/kristofvanlandschoot/DelegateUsage/tree/master

The main difference from your example, and maybe that's the place where you made a mistake is the third part of your code where you should write something like:

与您的示例的主要区别,也许这是您犯错误的地方是代码的第三部分,您应该写下这样的内容:

@IBAction func send(sender: AnyObject) {
    delegate?.runSegue("segueAB")
}

#2


0  

There are multiple errors in your code, for example:

您的代码中存在多个错误,例如:

Here you are creating a new B, and setting A as a delegate of that new instance, no the one you actually want

在这里,您将创建一个新的B,并将A设置为该新实例的委托,而不是您真正想要的那个

override func viewDidLoad() {
    «B()».delegate = self
}

And here you are creating force unwrapping a nil value

在这里,你正在创造一个展开零值的力量

@IBAction func send(sender: AnyObject) {
    let a: SegueDelegate? = «nil»
    «a!».runSegue("goToMainPage")
}

If what you want to do is tell A to perform a segue to C, from inside B, all you need to do is to call performSegueWithIdentifier on A

如果您要做的是告诉A从C内部执行segue到C,您需要做的就是在A上调用performSegueWithIdentifier

For example:

class B: UIView {
    weak var referenceToA: UIViewController? = nil // set this somewhere
    @IBAction func send(sender: AnyObject) {
        guard let a = referenceToA else {
            fatalError("you didn't set the reference to a view controller of class A")
        }
        a.performSegueWithIdentifier("goToMainPage", sender: self)
    }
}

#1


1  

Delegates are just a Design Pattern that you can use in a number of ways. You can look at the Apple Frameworks to see how and where to use delegates as examples. A table view delegate is probably the best known delegate in UIKit.

代表只是一种可以通过多种方式使用的设计模式。您可以查看Apple框架以查看如何以及在何处使用委托作为示例。表视图委托可能是UIKit中最知名的委托。

Delegates serve as a callback mechanism for code to communicate with an instance of an unknown class without knowing more than that that instance will respond to the methods of the delegate protocol.

委托充当代码的回调机制,以便与未知类的实例进行通信,而不需要知道该实例将响应委托协议的方法。

An alternative to a delegate is to use a closure (what we used to call a block in Objective-C). When to use one vs. the other is a matter of taste. There are a couple of rules of thumb, like for instance outlined here.

委托的替代方法是使用闭包(我们在Objective-C中用来调用块)。何时使用一个与另一个是一个品味问题。有几条经验法则,例如这里概述的。

What you are doing is, IMO, the proper way to use delegates. You separate the view functionality from the View Controller's functionalities via a delegate, and so the contract for your view is clear: the user needs to respond to the delegate method.

你正在做的是,IMO,使用代表的正确方法。您通过委托将视图功能与View Controller的功能分开,因此您的视图合同是明确的:用户需要响应委托方法。

Your code works and is correct. I made a quick implementation here: https://github.com/kristofvanlandschoot/DelegateUsage/tree/master

您的代码有效且正确无误。我在这里快速实现了:https://github.com/kristofvanlandschoot/DelegateUsage/tree/master

The main difference from your example, and maybe that's the place where you made a mistake is the third part of your code where you should write something like:

与您的示例的主要区别,也许这是您犯错误的地方是代码的第三部分,您应该写下这样的内容:

@IBAction func send(sender: AnyObject) {
    delegate?.runSegue("segueAB")
}

#2


0  

There are multiple errors in your code, for example:

您的代码中存在多个错误,例如:

Here you are creating a new B, and setting A as a delegate of that new instance, no the one you actually want

在这里,您将创建一个新的B,并将A设置为该新实例的委托,而不是您真正想要的那个

override func viewDidLoad() {
    «B()».delegate = self
}

And here you are creating force unwrapping a nil value

在这里,你正在创造一个展开零值的力量

@IBAction func send(sender: AnyObject) {
    let a: SegueDelegate? = «nil»
    «a!».runSegue("goToMainPage")
}

If what you want to do is tell A to perform a segue to C, from inside B, all you need to do is to call performSegueWithIdentifier on A

如果您要做的是告诉A从C内部执行segue到C,您需要做的就是在A上调用performSegueWithIdentifier

For example:

class B: UIView {
    weak var referenceToA: UIViewController? = nil // set this somewhere
    @IBAction func send(sender: AnyObject) {
        guard let a = referenceToA else {
            fatalError("you didn't set the reference to a view controller of class A")
        }
        a.performSegueWithIdentifier("goToMainPage", sender: self)
    }
}