No Prefixes in Swift0only Frameworks
C and Object-C symbols are global
Swift's module system allows disambiguation
Remember-each source file brings its imports into the same namespace
Values and references
Protocols and generics
Key path member lookup
Property wrappers
Classes
reference Type 相当于OC对象的引用
Structs
values Type 会拷贝整个
Enums
values Type 会拷贝整个
Choosing Reference or Values?
Prefer structs over classes
·Only choose classes when reference semantics are important
Classes can make a good choice when
·You need a reference counting and deinitialization
·The value is held centrally and shared
·Where is a separate notion of "identity" from "equality
RealityKit - Scenes and Entities
Values Types Make Copies of References
拷贝struct时,如果内部有引用类型,那么里面的引用类型只会进行浅拷贝,其他值类型则会进行深拷贝
Value and Reference Semantics
//可以通过这样暴露私有参数的内部参数
private var _texture: Texture
public var is Sparkly: Bool {
get { _texture.isSparkly }
set {
// 检查,深复制
if !isKnownUniquelyReferenced(&_texture) { _texture = Texture(copying: _texture) }
_texture.isSparkly = newValue
}
}
Protocols and Generics
Don't Literally Start With a Protocol
Start with concrete use cases
Discover a need for generic code
Try to compose solutions from existing protocols first
Consider a generic type instead of a protocol
SIMD? Scalar?
太多的协议,会造成编译速度变慢,因为会存在一个表里面
Key Path Member Lookup
Property Wrappers
Capture backing storage property and access policy for re-use
public struct MyType {
@LateInitialized public var ...
//
}
Provides similar benefits to the built-in lazy
·Eliminates boilerplate
·Document semantics at the point of definition
@property Wrapper
public struct LateInitialized {
private var storage: Value?
public init() {
storage = nil
}
public var value: Value {
get {
guard let value = storage else {
fatalError("value has not yet been set!")
}
return value
}
set {
storage = newValue
}
}
}
Using Property Wrappers
Use of property wrappers expand into a stored property and a computed property
public struct MyType {
@LateInitialized public var text: String
// Compiler-synthesized code...
var $text: LateInitialized = LateInitialized()
public var text: String {
get { $text.value }
set { $text.value = newValue }
}
}
Using the DefensiveCopying Property Wrapper
@DefensiveCopying variables can be initialized in their declaration:
public struct MyType {
@DefensiveCopying public var path: UIBezierPath = UIBezierPath()
}
// Defensive Copying
@propertyWrapper
public struct DefensiveCopying {
private var storage: Value
public init(initialValue value: Value) {
storage = value.copy() as! Value
}
public var value: Value {
get { storage }
set {
storage = newValue.copy() as! Value
}
}
}
可以另外添加一个方法不进行拷贝初始化
extension DefensiveCopying {
public init(withoutCopying value: Value) {
storage = value
}
}
Initializing the backing storage property:
public struct MyType {
@DefensiveCopying public var path: UIBezierPath
public init() {
$path = DefensiveCopying(withoutCopying: UIBezierPath())
}
}
API Design with Property Wrappers
Property wrappers describe the policy behind your data access Lots of API revolves around data access
@UserDefault(key: "BOOSTER_IGNITED", defaultValue: false)
static var isBoosterIgnited: Bool
@ThreadSpecific var localPool: MemoryPool //单独开一个线程存储,可以安全并且不需要考虑多线程的锁
Property Wrappers in SwiftUI
View data dependencies are expressed using property wrappers
struct SlideViewer: View {
@State private var isEditing = false
@Binding var slide: Slide
var body: some View {
VStack {
Text("Slide #\(slide.number)")
if isEditing {
TextField($slide.title)
}
// ...
}
}
}
内部实现
// Property Wrappers & Key Path Member Lookup
@propertyWrapper @dynamicMemberLookup
public var value: Value {
public struct Binding {
get { ... }
nonmutating set { ... }
}
public subscript(dynamicMember keyPath: WritableKeyPath) ->Binding { ... } //通过这个可以获取内部变量的@Binding属性
}
slide // Slide instance
slide.title // String instance
$slide // Binding instance
$slide.title // Binding instance 相当于 $slide[dynamicMember: \Slide.title]
Summary
Value semantics vs. reference semantics
Use protocols for code reuse — not classification
Property wrappers reuse computed property definitions