- Published on
π WWDC23 - What's new in Swift
- Authors
- Name
- μ΄μ°½μ€
WWDC23 - Whatβs new in Swift
Swiftμ μλ‘μ΄ feature, 맀ν¬λ‘κ° λ무 κΆκΈν΄μ ν΄λΉ μΈμ λΆν° μ°Ύμλ³΄κ² λμμ΅λλ€.
λ°λ‘ μμν΄λ³΄μ£ ..!
Expressive Code
Using if/else and switch Statements as Expressions
μμ°.. μμλΆν° ν° μμμ΄λ€μ.. if-else
ꡬ문과 switch
ꡬ문μ ννμ μΌλ‘μ μ¬μ©ν μ μλ€λ μμμ
λλ€.
let bullet =
isRoot && (count == 0 || !willExpand) ? ""
: count == 0 ? "- "
: maxDepth <= 0 ? "βΉ " : "βΏ "
λ€μ κ³Όμ₯λκΈ΄ νμ§λ§ 볡μ‘ν 쑰건μ μν΄ λ€μν κ°μ let
λ³μμ λ£μ΄μ£Όκ³ μΆμ λλ μμ κ°μ΄ μΌνμ°μ°μλ₯Ό κ²Ήκ²Ήμ΄ μμκ°λ©° μ¬μ©ν΄μΌ νμ΅λλ€. νμ§λ§ μ΄μ if-else
ꡬ문μΌλ‘ μ½κΈ° μ½κ² κ°λ₯ν©λλ€.
let bullet =
if isRoot && (count == 0 || !willExpand) { "" }
else if count == 0 { "- " }
else if maxDepth <= 0 { "βΉ " }
else { "βΏ " }
μ΄ λ°©μμ΄ νΉνλ ν¨κ³Όλ₯Ό 보λ κ³³μ μ μ λ³μλ μ μ₯ νλ‘νΌν°λ₯Ό μ¬μ©ν λμ λλ€.
let attributedName = {
if let displayName, !displayName.isEmpty {
AttributedString(markdown: displayName)
} else {
"Untitled"
}
}()
μ μ λ³μλ μ μ₯ νλ‘νΌν°μ 쑰건μ λ°λΌ λ€λ₯Έ κ°μ λ£μ΄μ£ΌκΈ° μν΄μλ μ΄λ κ² λ°λ‘ νΈμΆλλ ν΄λ‘μ λ₯Ό ν΅ν΄μΌλ§ νμ΅λλ€.
let attributedName =
if let displayName, !displayName.isEmpty {
AttributedString(markdown: displayName)
} else {
"Untitled"
}
νμ§λ§ μ΄μ if-else
ꡬ문μ ννμμΌλ‘ μ¬μ©ν μ μκΈ° λλ¬Έμ ν΄λ‘μ κ° νμ μμ΅λλ€.
Result Builders
Result Builderκ° λλλ©΄μ..
μ λ μ΄λ²μ μ²μ μμλ³΄κ² λμλλ°μ.. WWDC21μμ λ°νλμλ λ΄μ©μ΄λλΌκ΅¬μ..!?
image.constraints { view in
view.centerXAnchor == container.centerXAnchor
view.topAnchor == container.topAnchor + 20
view.widthAnchor == container.widthAnchor -- 20
view.heightAnchor == view.widthAnchor * 0.6
}
λ§μΉ μ΄λ κ² SwiftUIμ ννμ²λΌ μ μΈνμΌλ‘ κ°μ μ€μ ν΄μ€ μ μλ λ¬Έλ²μ λλ€.
DSL(Domain Specific Language) λΌκ³ λΆλ¦¬λλ°μ..
μ κ° μ λͺ¨λ₯΄κΈ° λλ¬Έμβ¦ π
μλ¬΄νΌ νμ 체νΉμ΄ λΉ¨λΌμ§κ³ μλ¬κ° μ’ λ μ νν μ§μ μ νμλλ€κ³ ν©λλ€.
Type Parameter Packs
μ΄ λΆλΆμ Genericκ³Ό κ΄λ ¨λ λ΄μ©μ λλ€.
Swiftμ λͺ¨λ κ³³μ Genericμ΄λΌκ³ λ ν μ μμ΅λλ€.
λ°°μ΄λ§λ΄λ μ¬μ€μ Array<Element>
λΌλ Genericμ νμ©ν νμ
μ΄μ£ !?
struct Request<Result> { ... }
struct RequestEvaluator {
func evaluate<Result>(_ request: Request<Result>) -> Result
}
func evaluate(_ request: Request<Bool>) -> Bool {
return RequestEvaluator().evaluate(request)
}
μ¬κΈ° Bool
νμ
μ κ°μ νλλ§ λ°λ ν¨μ evaluate
κ° μμ΅λλ€.
νμ§λ§ μ¬λ¬κ°μ κ°μ νλΌλ―Έν°λ‘ λ°κ³ μΆμ λλ μκ² μ£ ?
let value = RequestEvaluator().evaluate(request)
let (x, y) = RequestEvaluator().evaluate(r1, r2)
let (x, y, z) = RequestEvaluator().evaluate(r1, r2, r3)
λ¬Έμ λ μ΄λ κ² ν¨μλ₯Ό μ¬μ©νλ €λ©΄..
func evaluate<Result>(_:) -> (Result)
func evaluate<R1, R2>(_:_:) -> (R1, R2)
func evaluate<R1, R2, R3>(_:_:_:) -> (R1, R2, R3)
func evaluate<R1, R2, R3, R4>(_:_:_:_:)-> (R1, R2, R3, R4)
func evaluate<R1, R2, R3, R4, R5>(_:_:_:_:_:) -> (R1, R2, R3, R4, R5)
func evaluate<R1, R2, R3, R4, R5, R6>(_:_:_:_:_:_:) -> (R1, R2, R3, R4, R5, R6)
μ΄λ κ² λμ°νκ² κ° νλΌλ―Έν°μ κ°μμ λ§λ ν¨μλ€μ μ¬λ¬λ² μ€λ²λ‘λνλ©° μ μν΄μ£Όμ΄μΌ ν©λλ€.
μ΄κ±Έ 보μλ§μ RxSwiftμ combineLatest
κ° μκ°λλκ΅°μβ¦
λ± μ΄λ΄λμ κ²½μ°μ λλ€.
μ΄ λ°©λ²μ 보기μλ μμ’μ λΏλλ¬, μ 곡νλ νλΌλ―Έν°μ κ°μλ₯Ό μ¬μ©νλ μͺ½μμ λ°μ΄λμΌλ©΄ λΉμ°νκ²λ μ»΄νμΌλ¬ μλ¬λ₯Ό λ°μμν΅λλ€.
μ΄ λ¬Έμ λ₯Ό ν΄κ²°νκΈ° μν΄ Swiftμ Genericμ μ 곡λ μΈμμ κ°μλ³΄λ€ λ§μ μμ κ°μ λ°μλΌ μ μλ μλ‘μ΄ λ¬Έλ²μ΄ λμ λμμ΅λλ€.
μλ‘μ΄ each
ν€μλλ Generic νμ
μ μΆ©μ‘±νλ λ€μν κ°μμ μΈμλ€μ βpackedβλ μν λ‘ λ°μ μ μλλ‘ ν©λλ€.
func evaluate<each Result>(_: repeat Request<each Result>) -> (repeat each Result)
νλμ νλΌλ―Έν° Request<Result>
λμ μ¬λ¬κ°μ νλΌλ―Έν°λ₯Ό λ°λ³΅ν΄μ λ°λλ€λ μλ―Έλ‘ repeat Request<each Result>
λ₯Ό μ¬μ©ν©λλ€.
λ°ννλ κ°μ μΈμκ° νλμΌ κ²½μ° νλμ κ°μ, μ¬λ¬ κ°μΌ κ²½μ° μ¬λ¬ κ°μ κ°μ Tuple (repeat each Result)
λ‘ λ°νν©λλ€.
κ·Έλ λ€λ©΄ μ¬μ©νλ μͺ½μμλ μ΄λ¨κΉμ?
let results = RequestEvaluator.evaluate(r1, r2, r3)
Type Parameter Packs APIλ₯Ό μ¬μ©νλμ§ μ‘°μ°¨ μ μ μμ μ λλ‘ μμ°μ€λ½μ΅λλ€..!
Swift Macros
λλ§μ 맀ν¬λ‘μ λλ€..
assert
μμλΆν° μμνκ³ μλ€μ.
assert
λ μ‘°κ±΄λ¬Έμ΄ false
μΌ λ, νλ‘κ·Έλ¨μ μλμΌλ‘ μ’
λ£μν€μ£ .
assert(max(a, b) == c)
λ¬Έμ λ μμ κ°μ λ°©μμ νλ‘κ·Έλ¨μ κ·Έλ₯ μ’ λ£μμΌλ²λ¦¬κ³ , μ’ λ£λ λΌμΈλ§μ λ‘κ·Έμ λ¨κΈ΄λ€λ κ²μ λλ€.
κ·Έλμ μ νμ λ€λ₯Έ μ¬λ¬κ°μ§ assert
λ°©μλ€μ μΆκ°ν΄μ€¬μ΅λλ€.
![](XCAssertEqual(max(a, b), c))
XCAssertEqual
μ μ’ λ λμ λ‘κ·Έλ₯Ό λ¨κ²¨μ€λλ€. μκΉλ³΄λ€λ ν¨μ¬ λ«κΈ΄ νμ§λ§ μ¬μ ν a
, b
, νΉμ max(a, b)
μ€μμ μ΄λ€ κ°μ΄ μλ¬λ₯Ό λ°μμν€λμ§λ μ¬μ ν μ μκ° μμ£ .
νμ§λ§ μ΄μ λ Macroλ₯Ό μ¬μ©ν΄μ μ΄λ₯Ό ν΄κ²°ν μ μμ΅λλ€.
#assert(max(a, b) == c)
맀ν¬λ‘λ λ€λ₯Έ APIλ€κ³Ό λΉμ·νκ² ν¨ν€μ§μ ννλ‘ import
νμ¬ μ¬μ©ν μ μμ΅λλ€.
μ¬κΈ°μ μ¬μ©ν #assert
맀ν¬λ‘λ PowerAssertλΌλ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ€μΉν΄μ μ¬μ©ν μ μλ€μ.
π PowerAssert
Macro Declarations
μ΄λ¦μ΄ 맀ν¬λ‘λΌλ©΄ λ΄κ° μ§μ μνλ ννμ 맀ν¬λ‘λ₯Ό μ¬μ©ν μλ μμ΄μΌκ² μ£ ?
macro
ν€μλλ₯Ό μ¬μ©ν¨μΌλ‘μ¨ λ§€ν¬λ‘λ₯Ό μ μν΄μ€ μ μμ΅λλ€.
public macro assert(_ condition: Bool)
ν¨μμ μλΉν λΉμ·νκ² μκ²Όμ£ ..?
ν¨μμ λμΌνκ² μ μν΄μ€ μ μκ³ , ν¨μμ λ§μ°¬κ°μ§λ‘ νμ 체ν¬λ μ΄λ£¨μ΄μ§λλ€.
κ·Έλμ μ΄ assert
맀ν¬λ‘λ₯Ό
#assert(max(a, b))
μ΄λ κ² μ λͺ» μ¬μ©νλ©΄?
public macro assert(_ condition: Bool) = #externalMacro(
module: "PowerAssertPlugin",
type: "PowerAssertMacro"
)
λλΆλΆμ 맀ν¬λ‘λ βExternal Macrosβ λΌκ³ ν©λλ€.
μ»΄νμΌλ¬λ 맀ν¬λ‘λ₯Ό String
μΌλ‘ μ 곡λλ module
μ 보μ type
μ 보λ₯Ό ν΅ν΄ μλ³νλ€κ³ νλ€μ..
맀ν¬λ‘λ μ»΄νμΌλ¬ νλ¬κ·ΈμΈμΌλ‘ μλνλ©° μ±κ³Όλ λ³λμ νλ‘κ·Έλ¨ μΌλ‘μ¨ μ€νλλ€κ³ ν©λλ€.
μ»΄νμΌλ¬λ νλ¬κ·ΈμΈμκ² λ§€ν¬λ‘λ₯Ό μ λ¬νκ³ , νλ¬κ·ΈμΈμ΄ 맀ν¬λ‘μ λμλλ μμ€μ½λλ₯Ό μ»΄νμΌλ¬μκ² μ 곡νκ³ μλ€μ.
맀ν¬λ‘μκ² νμν λ§μ§λ§ μ 보λ κ·Έλ€μ μν (role) μ λλ€.
Freestanding Macros
@freestanding(expression)
public macro assert(_ condition: Bool) = #externalMacro(
module: "PowerAssertPlugin",
type: "PowerAssertMacro"
)
#assert
맀ν¬λ‘λ @freestanding(expression)
맀ν¬λ‘μΈλ°μ..
freestanding μ β#βλ‘ μ¬μ©ν μ μκ³ , λμλλ μ½λλ₯Ό μ§μ μ μΌλ‘ μ½μ νκΈ° λλ¬Έμ μ¬μ©λμμ΅λλ€.
expression μ κ²°κ³Όκ°μ΄ μλ κ·Έ μ΄λκ³³μμλ μ¬μ©ν μ μκΈ° λλ¬Έμ μ¬μ©λμλ€κ³ νλ€μ.
@freestanding(exrpession)
public macro Predicate<each Input>(
_ body: (repeat each Input) -> Bool
) -> Predicate<repeat each Input>
let pred = #Predicate<Person> {
#0.favoriteColor == .blue
}
let blueLovers = people.filter(pred)
expression 맀ν¬λ‘μλ #Predicate
λΌλ 맀ν¬λ‘λ μμ΅λλ€.
#Predicate
맀ν¬λ‘λ ν΄λ‘μ μμμ type-safeνκ² Predicateλ₯Ό μμ±ν μ μλλ‘ ν΄μ€λ€κ³ νλ€μ.
Attached Macros
λ ννμ 맀ν¬λ‘λ μμ΅λλ€.
μμλ‘ μ¬μ©ν enum
μ μ¬μ©ν κ²½μ°μΈλ°μ.
enum Path {
case relative(String)
case absolute(String)
}
extension Path {
var isAbsolute: Bool {
if case .absolute = self { true }
else { false }
}
}
extension Path {
var isRelative: Bool {
if case .relative = self { true }
else { false }
}
}
let absPaths = paths.filter { $0.isAbsolute }
enum
μ case
λ₯Ό κ²μ¬ν λ λ³΄ν΅ μ΄λ κ² λ§μ΄ μ¬μ©νμ΅λλ€.
μ΄λ° λ°©μμ λ¬Έμ κ° μμ΅λλ€. case
κ° λμ΄λ μλ‘ μ μ λ κΈΈμ΄μ§λ λ°©μμ μ½λλΌλ κ²μ΄μ£ .
@CaseDetection
enum Path {
case relative(String)
case absolute(String)
}
let absPaths = paths.filter { $0.isAbsolute }
@CaseDetctio
nμ βAttached Macrosβ μ
λλ€.
Property Wrapperμ λμΌνκ² β@β λ₯Ό μ¬μ©νκ³ μλ€μ!
μ΄ @CaseDetection
맀ν¬λ‘λ μ΄μ μ isAbsolute
μ isRelative
νλ‘νΌν°λ₯Ό μλμΌλ‘ μμ±ν΄μ€λλ€.
** Attached Macros** λ λ€μ― κ°μ§ μ’ λ₯λ‘ λλ μ μκ³ , κ°κ°μ μν μ μμ κ°μ΅λλ€.
member
type
/extension
μΌλ‘ μλ‘μ΄ μ μλ₯Ό μΆκ°- ex)
@CaseDetection
peer
- μ μλ ννκ³Ό ν¨κ» λ€λ₯Έ ννμΌλ‘μ¨ μ μλ₯Ό μΆκ°
- ex)
async
λ©μλμ κ°μ λ‘μ§μ μννλ completion handler λ²μ μ λ©μλ μΆκ°
accessor
- νλ‘νΌν°μ μ κ·Όνλ λ°©μμ μΆκ° (Property Wrapperμ μ μ¬)
- ex) μ μ₯ νλ‘νΌν°λ₯Ό μ°μ° νλ‘νΌν°λ‘ λ³κ²½
memberAttribute
type
/extension
μΌλ‘ μμ±(attribute)λ₯Ό μΆκ°
conformance
type
/extension
μΌλ‘ νλ‘ν μ½μ μΆ©μ‘±μν€κΈ° μν μμ μΆκ°
μΌλ°μ μΈ APIμ λ€λ₯΄κ² 맀ν¬λ‘κ° μ’μ μ μ, μ½λμμ λ°λ‘ μ΄λ€ μ½λ κ° μ€νλκ³ μλ μ§ νμΈν μ μκ³ , λλ²κ·Έ κ³Όμ μμ μ§μ ν μ μμΌλ©°, 맀ν¬λ‘ μμ λ°κΉ₯μΌλ‘ 볡λΆνλ κ²μΌλ‘ μ½κ² μμ ν μλ μλ€λ κ²μ λλ€.
Attached Macros λ€μ λμμ μ¬λ¬κ°κ° μ¬μ©λ μλ μμ΅λλ€.
μμλ‘ SwiftUIμ μ½λλ₯Ό λ€κ³ μλλ°μ.. λ¬΄μ¨ μλ―ΈμΈμ§λ μ κ² κ°μμ ν λ² μ΄ν΄λ³΄κ² μ΅λλ€.
// Observation in SwiftUI
final class Person: ObservableObject {
@Published var name: String
@Published var age: Int
@Published var isFavorite: Bool
}
struct ContentView: View {
@ObservedObject var person: Person
var body: some View {
Text("Hello, \(person.name)")
}
}
μ΄λ° ννμ ν΄λμ€κ° μλλ°μ, Person
μ κ° νλ‘νΌν°λ€μ λ³νλ₯Ό λ°μ ContentView
μ λ΄μ©μ μ
λ°μ΄νΈν΄μ£Όλ μ½λ κ°μ΅λλ€.
λ¬Έμ λ λ°λ³΅λλ @Published
, ObservableObject
νλ‘ν μ½ λ± νμν λΆκ°μμ
λ€μ΄ λ무 λ§λ€λ κ²μ΄μ£ .
맀ν¬λ‘λ₯Ό μ¬μ©νλ©΄ μ΄ κ³Όμ λ€μ νλλ‘ μΆμμν¬ μ μμ΅λλ€.
// Observation in SwiftUI
@Observable final class Person {
var name: String
var age: Int
var isFavorite: Bool
}
struct ContentView: View {
var person: Person
var body: some View {
Text("Hello, \(person.name)")
}
}
@Observable
νλλ©΄ λͺ¨λ μμ
μ΄ μνλ©λλ€.
λ΄λΆλ₯Ό ν λ² μ΄ν΄λ³ΌκΉμ?
@attached(member, names: ...)
@attached(memberAttribute)
@attached(conformance)
public macro Observable() = #externalMacro(...).
member
roleμ ν΅ν΄ μλ‘μ΄ νλ‘νΌν°λ€κ³Ό λ©μλλ€μ μΆκ°ν©λλ€.memberAttribute
roleμ ν΅ν΄@ObservationTracked
맀ν¬λ‘λ₯Ό κ° μ μ₯ νλ‘νΌν°μ μΆκ°νκ³getter
μsetter
λ₯Ό μΆκ°ν©λλ€.Observable
νλ‘ν μ½μ μ±νν©λλ€.
맀ν¬λ‘λ₯Ό νΌμΉ ννμ μ½λλ μ΄λ μ΅λλ€.
@Observable final class Person: Observable {
@ObservationTracked var name: String { get { β¦ } set { β¦ } }
@ObservationTracked var age: Int { get { β¦ } set { β¦ } }
@ObservationTracked var isFavorite: Bool { get { β¦ } set { β¦ } }
internal let _$observationRegistrar = ObservationRegistrar<Person>()
internal func access<Member>(
keyPath: KeyPath<Person, Member>
) {
_$observationRegistrar.access(self, keyPath: keyPath)
}
internal func withMutation<Member, T>(
keyPath: KeyPath<Person, Member>,
_ mutation: () throws -> T
) rethrows -> T {
try _$observationRegistrar.withMutation(of: self, keyPath: keyPath, mutation)
}
}
맀ν¬λ‘μ λν΄μλ ν λ² κ΄λ ¨ μΈμ μ μ΄ν΄λ³΄λ©΄μ 곡λΆν΄λ΄μΌκ² λ€μ.
μλ‘μ΄ ν¨λ¬λ€μμ μμμΌ λ―ν λλ..!
Swift Foundation
μ΅κ·Ό μ νμ΄ Foundation μ½λλ€μ Swiftλ‘ λ€μ μ°λ νλ‘μ νΈλ₯Ό μμνλ€κ³ ν©λλ€.
κΈ°μ‘΄μ C, Obj-C μ½λλ€μ Swiftλ‘ κ΅μ²΄νκ³ μλ€κ³ νλ€μ..
μ΄λ² λ²μ μλ Date
, Calendar
, Locale
, AttributedString
, JSON encode
/ decode
κ° Swiftλ‘ λ€μ μ°μ¬μ‘λ€κ³ ν©λλ€.
λ€.. κ·Έλ λ€κ³ ν©λλ€..
λμ΄κ°μ£ !
Ownership
μ΄λ€ κ°μ μ΄λ€ μ½λκ° μμ νκ³ μλ μ§μ λν μΆμ μ΄ κ°λ₯ν΄μ‘λ€κ³ ν©λλ€.
μ λ μ½λ μμ±μκ° λκ΅°μ§ μκ·Έλμ² κ°μ κ±Έ λ¨κ²¨λλ 건 μ€ μμλλ°, μ ν λ€λ₯Έ κΈ°λ₯μ΄μλ€μ.
struct FileDescriptor {
private var fd: CInt
init(descriptor: CInt) { self.fd = descriptor }
func write(buffer: [UInt8]) throws {
let written = buffer.withUnsafeBufferPointer {
Darwin.write(fd, $0.baseAddress, $0.count)
}
// ...
}
func close() {
Darwin.close(fd)
}
}
μ΄ μ½λλ μνμ±μ΄ μμ΅λλ€.
νμΌ μμ μ λ§μΉ νμ close()
λ₯Ό νΈμΆνμ§ μμ κ°λ₯μ±μ΄ λννμ£ .
FileDescriptor
λ₯Ό ν΄λμ€λ‘ λ°κΎΈκ³ deinit
μμ μ close()
λ₯Ό νΈμΆν΄μ€λ λμ§λ§, ν΄λμ€λ reference νμ
μ΄κΈ° λλ¬Έμ νλμ νμΌμ κ΄λ¦¬νλ μΈ‘λ©΄μμλ μνμ±μ΄ ν½λλ€.
struct FileDescriptor: ~Copyable {
private var fd: CInt
init(descriptor: CInt) { self.fd = descriptor }
func write(buffer: [UInt8]) throws {
let written = buffer.withUnsafeBufferPointer {
Darwin.write(fd, $0.baseAddress, $0.count)
}
// ...
}
consuming func close() {
Darwin.close(fd)
}
deinit {
Darwin.close(fd)
}
}
κ·Έλμ λ±μ₯ν κ²μ΄ Non-Copyable struct
μ
λλ€.
~Copyable μ λΆμ¬μ£Όλ©΄, ν΄λμ€μ λ§μ°¬κ°μ§λ‘ deinit
μ μ¬μ©ν μ μκ² λ©λλ€.
μΆκ°μ μΌλ‘ consuming
μ΄λΌλ ν€μλλ λ±μ₯νλλ°μ, ν΄λΉ ν€μλκ° λ¬λ¦° ν¨μλ₯Ό νΈμΆν¨μΌλ‘μ¨ κ΅¬μ‘°μ²΄μ λν μμ κΆμ ν¬κΈ°ν μ μμ΅λλ€.
Non-Copyable ꡬ쑰체λ 볡μ¬λ μ μμΌλ, μμ κΆμ ν¬κΈ°νκ² λλ©΄ μ κ·Όν μ μλ κ°μ΄ λκ² μ£ ?
κ·Έλμ consuming
ν¨μλ ν΄λμ€λ₯Ό λ©λͺ¨λ¦¬μμ ν΄μ νλ κ²μ²λΌ ꡬ쑰체λ₯Ό λ©λͺ¨λ¦¬μμ ν΄μ μν΅λλ€.
Whatβs new in Swift Concurrency
Custom Actor Executors λΌλ λ μμ΄ μλ‘κ² λμμ΅λλ€.
κΈ°μ‘΄μ ActorλΌλ λμ μμ λ‘κ² μ¬μ©ν μ μλ λ μμ μλμμ£ ?
μ΄μ Actorλ₯Ό νΉμ DispatchQueue μ ν λΉμν¬ μ μλ€κ³ ν©λλ€.
actor MyConnection {
private var database: UnsafeMutablePointer<sqlite3>
private let queue: DispatchSerialQueue
nonisolated var unownedExecutor: UnownedSerialExecutor { queue.asUnownedSerialExecutor() }
init(filename: String, queue: DispatchSerialQueue) throws { β¦ }
func pruneOldEntries() { β¦ }
func fetchEntry<Entry>(named: String, type: Entry.Type) -> Entry? { β¦ }
}
await connection.pruneOldEntries()
unownedExecutor
λ₯Ό μ΄λ κ² μ§μ ν΄μ£Όλ©΄, λͺ¨λ Synchronizationμ΄ ν΄λΉ queueμμλ§ μ΄λ£¨μ΄μ§λ€κ³ νλ€μ.
λ¨μν await connection.pruneOldEntries()
λ₯Ό νΈμΆν΄μ£Όλ κ² λ§μΌλ‘λ μ§μ λ queue
μμ async
νκ² λμνλ€λ κ²μ΄μ£ !
μ΄μ Realmμ λ€λ£¨κΈ° μ’ λ μ¬μμ§λ κ±ΈκΉμ.. μ΅κ·Όμ μ΄κ±Έλ‘ κ³ λ―Όμ λ§μ΄ νλλ° λ§μ΄μ£ ..
// Executor protocols
protocol Executor: AnyObject, Sendable {
func enqueue(_ job: consuming ExecutorJob)
}
protocol SerialExecutor: Executor {
func asUnownedSerialExecutor() -> UnownedSerialExecutor
func isSameExclusiveExecutionContext(other executor: Self) -> Bool
}
extension DispatchSerialQueue: SerialExecutor { β¦ }
μλ¬΄νΌ μ΄ μλ‘μ΄ λμμ DispatchQueueκ° μλ‘μ΄ SerialExecutor
νλ‘ν μ½μ λ°λ₯΄κΈ° λλ¬Έμ κ°λ₯νλ€κ³ ν©λλ€.
isSameExclusiveExecutionContext(other executor:) -> Bool
μ ν΅ν΄ μ΄λ―Έ ν΄λΉ μ½λκ° μ€νλκ³ μλ μ§λ₯Ό κ²μ¬νκ³ , asUnownedSerialExecutor() -> UnownedSerialExecutor
λ₯Ό ν΅ν΄ Executor
μ unowned
μ°Έμ‘°λ₯Ό κ°μ Έμ¨λ€κ³ ν©λλ€.
κ·Έλ¦¬κ³ κ°μ₯ μ€μν enqueue(_ job:)
λ₯Ό ν΅ν΄ Executor
μ Job λ€μ κ΄λ¦¬νλ€κ³ νλ€μ.
μ¬κΈ°μ Job μ΄λ Executor
μμ λΉλκΈ°μ μΌλ‘ μ€νλμ΄μΌ ν λκΈ° TaskλΌκ³ ν©λλ€.
μμ§ν λ¬΄μ¨ λ§μΈμ§ λ무 ν·κ°λ¦¬λ€μβ¦ π
κ²°λ‘ μ μ΄μ βActor μμ DispatchQueue λ₯Ό μ§μ ν΄μ μ¬μ©ν μ μκ³ , μ΄λ DispatchQueueκ° μλ‘μ΄ SerialExecutor
νλ‘ν μ½μ λ°λ₯΄κΈ° λλ¬Έμ΄λ€. SerialExecutor
νλ‘ν μ½μ dispatch asyncλ₯Ό ν¬ν¨ν μ¬λ¬ Job λ€μ μμ°¨μ μΌλ‘ queue
λ₯Ό ν΅ν΄ μνν΄λκ°λ μμ
μ νλ€.β λΌκ³ μ΄ν΄νκ³ λμ΄κ°λ €κ³ ν©λλ€.
μμ°..
λ€λ‘ κ°μλ‘ μ μ μ΄ μλν΄μ§ λ» νμ§λ§.. ν λ² μ νμ΄λ³΄κΈ΄ νμ΅λλ€..
λΉμ₯ μ μκ² μ μΌ μ€μνλ λ΄μ©λ€μ
- Macros
- Type Parameter Packs
- DispatchQueue in Actor
μ΄λ κ²μΈ κ² κ°μμ!
νΉνλ 맀ν¬λ‘λ μ λλ‘ ν λ² μ΄ν΄λ΄μΌ ν κ² κ°μ΅λλ€..