I was trying to pass around variables between views in Swift, and ran into the rather abstract concept of protocols and delegates.
我试图在Swift的视图之间传递变量,并遇到了相当抽象的协议和委托概念。
Then I tried storing a reference to the first view in a second view and call functions on that directly. This seems to work:
然后,我尝试在第二个视图中存储对第一个视图的引用,并直接调用该视图上的函数。这似乎工作:
SCREEN 1
屏幕1
class Screen1: UIViewController {
var myName = "Screen1"
override func viewDidLoad() {
super.viewDidLoad()
}
//
// checking if the segue to screen 2 is called and then passing a reference
//
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if segue.identifier == "screen2Segue"{
let vc = segue.destinationViewController as Screen2
vc.storedReference = self
}
}
func getName() -> String {
return myName
}
}
SCREEN 2
屏幕2
class Screen2: UIViewController {
var storedReference:Screen1!
override func viewDidLoad() {
super.viewDidLoad()
}
func testReference() {
// calling a function on the stored reference to screen 1
var str = storedReference.getName()
println("Leaving screen 2, going to " + str)
}
}
My question: what's wrong with this code? Why use delegates and protocols if you can just pass around a reference directly?
我的问题是:这个代码有什么问题?如果可以直接传递引用,为什么要使用委托和协议呢?
Perhaps related: when does a view get un-initialized and replaced by an entirely new view instance? Am I calling 'getName()' on an old instance?
也许相关:什么时候视图未初始化并被一个全新的视图实例所取代?我是否在旧实例上调用getName() ?
4 个解决方案
#1
10
Protocols are useful for separating implementation from interface, which helps increase code reusability, understandability, and testability.
协议对于将实现与接口分离非常有用,这有助于提高代码的可重用性、可理解性和可测试性。
For example, perhaps you wish to store items in a List of some sort. Some possible implementations of a List include array-based implementations and node-based (linked-list) implementations. If you were to declare a protocol called List
and have classes ArrayList
and LinkedList
that implemented that protocol, anything that required the use of a list (variable passed as a parameter to a method, a property, etc) could use List
as the variable type, and be able to function without caring about whether a the list was an ArrayList
or a LinkedList
. You could change which type was used, or how they were implemented, and it would not matter to whatever was using them, because only the exposed interface declared in the protocol would be visible.
例如,您可能希望将项目存储在某种列表中。列表的一些可能实现包括基于数组的实现和基于节点的(链接列表)实现。如果你声明一个协议称为列表和ArrayList类和链表,实现协议,任何需要使用列表(变量作为参数传递给一个方法,一个属性,等等)可以使用作为变量类型列表,并能够函数不关心是否列表是一个ArrayList或LinkedList。您可以更改使用了哪种类型,或者它们是如何实现的,这与使用它们的内容无关,因为只有协议中声明的公开接口是可见的。
Protocols can also be useful for emulating something like multiple inheritance, as a class can inherit from a superclass, as well as implement one or more interfaces. (eg. A bat is both a mammal and winged, so it could be represented as a Bat
class inheriting from a Mammal
class that implements the Winged
protocol).
协议对于模拟多继承也很有用,因为类可以从超类继承,也可以实现一个或多个接口。(如。蝙蝠既是哺乳动物又是有翅的,因此它可以被表示为蝙蝠类,继承了实现有翅协议的哺乳动物类)。
The delegate pattern uses protocols to delegate some responsibilities to another object, which is especially good for code separation and reusability. For example, the UITableViewDelegate
protocol in iOS allows a UITableView
to react to things like cell selection by delegating another object to handle the event. This has probably been used by millions of objects in thousands of applications, without the developers at Apple who implemented UITableView
and UITableViewDelegate
having ever known anything about the objects that were implementing the protocol.
委托模式使用协议将某些职责委托给另一个对象,这对于代码分离和重用尤其有用。例如,iOS中的UITableViewDelegate协议允许UITableView通过委托另一个对象来处理事件来对单元格选择之类的事情做出反应。在成千上万的应用程序中,这可能已经被数以百万计的对象所使用,而苹果公司的开发人员实现了UITableView和UITableViewDelegate,他们对实现协议的对象一无所知。
By directly passing a reference between your view controllers, you are forcing the second to be completely dependent upon the first. If you ever wished to change the flow of your application so that the second view controller could be accessed from somewhere else, you would be forced to rewrite that view controller to use the new origin. If you use a protocol instead, no changes to the second view controller would have to be made.
通过在视图控制器之间直接传递引用,您将强制第二个视图完全依赖于第一个视图控制器。如果您希望更改应用程序的流,以便可以从其他地方访问第二个视图控制器,您将*重写该视图控制器以使用新的起点。如果您使用的是协议,则不需要对第二个视图控制器进行任何更改。
#2
4
It is a basic design principle to not expose any more of a design than you have to. By passing the reference around you are exposing the whole object. Which means that others can call any of its functions and access any of its properties. And change them. This isn't good. Besides letting others use the object in ways it might not have intended, you will also run into issues if you try to change the object in the future and find out that it breaks somebody else who was using something you didn't intend. So, always a good idea to not expose anything that you don't have to. This is the purpose of delegates and protocols. It gives the object complete control over what is exposed. Much safer. Better design.
这是一个基本的设计原则,不公开更多的设计。通过传递引用,您将暴露整个对象。这意味着其他人可以调用它的任何函数并访问它的任何属性。和改变他们。这不是很好。除了让其他人以它可能不打算使用的方式使用这个对象之外,如果您试图在未来更改这个对象并发现它破坏了正在使用您不打算使用的东西的其他人,那么您还将遇到问题。所以,最好不要暴露任何不必要的东西。这是委托和协议的目的。它使对象能够完全控制公开的内容。更安全。更好的设计。
#3
3
I think you didn't fully get the understanding what protocols are.
我想你还没有完全理解什么是协议。
I always say protocols are like contracts.
The delegate object that implements a certain protocols promises that it can do things the delegator can't do.
我总是说协议就像契约。实现特定协议的委托对象承诺它可以做委托者不能做的事情。
In real world I have a problem with my house's tubes.
I (the delegator) call a plumber (the delegate) to fix it. The plumber promises (by contract) to be able to duo it. The promise is the protocol. I don't care how he do it, as long as he does it.
在现实生活中,我对我家的管道有问题。我(代表)叫一个水管工(代表)来修理它。管道工(按合同)保证能把它修好。承诺就是协议。我不在乎他怎么做,只要他做就行。
But these contracts are not only useful for delegation.
I am just writing a food ordering app. As it has a menu it need item to display in it.
I could go with basic inheritance and write a class MenuItem, that all sub classes must inherit from.
Or I write an protocol to express: «No matter what object you are, as long as you fulfill this contract we have a deal». this allows me to create many different classes or annotate existing classes in categories, although I don't have the tool of multiple inheritance.
但这些合同不仅对授权有用。我正在写一款订餐app,因为它有菜单,所以需要在里面显示。我可以使用基本继承和编写类MenuItem,所有子类都必须继承。或者我写一个协议来表达:“无论你是什么对象,只要你履行这个合同,我们就会达成协议。”这允许我创建许多不同的类,或者在类别中注释现有的类,尽管我没有多重继承的工具。
Actually I do both: I write a protocol MenuItem
and a class MenuItem
that conforms to the protocol. Now I can use simple inheritance or use classes that do not inherit from the class MenuItem
.
实际上我两者都做:我编写一个协议MenuItem和一个符合协议的类MenuItem。现在,我可以使用简单的继承或使用不从MenuItem类继承的类。
Code in Objective-C (sorry: I am still transitioning to Swift)
Objective-C中的代码(抱歉:我还在向Swift转换)
@protocol MenuItem <NSObject>
-(NSString *)name;
-(double) price;
-(UIColor *)itemColor;
@end
@interface MenuItem : NSObject <MenuItem>
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) double price;
@property (nonatomic, strong) UIColor *itemColor;
@end
#import "MenuItem.h"
@implementation MenuItem
-(id)initWithCoder:(NSCoder *)decoder
{
self = [super init];
if (self) {
self.name = [decoder decodeObjectForKey:@"name"];
self.price = [decoder decodeDoubleForKey:@"price"];
self.itemColor = [decoder decodeObjectForKey:@"itemColor"];
}
return self;
}
-(void)encodeWithCoder:(NSCoder *)encoder
{
[encoder encodeDouble:self.price forKey:@"price"];
[encoder encodeObject:self.name forKey:@"name"];
[encoder encodeObject:self.itemColor forKey:@"itemColor"];
}
@end
Apple uses the same Architecture for NSObject: there is a protocol and a class NSObject
. This allows classes, that aren't intact inheriting from the class NSObject
to act ash an NSObject. One famous example:NSProxy
.
苹果对NSObject使用相同的架构:有一个协议和一个类NSObject。这允许不完整地继承类NSObject以执行NSObject的类。一个著名的例子:NSProxy。
in your case Screen1 promises to be able to understand messages that are send by the detail view controller Screen2. These allows decoupling: any object that does understand Screen1's protocol can be used. Also it helps to maintain a sane object tree, as we don't have to have circular imports. But in general you have to keep in mind that the delegator (Screen2) must keep a weak reference to it's delegate, otherwise we have a retain circle.
在您的例子中,Screen1保证能够理解由detail视图控制器Screen2发送的消息。这些允许解耦:任何理解Screen1的对象都可以使用。它还有助于维护一个正常的对象树,因为我们不必使用循环导入。但一般来说,你必须记住,委派者(Screen2)必须对它的委派保持弱引用,否则我们就会有一个保留循环。
Of course an important example it UITableView:
The table view object knows everything about rendering it's cells, handling scrolling and so one. But the engineer who wrote it couldn't now how you want your table view look like. That's why he introduced a delegate to give you the chance to create the right cell. As he couldn't also know what your data looks like, he also introduced the datasource - that works exactly like a delegate: you will be asked to provide all information about your data, that are needed.
当然,它UITableView的一个重要示例是:表视图对象知道如何渲染它的单元格、处理滚动等等。但是,编写它的工程师现在不可能希望您的表视图是什么样子的。这就是为什么他引入了一个委托,让您有机会创建正确的单元格。由于他也不知道您的数据是什么样子,他还介绍了数据源——它的工作方式与委托完全一样:您将被要求提供有关您的数据的所有信息,这是必需的。
#4
2
This is mostly a matter of opinion so this question should probably be closed, but I think the developer community as a whole is in an agreement on this so I am going to answer it anyway.
这主要是一个观点问题,所以这个问题应该结束了,但是我认为整个开发者社区都同意这个问题,所以我还是要回答这个问题。
An important concept in Software Architecture (the design of the structure of code) is called Separation of Concerns. The basic principle is that you should break down what your code has to do into small components that only have one distinct purpose. Each of these components should be able to stand mostly on their own without much concern with other components other than the ones it needs to directly be interacting with.
软件架构中的一个重要概念(代码结构的设计)称为关注点分离。基本原则是,您应该将代码要做的工作分解成只有一个不同目的的小组件。这些组件中的每一个都应该能够独立运行,而不需要与其他组件进行过多的关注,而只需与其他组件进行直接交互。
This helps greatly with code reuse. If you design a small component that is independent of most / if not all other components, you can easily plug that into other parts of your code or other applications. Take UITableView for example. By using the delegate pattern, every developer can easily create a table view and populate it with whatever data they want. Since that data source is a separate object (with the separate concern of coming up with the data) you can attach that same data source to multiple table views. Think of a contact list on iOS. You will want to access that same data in many ways. Instead of always rewriting a table view that loads the specific data and displays it in a specific way, you can reuse the data source with a different table view as many times as you want.
这极大地帮助了代码重用。如果您设计一个独立于大多数/如果不是所有其他组件的小组件,您可以轻松地将其插入代码或其他应用程序的其他部分。以UITableView为例。通过使用委托模式,每个开发人员都可以轻松地创建一个表视图,并用他们想要的任何数据填充它。由于数据源是一个单独的对象(考虑到生成数据的问题),所以可以将相同的数据源附加到多个表视图。想想iOS上的联系人列表。您将希望以多种方式访问相同的数据。不要总是重写一个装载特定数据并以特定方式显示它的表视图,您可以使用不同的表视图重用数据源。
This also helps with the understandability of your code. It is tough for developers to keep too many thing in their head about the state of your app. If each of your code components are broken down into small, well defined responsibilities, a developer can understand each component separately. They can also look at a component, and make accurate assumptions about what it does without having to look at the specific implementation. This isn't such a big deal with small apps, but as code bases grow, this becomes very important.
这也有助于代码的可理解性。对于开发人员来说,要记住太多关于应用程序状态的东西是很困难的。如果您的每个代码组件被分解成小的、定义良好的职责,那么开发人员可以分别理解每个组件。他们还可以查看组件,并对其功能做出准确的假设,而不必查看特定的实现。对于小型应用程序来说,这并不是什么大问题,但随着代码库的增长,这一点变得非常重要。
By passing in a reference to your first view controller, you are making your second view controller completely dependent on the first. You cannot reuse the second view controller in another instance and its job becomes less clear.
通过传递对第一个视图控制器的引用,您正在使第二个视图控制器完全依赖于第一个视图控制器。您不能在另一个实例中重用第二个视图控制器,其工作也变得不那么清晰。
There are lots of other benefits to separation of concerns but I believe those are two compelling and important ones.
分离关注点还有很多其他好处,但我认为这是两个引人注目的重要好处。
#1
10
Protocols are useful for separating implementation from interface, which helps increase code reusability, understandability, and testability.
协议对于将实现与接口分离非常有用,这有助于提高代码的可重用性、可理解性和可测试性。
For example, perhaps you wish to store items in a List of some sort. Some possible implementations of a List include array-based implementations and node-based (linked-list) implementations. If you were to declare a protocol called List
and have classes ArrayList
and LinkedList
that implemented that protocol, anything that required the use of a list (variable passed as a parameter to a method, a property, etc) could use List
as the variable type, and be able to function without caring about whether a the list was an ArrayList
or a LinkedList
. You could change which type was used, or how they were implemented, and it would not matter to whatever was using them, because only the exposed interface declared in the protocol would be visible.
例如,您可能希望将项目存储在某种列表中。列表的一些可能实现包括基于数组的实现和基于节点的(链接列表)实现。如果你声明一个协议称为列表和ArrayList类和链表,实现协议,任何需要使用列表(变量作为参数传递给一个方法,一个属性,等等)可以使用作为变量类型列表,并能够函数不关心是否列表是一个ArrayList或LinkedList。您可以更改使用了哪种类型,或者它们是如何实现的,这与使用它们的内容无关,因为只有协议中声明的公开接口是可见的。
Protocols can also be useful for emulating something like multiple inheritance, as a class can inherit from a superclass, as well as implement one or more interfaces. (eg. A bat is both a mammal and winged, so it could be represented as a Bat
class inheriting from a Mammal
class that implements the Winged
protocol).
协议对于模拟多继承也很有用,因为类可以从超类继承,也可以实现一个或多个接口。(如。蝙蝠既是哺乳动物又是有翅的,因此它可以被表示为蝙蝠类,继承了实现有翅协议的哺乳动物类)。
The delegate pattern uses protocols to delegate some responsibilities to another object, which is especially good for code separation and reusability. For example, the UITableViewDelegate
protocol in iOS allows a UITableView
to react to things like cell selection by delegating another object to handle the event. This has probably been used by millions of objects in thousands of applications, without the developers at Apple who implemented UITableView
and UITableViewDelegate
having ever known anything about the objects that were implementing the protocol.
委托模式使用协议将某些职责委托给另一个对象,这对于代码分离和重用尤其有用。例如,iOS中的UITableViewDelegate协议允许UITableView通过委托另一个对象来处理事件来对单元格选择之类的事情做出反应。在成千上万的应用程序中,这可能已经被数以百万计的对象所使用,而苹果公司的开发人员实现了UITableView和UITableViewDelegate,他们对实现协议的对象一无所知。
By directly passing a reference between your view controllers, you are forcing the second to be completely dependent upon the first. If you ever wished to change the flow of your application so that the second view controller could be accessed from somewhere else, you would be forced to rewrite that view controller to use the new origin. If you use a protocol instead, no changes to the second view controller would have to be made.
通过在视图控制器之间直接传递引用,您将强制第二个视图完全依赖于第一个视图控制器。如果您希望更改应用程序的流,以便可以从其他地方访问第二个视图控制器,您将*重写该视图控制器以使用新的起点。如果您使用的是协议,则不需要对第二个视图控制器进行任何更改。
#2
4
It is a basic design principle to not expose any more of a design than you have to. By passing the reference around you are exposing the whole object. Which means that others can call any of its functions and access any of its properties. And change them. This isn't good. Besides letting others use the object in ways it might not have intended, you will also run into issues if you try to change the object in the future and find out that it breaks somebody else who was using something you didn't intend. So, always a good idea to not expose anything that you don't have to. This is the purpose of delegates and protocols. It gives the object complete control over what is exposed. Much safer. Better design.
这是一个基本的设计原则,不公开更多的设计。通过传递引用,您将暴露整个对象。这意味着其他人可以调用它的任何函数并访问它的任何属性。和改变他们。这不是很好。除了让其他人以它可能不打算使用的方式使用这个对象之外,如果您试图在未来更改这个对象并发现它破坏了正在使用您不打算使用的东西的其他人,那么您还将遇到问题。所以,最好不要暴露任何不必要的东西。这是委托和协议的目的。它使对象能够完全控制公开的内容。更安全。更好的设计。
#3
3
I think you didn't fully get the understanding what protocols are.
我想你还没有完全理解什么是协议。
I always say protocols are like contracts.
The delegate object that implements a certain protocols promises that it can do things the delegator can't do.
我总是说协议就像契约。实现特定协议的委托对象承诺它可以做委托者不能做的事情。
In real world I have a problem with my house's tubes.
I (the delegator) call a plumber (the delegate) to fix it. The plumber promises (by contract) to be able to duo it. The promise is the protocol. I don't care how he do it, as long as he does it.
在现实生活中,我对我家的管道有问题。我(代表)叫一个水管工(代表)来修理它。管道工(按合同)保证能把它修好。承诺就是协议。我不在乎他怎么做,只要他做就行。
But these contracts are not only useful for delegation.
I am just writing a food ordering app. As it has a menu it need item to display in it.
I could go with basic inheritance and write a class MenuItem, that all sub classes must inherit from.
Or I write an protocol to express: «No matter what object you are, as long as you fulfill this contract we have a deal». this allows me to create many different classes or annotate existing classes in categories, although I don't have the tool of multiple inheritance.
但这些合同不仅对授权有用。我正在写一款订餐app,因为它有菜单,所以需要在里面显示。我可以使用基本继承和编写类MenuItem,所有子类都必须继承。或者我写一个协议来表达:“无论你是什么对象,只要你履行这个合同,我们就会达成协议。”这允许我创建许多不同的类,或者在类别中注释现有的类,尽管我没有多重继承的工具。
Actually I do both: I write a protocol MenuItem
and a class MenuItem
that conforms to the protocol. Now I can use simple inheritance or use classes that do not inherit from the class MenuItem
.
实际上我两者都做:我编写一个协议MenuItem和一个符合协议的类MenuItem。现在,我可以使用简单的继承或使用不从MenuItem类继承的类。
Code in Objective-C (sorry: I am still transitioning to Swift)
Objective-C中的代码(抱歉:我还在向Swift转换)
@protocol MenuItem <NSObject>
-(NSString *)name;
-(double) price;
-(UIColor *)itemColor;
@end
@interface MenuItem : NSObject <MenuItem>
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) double price;
@property (nonatomic, strong) UIColor *itemColor;
@end
#import "MenuItem.h"
@implementation MenuItem
-(id)initWithCoder:(NSCoder *)decoder
{
self = [super init];
if (self) {
self.name = [decoder decodeObjectForKey:@"name"];
self.price = [decoder decodeDoubleForKey:@"price"];
self.itemColor = [decoder decodeObjectForKey:@"itemColor"];
}
return self;
}
-(void)encodeWithCoder:(NSCoder *)encoder
{
[encoder encodeDouble:self.price forKey:@"price"];
[encoder encodeObject:self.name forKey:@"name"];
[encoder encodeObject:self.itemColor forKey:@"itemColor"];
}
@end
Apple uses the same Architecture for NSObject: there is a protocol and a class NSObject
. This allows classes, that aren't intact inheriting from the class NSObject
to act ash an NSObject. One famous example:NSProxy
.
苹果对NSObject使用相同的架构:有一个协议和一个类NSObject。这允许不完整地继承类NSObject以执行NSObject的类。一个著名的例子:NSProxy。
in your case Screen1 promises to be able to understand messages that are send by the detail view controller Screen2. These allows decoupling: any object that does understand Screen1's protocol can be used. Also it helps to maintain a sane object tree, as we don't have to have circular imports. But in general you have to keep in mind that the delegator (Screen2) must keep a weak reference to it's delegate, otherwise we have a retain circle.
在您的例子中,Screen1保证能够理解由detail视图控制器Screen2发送的消息。这些允许解耦:任何理解Screen1的对象都可以使用。它还有助于维护一个正常的对象树,因为我们不必使用循环导入。但一般来说,你必须记住,委派者(Screen2)必须对它的委派保持弱引用,否则我们就会有一个保留循环。
Of course an important example it UITableView:
The table view object knows everything about rendering it's cells, handling scrolling and so one. But the engineer who wrote it couldn't now how you want your table view look like. That's why he introduced a delegate to give you the chance to create the right cell. As he couldn't also know what your data looks like, he also introduced the datasource - that works exactly like a delegate: you will be asked to provide all information about your data, that are needed.
当然,它UITableView的一个重要示例是:表视图对象知道如何渲染它的单元格、处理滚动等等。但是,编写它的工程师现在不可能希望您的表视图是什么样子的。这就是为什么他引入了一个委托,让您有机会创建正确的单元格。由于他也不知道您的数据是什么样子,他还介绍了数据源——它的工作方式与委托完全一样:您将被要求提供有关您的数据的所有信息,这是必需的。
#4
2
This is mostly a matter of opinion so this question should probably be closed, but I think the developer community as a whole is in an agreement on this so I am going to answer it anyway.
这主要是一个观点问题,所以这个问题应该结束了,但是我认为整个开发者社区都同意这个问题,所以我还是要回答这个问题。
An important concept in Software Architecture (the design of the structure of code) is called Separation of Concerns. The basic principle is that you should break down what your code has to do into small components that only have one distinct purpose. Each of these components should be able to stand mostly on their own without much concern with other components other than the ones it needs to directly be interacting with.
软件架构中的一个重要概念(代码结构的设计)称为关注点分离。基本原则是,您应该将代码要做的工作分解成只有一个不同目的的小组件。这些组件中的每一个都应该能够独立运行,而不需要与其他组件进行过多的关注,而只需与其他组件进行直接交互。
This helps greatly with code reuse. If you design a small component that is independent of most / if not all other components, you can easily plug that into other parts of your code or other applications. Take UITableView for example. By using the delegate pattern, every developer can easily create a table view and populate it with whatever data they want. Since that data source is a separate object (with the separate concern of coming up with the data) you can attach that same data source to multiple table views. Think of a contact list on iOS. You will want to access that same data in many ways. Instead of always rewriting a table view that loads the specific data and displays it in a specific way, you can reuse the data source with a different table view as many times as you want.
这极大地帮助了代码重用。如果您设计一个独立于大多数/如果不是所有其他组件的小组件,您可以轻松地将其插入代码或其他应用程序的其他部分。以UITableView为例。通过使用委托模式,每个开发人员都可以轻松地创建一个表视图,并用他们想要的任何数据填充它。由于数据源是一个单独的对象(考虑到生成数据的问题),所以可以将相同的数据源附加到多个表视图。想想iOS上的联系人列表。您将希望以多种方式访问相同的数据。不要总是重写一个装载特定数据并以特定方式显示它的表视图,您可以使用不同的表视图重用数据源。
This also helps with the understandability of your code. It is tough for developers to keep too many thing in their head about the state of your app. If each of your code components are broken down into small, well defined responsibilities, a developer can understand each component separately. They can also look at a component, and make accurate assumptions about what it does without having to look at the specific implementation. This isn't such a big deal with small apps, but as code bases grow, this becomes very important.
这也有助于代码的可理解性。对于开发人员来说,要记住太多关于应用程序状态的东西是很困难的。如果您的每个代码组件被分解成小的、定义良好的职责,那么开发人员可以分别理解每个组件。他们还可以查看组件,并对其功能做出准确的假设,而不必查看特定的实现。对于小型应用程序来说,这并不是什么大问题,但随着代码库的增长,这一点变得非常重要。
By passing in a reference to your first view controller, you are making your second view controller completely dependent on the first. You cannot reuse the second view controller in another instance and its job becomes less clear.
通过传递对第一个视图控制器的引用,您正在使第二个视图控制器完全依赖于第一个视图控制器。您不能在另一个实例中重用第二个视图控制器,其工作也变得不那么清晰。
There are lots of other benefits to separation of concerns but I believe those are two compelling and important ones.
分离关注点还有很多其他好处,但我认为这是两个引人注目的重要好处。