首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当我在Swift中将对象的委托设置为"self“时,编译器在做什么?

当我在Swift中将对象的委托设置为"self“时,编译器在做什么?
EN

Stack Overflow用户
提问于 2016-11-18 21:07:12
回答 3查看 199关注 0票数 2

在我的代码中,我有实现UITextFieldDelegateUITextFieldDelegateUIPickerViewDelegate

textFieldpickerView的委托分别通过textField.delegate = selfpickerView.delegate = self分配。

我理解两种协议的状态,因为它们都只接受与它们的委托相匹配的类型,但我不确定编译器如何区分这两种类型的UIPickerViewDelegateUITextFieldDelegate,因为这两个类都是协议。

当我将selftextField.delegate pickerView.delegate 设置为pickerView.delegate时,编译器究竟在做什么?编译器似乎很聪明,能够解决这个问题,但我很想知道幕后发生了什么。

例如:

代码语言:javascript
复制
class TextFieldViewController: UIViewController, UITextFieldDelegate,  UIPickerViewDelegate {

    @IBOutlet weak var textField: UITextField!
    @IBOutlet weak var pickerView: UIPickerView!

    override func viewDidLoad() {
        super.viewDidLoad()

        pickerView.delegate = self
        textField.delegate = self
    }

}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-11-19 11:33:54

当我设置textField.delegate时,编译器到底在做什么?

这个问题有两个答案:一个用于纯Swift类型,另一个用于Objective协议。

正如您的例子关于Objective(因为UITextFieldDelegate是一个Objective协议),我将首先回答这个问题。

目标C @protocol

编译器的工作不仅是生成代码,而且还要检查正确性。这样做的方法是确保分配给UITextFielddelegate属性的对象的静态类型与声明相匹配。在这种情况下,如果self的类型不符合UITextFieldDelegate,编译器就会抱怨。

这称为静态安全,是一个纯粹的编译时概念,不影响代码或运行时。

在稍后阶段,编译器必须生成执行实际赋值的代码。如果设置objc属性,它将查找setter名称(使用setDelegate:),并使用此选择器发出objc_msgSend调用。

魔法在这个函数中使向任何对象发送任意消息成为可能。因为这发生在运行时(术语是“后期绑定”或“动态分派”),编译器的工作就在此时完成。

当文本字段试图回调委托时,它使用相同的机制发送消息。它不需要知道任何关于委托类型的信息,而且它是一个object对象。

在使用@objc实例时,Objective和Swift代码都是如此。

纯Swift protocol

当委托是纯Swift协议(不是从NSObject协议派生的)时,一切都会发生变化。因为你的问题不是关于这个案子的,所以我不会说太多的细节。

在纯Swift中,没有后期绑定:方法的名称与其实现之间的连接是在编译时进行的(而在Objective中,这种连接发生在运行时)。

由于假设的纯Swift TextField中的委托属性必须有一种在委托中查找协议方法的方法,所以编译器为协议和静态类型创建一个所谓的见证表,并将其与实例一起存储。在调用委托中的方法时,编译器通过见证表路由调用以查找实际实现。在编译期间所做的工作比在Objective情况下做的要多得多。

如果您想了解更多关于Swift如何表示数据和调度方法的信息,那么就有一个2016 WWDC视频,它将详细介绍(下面是笔录)。

同时,我也非常推荐潜入快速ABI文档。有关存在主义容器布局的部分描述了纯Swift TextField将如何存储其delegate属性。

票数 3
EN

Stack Overflow用户

发布于 2016-11-18 21:50:54

你很困惑。

遵守协议就像说你会说一种语言。

一个人会说一种以上的语言。比如说我会说英语、法语和德语。我宣布自己符合英国、法国和德国的议定书。

然后,我可以将自己设置为任何对象的委托,这些对象的委托需要符合这些协议之一。

把这想成我是个电话接线员。电话系统知道我会说英语、法语和德语,所以它会把那些语言中的任何一种的客户的电话转接给我。

自我就是自我。在您的示例中,您定义了TextFieldViewController的代码。您可以告诉编译器,TextFieldViewController对象既符合UITextFieldDelegate协议也符合UIPickerViewDelegate协议。这意味着你会说两种“语言”

编译器在编译时所做的就是确保,当您说someUITextField.delegate = someObject时,someObject是一个符合文本字段所需的协议的对象,在本例中是UITextfieldDelegate.

如果您在情节提要中添加了一个UITableView,并试图将视图控制器连接为表视图的委托,而不符合UITableViewDelegate协议,编译器会抱怨,因为视图控制器没有说明它知道如何提供该角色。

由于TextFieldViewController类既符合UITextFieldDelegate协议又符合UIPickerViewDelegate协议,所以它可以是这两种类型对象的委托。视图控制器遵循六种不同的协议,并充当大量对象的委托,这并不少见。

编辑:

你问:

当我将textField.delegate设置为self,pickerView.delegate设置为self时,编译器到底在做什么?编译器似乎很聪明,可以搞清楚,但我很想知道幕后发生了什么

编译器检查文本字段的委托需要的对象类型。它了解到,对于文本字段的委托,它需要是一个符合UITexFieldDelegate协议的对象。

它查看等于符号( self )右侧的对象,验证self( TextFieldViewController类型的对象)是否符合UITextFieldDelegate协议。因此,它会将self安装到text字段的委托属性中。

然后,当文本字段需要向其委托发送消息时,它会向存储在委托属性中的对象发送一条消息。接收对象将传入的消息发送到其实现中的适当方法。

票数 3
EN

Stack Overflow用户

发布于 2016-11-19 12:22:15

委托是一个与对象连接的事物,它有不同的方法来处理这个对象。在您使用的任何类中,都可以重写这些方法。为了使该类能够包含这些方法,该类必须继承一个对象代理

如果要从代码中管理对象,则必须设置.delegate属性。它可以通过代码或故事板设置。此属性必须包含从该属性所有者对象的委托继承的类对象。因此,当您键入tratata.delegate = self时,您要将self类设置为该属性的对象。从那时起,您可以从代码中管理不同的视图。

委托还可以包含必须重写的必要方法。如果你看到一个错误“不符合协议”--这意味着你已经忘记了其中的一个。

祝好运!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40685940

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档