2025-02-10 09:31:57
,某些文章具有时效性,若有错误或已失效,请在下方留言。Swift provides four concrete nominal types for defining custom objects: actors, classes, structs, and enums. Each of these works a little differently from the others, but the first three might seem similar so it’s worth spending a little time clarifying what they have in common and where their differences are.
Swift 提供了四种具体的名义类型来定义自定义对象:actors、classes、structs 和 enums。这些方法中的每一个都与其他方法略有不同,但前三个可能看起来相似,因此值得花一点时间澄清它们的共同点和差异所在。
Tip: Ultimately, which you use depends on the exact context you’re working in, and you will need them all at some point.
提示: 最终,你使用哪种方式取决于你正在工作的确切上下文,并且你将在某个时候需要它们。
Actors: 演员:
- Are reference types, so are good for shared mutable state.
是引用类型,因此适用于共享的可变状态。 - Can have properties, methods, initializers, and subscripts.
可以具有 properties、methods、initializers 和 subscripts。 - Do not support inheritance.
不支持继承。 - Automatically conform to the
Actor
protocol.
自动符合Actor
协议。 - Automatically conform to the
AnyObject
protocol, and can therefore conform toIdentifiable
without adding an explicitid
property.
自动符合AnyObject
协议,因此可以符合Identifiable
而无需添加显式id
属性。 - Can have a deinitializer.
可以有一个 deinitializer。 - Cannot have their public properties and methods directly accessed externally; we must use
await
.
不能从外部直接访问其公共属性和方法;我们必须使用await
。 - Can execute only one method at a time, regardless of how they are accessed.
一次只能执行一个方法,而不管它们是如何访问的。
Classes: 类:
- Are reference types, so are good for shared mutable state.
是引用类型,因此适用于共享的可变状态。 - Can have properties, methods, initializers, and subscripts.
可以具有 properties、methods、initializers 和 subscripts。 - Support inheritance. 支持继承。
- Cannot conform to the
Actor
protocol.
无法符合Actor
协议。 - Automatically conform to the
AnyObject
protocol, and can therefore conform toIdentifiable
without adding an explicitid
property.
自动符合AnyObject
协议,因此可以符合Identifiable
而无需添加显式id
属性。 - Can have a deinitializer.
可以有一个 deinitializer。 - Can have their public properties and methods directly accessed externally.
可以直接从外部访问其公共属性和方法。 - Can potentially be executing severals methods at a time.
可以一次执行多个方法。
Structs: 结构体:
- Are value types, so are copied rather than shared.
是值类型,因此是复制而不是共享。 - Can have properties, methods, initializers, and subscripts.
可以具有 properties、methods、initializers 和 subscripts。 - Do not support inheritance.
不支持继承。 - Cannot conform to the
Actor
protocol.
无法符合Actor
协议。 - Cannot conform to the
AnyObject
protocol; if you want to addIdentifiable
conformance you must add anid
property yourself.
无法符合AnyObject
协议;如果要添加Identifiable
conformance,则必须自己添加id
属性。 - Cannot have a deinitializer.
不能有 deinitializer。 - Can have their public properties and methods directly accessed externally.
可以直接从外部访问其公共属性和方法。 - Can potentially be executing severals methods at a time.
可以一次执行多个方法。
You might think the advantages of actors are such that they should be used everywhere classes are currently used, but that is a bad idea. Not only do you lose the ability for inheritance, but you’ll also cause a huge amount of pain for yourself because every single external property access needs to use await
.
你可能认为 actor 的优点是应该在当前使用类的任何地方使用它们,但这是一个坏主意。你不仅失去了继承的能力,而且还会给自己带来巨大的痛苦,因为每个外部属性访问都需要使用 await
。
However, there are certainly places where actors are a natural fit. For example, if you were previously creating serial queues to handle specific workflows, they can be replaced almost entirely with actors – while also benefiting from increased safety and performance. So, if you have some work that absolutely must work one at a time, such as accessing a database, then trying converting it into something like a database actor.
然而,肯定有一些地方演员是天作之合。例如,如果您以前创建串行队列来处理特定工作流,则它们几乎可以完全替换为参与者,同时还可以从更高的安全性和性能中受益。所以,如果你有一些工作绝对必须一次工作一个,比如访问一个数据库,那么试着把它转换成一个类似数据库 actor 的东西。
There is one area in particular where using actors rather than classes is going to cause problems, so I really can’t say this clearly enough:
特别是,使用 actor 而不是 class 会导致问题,所以我真的不能说得足够清楚:
Do not use actors for your SwiftUI data models. You should use a class that uses the @Observable
macro or conforms to the ObservableObject
protocol instead. If needed, you can optionally also mark that class with @MainActor
to ensure it does any UI work safely, but keep in mind that all SwiftUI views automatically run their code on the main actor.
不要将 Actor 用于 SwiftUI 数据模型。 您应该改用使用 @Observable
宏或符合 ObservableObject
协议的类。如果需要,您还可以选择使用 @MainActor
标记该类,以确保它安全地执行任何 UI 工作,但请记住,所有 SwiftUI 视图都会在主要参与者上自动运行其代码。
If you desperately need to be able to carve off some async work safely, you can create a sibling actor – a separate actor that does not use @MainActor
, but does not directly update the UI.
如果您迫切需要能够安全地分割一些异步工作,您可以创建一个同级 actor – 一个不使用 @MainActor
,但不直接更新 UI 的单独 actor。