当您将 self 分配给 delegate 时到底发生了什么?

What exactly happens when you assign self to delegate?

我是 Swift 的新手,我很难理解将 self 分配给代理人的目的。部分困难源于委托似乎有两种不同的使用方式。

首先是作为在特定事件发生时从一个 class 向另一个发送消息的手段,几乎类似于状态管理。其次是使“class 或结构能够将其某些职责移交给(或委派)另一种类型的实例,”如 documentation 中所述。我有一种感觉,这两者在根本上是相同的,但我只是不明白。

protocol PersonProtocol {
    func getName() -> String
    func getAge() -> Int
}

class Person {
    var delegate: PersonProtocol?
    
    func printName() {
        if let del = delegate {
            print(del.getName())
        } else {
            print("The delegate property is not set")
        }
    }
    
    func printAge() {
        if let del = delegate {
            print(del.getAge())
        } else {
            print("The delegate property is not set")
        }
    }
}

class ViewController: UIViewController, PersonProtocol {
    var person: Person!
    
    override func viewDidLoad() {
        person.delegate = self
        
        person.printAge()
        person.printName()
    }
    
    func getAge() -> Int {
        print("view controller")
       return 99
    }
    
    func getName() -> String {
        return "Some name"
    }
}

在这种情况下 person.delegate = self 的目的是什么?如果没有它,ViewController 是否已经要求符合 PersonProtocol

如果您注意到在您的 Person class 内部,delegate 为 nil。如果你不执行 person.delegate = self,delegate 将保持为 nil。

换句话说,将 ViewController 赋值给 person.delegate 允许 Person 识别委托人是谁(即引用 ViewController),这样你就可以成功执行来自 Person class.

的 delegate?.getName() 或 delegate?.getAge() 之类的语句

I have a feeling that these two are fundamentally the same

第一个是第二个的特例。 “从一个 class 向另一个发送消息”只是“移交其部分职责”的一种特定方式。 “消息”就是“责任”

What is the purpose of person.delegate = self in this case?

在这里,person 将其部分职责委托(即放手)给另一个对象。它通过向另一个对象发送消息来做到这一点。首先,它需要确定可以将这些职责委派给哪些对象。这是通过要求其 delegate 符合 PersonProtocol 来实现的,因为 PersonProtocol 定义了 Person 将要发送的消息。

接下来,person 需要确切地 知道应该将这些消息发送到哪个对象。这就是 person.delegate = self 所做的。请记住,在此之前 person 对您的 ViewController 一无所知。你可以说:

而不是 = self
person.delegate = SomeOtherClassThatConformsToPersonProtocol()

person 会将其消息发送到该对象,并且不会调用 ViewController 中的方法。

Isn't ViewController already required to conform to PersonProtocol without it?

正确,但没有它,person 不知道应该将消息发送到哪个对象,因此,您的 ViewController 中的方法将不会被调用。


请注意,delegate 属性 应声明为 weak 以避免保留循环。当您执行 person.delegate = self 时,您会得到一个保留周期:selfperson 有强引用,person 也通过 [ 对 self 有强引用=13=] 属性.

这意味着 Person 无法 getName()getAge() 因此 Person class 将其委托给其他数据源。 假设您的视图控制器有一个数据源 class PersonDataSource 处理 API 以获取此信息 所以

class PersonDataSource: PersonProtocol { 
    func getAge() -> Int {
        print("view controller")
       return 99
    }
    
    func getName() -> String {
        return "Some name"
    }
 } 

所以视图控制器看起来像这样

class ViewController: UIViewController {
    var person: Person!
    var personDataSource = PersonDataSource()
    override func viewDidLoad() {
        person.delegate = personDataSource
        
        person.printAge()
        person.printName()
    }
}