Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Swift Concurrency Essentials

kakao
November 01, 2024

Swift Concurrency Essentials

#Swift #Concurrency #iOS #KakaoTalk

Swift 6부터 본격적으로 지원되는 Swift Concurrency에 대한 전반적인 개념을 소개합니다. 동시성 환경에서 안전한 코드를 만들기 위한 Concurrency의 주요 개념들에 대해 다루며, 이들을 다룰 때 주의할 점과 카카오톡에서는 어떻게 이용하고 있는지를 알아봅니다.

발표자 : hayden.chae
톡iOS에서 톡캘린더 개발을 담당하여, 더 나은 서비스를 만들기 위해 노력하는 헤이든입니다.

kakao

November 01, 2024
Tweet

More Decks by kakao

Other Decks in Programming

Transcript

  1. 4XJGU$PODVSSFODZ.PEFM fetchData(imagesURL) { data in DispatchQueue.global().async { let images =

    data.convertToResizedImages() DispatchQueue.main.async { images.enumerated().forEach { index, image in imageViews[index].image = image } } } }
  2. 4XJGU$PODVSSFODZ.PEFM let data = await fetchData(imageURL) let images = await

    data.convertToResizedImages() images.enumerated().forEach { index, image in imageViews[index].image = image }
  3. $PODVSSFODZীࢲ੄झۨ٘ Task.detached { let information = NonSendableInfo() // Thread#1 await

    someActor.add(information) // Thread#2 await someActor.arrangeInformation() // Thread#3 doSomeExtraWork() // Thread#4 }
  4. $PODVSSFODZীࢲ੄झۨ٘ Task.detached { let information = NonSendableInfo() // Thread#1 await

    someActor.add(information) // Thread#2 await someActor.arrangeInformation() // Thread#3 doSomeExtraWork() // Thread#4 }
  5. زӝജ҃ীࢲ੄$08 Task { var original = [10, 20, 30] //

    0x0010 var clone = original // 0x0010 clone.append(40) }
  6. زӝജ҃ীࢲ੄$08 Task { var original = [10, 20, 30] //

    0x0010 var clone = original clone.append(40) // 0x0030 }
  7. ࠺زӝജ҃ীࢲ੄$08 Task { var original = [10, 20, 30] var

    clone = original Task.detached { clone.append(40) } await Task.yield() original.append(50) }
  8. ࠺زӝജ҃ীࢲ੄$08$MPOF੉ݢ੷߸҃ؼٸ Task { var original = [10, 20, 30] //

    0x0010 var clone = original Task.detached { clone.append(40) // 0x0010 } await Task.yield() original.append(50) }
  9. ࠺زӝജ҃ীࢲ੄$08$MPOF੉ݢ੷߸҃ؼٸ Task { var original = [10, 20, 30] //

    0x0010 var clone = original Task.detached { clone.append(40) // 0x0030 } await Task.yield() original.append(50) }
  10. ࠺زӝജ҃ীࢲ੄$080SJHJOBM੉ݢ੷߸҃ؼٸ Task { var original = [10, 20, 30] //

    0x0010 var clone = original // 0x0010 Task.detached { clone.append(40) } await Task.yield() original.append(50) }
  11. ࠺زӝജ҃ীࢲ੄$080SJHJOBM੉ݢ੷߸҃ؼٸ Task { var original = [10, 20, 30] //

    0x0010 var clone = original // 0x0010 Task.detached { clone.append(40) } await Task.yield() original.append(50) }
  12. ࠺زӝജ҃ীࢲ੄$080SJHJOBM੉ݢ੷߸҃ؼٸ Task { var original = [10, 20, 30] var

    clone = original // 0x0010 Task.detached { clone.append(40) } await Task.yield() original.append(50) // 0x0030 }
  13. ࠺زӝജ҃ীࢲ੄$08زदী߸҃ؼٸ Task { var original = [10, 20, 30] //

    0x0010 var clone = original // 0x0010 Task.detached { clone.append(40) } await Task.yield() original.append(50) }
  14. ࠺زӝജ҃ীࢲ੄$08زदী߸҃ؼٸ Task { var original = [10, 20, 30] //

    0x0010 var clone = original // 0x0010 Task.detached { clone.append(40) } await Task.yield() original.append(50) }
  15. ࠺زӝജ҃ীࢲ੄$08زदী߸҃ؼٸ Task { var original = [10, 20, 30] //

    0x0010 var clone = original Task.detached { clone.append(40) // 0x0030 } await Task.yield() original.append(50) // 0x0050 }
  16. 4FOEBCMF$MBTTFT 4XJGU 4XJGU 4VQFSDMBTT হযঠೠ׮ 4VCDMBTTJOH fi OBM۽ࠛоמ 1SPQFSUJFT ݽٚ੷੢೐۽ಌ౭о4FOEBCMFMFU

    ݽٚ੷੢೐۽ಌ౭оইېઑѤ઺ೞաܳ݅઒ 4FOEBCMFMFU (MPCBMBDUPSীӈࣘ OPOJTPMBUFE VOTBGF $MBTT੗୓о(MPCBMBDUPSীӈࣘغয੓যب4FOEBCMFೞ׮
  17. 4FOEBCMF$MBTTFT 4XJGU 4XJGU 4VQFSDMBTT হযঠೠ׮ 4VCDMBTTJOH fi OBM۽ࠛоמ 1SPQFSUJFT ݽٚ੷੢೐۽ಌ౭о4FOEBCMFMFU

    ݽٚ੷੢೐۽ಌ౭оইېઑѤ઺ೞաܳ݅઒ 4FOEBCMFMFU (MPCBMBDUPSীӈࣘ OPOJTPMBUFE VOTBGF $MBTT੗୓о(MPCBMBDUPSীӈࣘغয੓যب4FOEBCMFೞ׮
  18. 4FOEBCMF$MBTTFT 4XJGU 4XJGU 4VQFSDMBTT হযঠೠ׮ 4VCDMBTTJOH fi OBM۽ࠛоמ 1SPQFSUJFT ݽٚ੷੢೐۽ಌ౭о4FOEBCMFMFU

    ݽٚ੷੢೐۽ಌ౭оইېઑѤ઺ೞաܳ݅઒ 4FOEBCMFMFU (MPCBMBDUPSীӈࣘ OPOJTPMBUFE VOTBGF $MBTT੗୓о(MPCBMBDUPSীӈࣘغয੓যب4FOEBCMFೞ׮
  19. 4FOEBCMF$MBTTFT 4XJGU 4XJGU 4VQFSDMBTT হযঠೠ׮ 4VCDMBTTJOH fi OBM۽ࠛоמ 1SPQFSUJFT ݽٚ੷੢೐۽ಌ౭о4FOEBCMFMFU

    ݽٚ੷੢೐۽ಌ౭оইېઑѤ઺ೞաܳ݅઒ 4FOEBCMFMFU (MPCBMBDUPSীӈࣘ OPOJTPMBUFE VOTBGF $MBTT੗୓о(MPCBMBDUPSীӈࣘغয੓যب4FOEBCMFೞ׮
  20. 4FOEBCMF$MBTTFT 4XJGU 4XJGU 4VQFSDMBTT হযঠೠ׮ 4VCDMBTTJOH fi OBM۽ࠛоמ 1SPQFSUJFT ݽٚ੷੢೐۽ಌ౭о4FOEBCMFMFU

    ݽٚ੷੢೐۽ಌ౭оইېઑѤ઺ೞաܳ݅઒ 4FOEBCMFMFU (MPCBMBDUPSীӈࣘ OPOJTPMBUFE VOTBGF $MBTT੗୓о(MPCBMBDUPSীӈࣘغয੓যب4FOEBCMFೞ׮
  21. 4FOEBCMF$MBTTFT 4XJGU 4XJGU 4VQFSDMBTT হযঠೠ׮ 4VCDMBTTJOH fi OBM۽ࠛоמ 1SPQFSUJFT ݽٚ੷੢೐۽ಌ౭о4FOEBCMFMFU

    ݽٚ੷੢೐۽ಌ౭оইېઑѤ઺ೞաܳ݅઒ 4FOEBCMFMFU (MPCBMBDUPSীӈࣘ OPOJTPMBUFE VOTBGF $MBTT੗୓о(MPCBMBDUPSীӈࣘغয੓যب4FOEBCMFೞ׮
  22. 4FOEBCMF$MBTTFT 4XJGU 4XJGU 4VQFSDMBTT হযঠೠ׮ 4VCDMBTTJOH fi OBM۽ࠛоמ 1SPQFSUJFT ݽٚ੷੢೐۽ಌ౭о4FOEBCMFMFU

    ݽٚ੷੢೐۽ಌ౭оইېઑѤ઺ೞաܳ݅઒ 4FOEBCMFMFU (MPCBMBDUPSীӈࣘ OPOJTPMBUFE VOTBGF $MBTT੗୓о(MPCBMBDUPSীӈࣘغয੓যب4FOEBCMFೞ׮
  23. class SharedState: @unchecked Sendable { private var revision = 0

    private let accessLock = NSLock() func updateRevision(_ newRevision: Int) { accessLock.lock() revision = newRevision accessLock.unlock() } }
  24. class SharedState: @unchecked Sendable { private var revision = 0

    private let accessLock = NSLock() func updateRevision(_ newRevision: Int) { accessLock.lock() revision = newRevision accessLock.unlock() } }
  25. class SharedState: @unchecked Sendable { private var revision = 0

    private let accessLock = NSLock() func updateRevision(_ newRevision: Int) { accessLock.lock() revision = newRevision accessLock.unlock() } var dangerousArray: [PotentialRace] = [] }
  26. class SharedState: @unchecked Sendable { private var revision = 0

    private let accessLock = NSLock() func updateRevision(_ newRevision: Int) { accessLock.lock() revision = newRevision accessLock.unlock() } var dangerousArray: [PotentialRace] = [] // NO WARNING!!! }
  27. class SharedState: @unchecked Sendable { private var revision = 0

    private let accessLock = NSLock() func updateRevision(_ newRevision: Int) { accessLock.lock() revision = newRevision accessLock.unlock() } var dangerousArray: [PotentialRace] = [] }
  28. final class SharedState: Sendable { nonisolated(unsafe) private var revision =

    0 private let accessLock = NSLock() func updateRevision(_ newRevision: Int) { accessLock.lock() revision = newRevision accessLock.unlock() } var dangerousArray: [PotentialRace] = [] }
  29. ⛔4UPSFEQSPQFSUZCSBICSBIj final class SharedState: Sendable { nonisolated(unsafe) private var revision

    = 0 private let accessLock = NSLock() func updateRevision(_ newRevision: Int) { accessLock.lock() revision = newRevision accessLock.unlock() } var dangerousArray: [PotentialRace] = [] }
  30. final class SharedState: Sendable { nonisolated(unsafe) private var revision =

    0 private let accessLock = NSLock() func updateRevision(_ newRevision: Int) { accessLock.lock() revision = newRevision accessLock.unlock() } let safeArray = Mutex<[PotentialRace]>([]) }
  31. final class SharedState: Sendable { nonisolated(unsafe) private var revision =

    0 private let accessLock = NSLock() func updateRevision(_ newRevision: Int) { accessLock.lock() revision = newRevision accessLock.unlock() } func getRevision() { accessLock.lock() defer { accessLock.unlock() } return revision } }
  32. final class SharedState: Sendable { nonisolated(unsafe) private var revision =

    0 private let accessLock = NSLock() func updateRevisionAndDoSomething(_ newRevision: Int) async { accessLock.lock() revision = newRevision await doSomething() accessLock.unlock() } }
  33. final class SharedState: Sendable { nonisolated(unsafe) private var revision =

    0 private let accessLock = NSLock() func updateRevisionAndDoSomething(_ newRevision: Int) async { accessLock.lock() revision = newRevision await doSomething() accessLock.unlock() } }
  34. final class SharedState: Sendable { private let revision = Mutex(0)

    func updateRevisionAndDoSomething(_ newRevision: Int) async { revision.withLock { $0 = newRevision } await doSomething() } }
  35. final class SharedState: Sendable { private let revision = Mutex(0)

    func updateRevisionAndDoSomething(_ newRevision: Int) async { revision.withLock { $0 = newRevision } await doSomething() } } @available(macOS 15.0, iOS 18.0) @frozen public struct Mutex<Value> : ~Copyable where Value : ~Copyable
  36. final class CustomMutex<Value>: Sendable { nonisolated(unsafe) private var value: Value

    private let accessLock = NSLock() init(_ value: consuming sending Value) { self.value = value } func withLock<Result, E>( _ body: (inout sending Value) throws(E) -> sending Result ) throws(E) -> sending Result where E: Error { accessLock.lock() defer { accessLock.unlock() } return try body(&value) } }
  37. actor UserActionLogger { private var logs: [UserActionLoggable] func pushLog(_ log:

    UserActionLoggable) async throws { logs.append(log) guard logs.count >= batchRequestSize else { return } let sendingLogs = logs.prefix(batchRequestSize) try await LogAPI.postActionLogs(sendingLogs) let remainingSize = logs.count - sendingLogs.count logs = logs.suffix(remainingSize) } }
  38. actor UserActionLogger { private var logs: [UserActionLoggable] func pushLog(_ log:

    UserActionLoggable) async throws { logs.append(log) guard logs.count >= batchRequestSize else { return } let sendingLogs = logs.prefix(batchRequestSize) try await LogAPI.postActionLogs(sendingLogs) let remainingSize = logs.count - sendingLogs.count logs = logs.suffix(remainingSize) } }
  39. actor UserActionLogger { private var logs: [UserActionLoggable] func pushLog(_ log:

    UserActionLoggable) async throws { logs.append(log) guard logs.count >= batchRequestSize else { return } let sendingLogs = logs.prefix(batchRequestSize) try await LogAPI.postActionLogs(sendingLogs) let remainingSize = logs.count - sendingLogs.count logs = logs.suffix(remainingSize) } }
  40. actor UserActionLogger { private var logs: [UserActionLoggable] func pushLog(_ log:

    UserActionLoggable) async throws { logs.append(log) guard logs.count >= batchRequestSize else { return } let sendingLogs = logs.prefix(batchRequestSize) try await LogAPI.postActionLogs(sendingLogs) let remainingSize = logs.count - sendingLogs.count logs = logs.suffix(remainingSize) } }
  41. actor UserActionLogger { private var logs: [UserActionLoggable] func pushLog(_ log:

    UserActionLoggable) async throws { logs.append(log) guard logs.count >= batchRequestSize else { return } let sendingLogs = logs.prefix(batchRequestSize) try await LogAPI.postActionLogs(sendingLogs) let remainingSize = logs.count - sendingLogs.count logs = logs.suffix(remainingSize) } } try await UserActionLogger.shared.pushLog(someLog)
  42. actor UserActionLogger { private var logs: [UserActionLoggable] func pushLog(_ log:

    UserActionLoggable) async throws { logs.append(log) guard logs.count >= batchRequestSize else { return } let sendingLogs = logs.prefix(batchRequestSize) try await LogAPI.postActionLogs(sendingLogs) let remainingSize = logs.count - sendingLogs.count logs = logs.suffix(remainingSize) } } try await UserActionLogger.shared.pushLog(someLog) try await UserActionLogger.shared.pushLog(someLog)
  43. ⛔$BOUUBLFBTVG fi YPGOFHBUJWFMFOHUI actor UserActionLogger { private var logs: [UserActionLoggable]

    func pushLog(_ log: UserActionLoggable) async throws { logs.append(log) guard logs.count >= batchRequestSize else { return } let sendingLogs = logs.prefix(batchRequestSize) try await LogAPI.postActionLogs(sendingLogs) let remainingSize = logs.count - sendingLogs.count logs = logs.suffix(remainingSize) } } try await UserActionLogger.shared.pushLog(someLog) try await UserActionLogger.shared.pushLog(someLog)
  44. actor UserActionLogger { private var logs: [UserActionLoggable] // count =

    5 func pushLog(_ log: UserActionLoggable) async throws { logs.append(log) guard logs.count >= batchRequestSize else { return } let sendingLogs = logs.prefix(batchRequestSize) try await LogAPI.postActionLogs(sendingLogs) let remainingSize = logs.count - sendingLogs.count logs = logs.suffix(remainingSize) } } try await UserActionLogger.shared.pushLog(someLog) try await UserActionLogger.shared.pushLog(someLog)
  45. actor UserActionLogger { private var logs: [UserActionLoggable] // count =

    5 func pushLog(_ log: UserActionLoggable) async throws { logs.append(log) guard logs.count >= batchRequestSize else { return } let sendingLogs = logs.prefix(batchRequestSize) try await LogAPI.postActionLogs(sendingLogs) // count = 5 let remainingSize = logs.count - sendingLogs.count logs = logs.suffix(remainingSize) } } try await UserActionLogger.shared.pushLog(someLog) try await UserActionLogger.shared.pushLog(someLog)
  46. actor UserActionLogger { private var logs: [UserActionLoggable] // count =

    6 func pushLog(_ log: UserActionLoggable) async throws { logs.append(log) guard logs.count >= batchRequestSize else { return } let sendingLogs = logs.prefix(batchRequestSize) try await LogAPI.postActionLogs(sendingLogs) // count = 5 let remainingSize = logs.count - sendingLogs.count logs = logs.suffix(remainingSize) } } try await UserActionLogger.shared.pushLog(someLog) try await UserActionLogger.shared.pushLog(someLog)
  47. actor UserActionLogger { private var logs: [UserActionLoggable] // count =

    6 func pushLog(_ log: UserActionLoggable) async throws { logs.append(log) guard logs.count >= batchRequestSize else { return } let sendingLogs = logs.prefix(batchRequestSize) try await LogAPI.postActionLogs(sendingLogs) // count = 5 let remainingSize = logs.count - sendingLogs.count logs = logs.suffix(remainingSize) } } try await UserActionLogger.shared.pushLog(someLog) try await UserActionLogger.shared.pushLog(someLog)
  48. actor UserActionLogger { private var logs: [UserActionLoggable] // count =

    6 func pushLog(_ log: UserActionLoggable) async throws { logs.append(log) guard logs.count >= batchRequestSize else { return } let sendingLogs = logs.prefix(batchRequestSize) try await LogAPI.postActionLogs(sendingLogs) // count = 5 let remainingSize = logs.count - sendingLogs.count // 6 - 5 logs = logs.suffix(remainingSize) } } try await UserActionLogger.shared.pushLog(someLog) try await UserActionLogger.shared.pushLog(someLog)
  49. actor UserActionLogger { private var logs: [UserActionLoggable] // count =

    1 func pushLog(_ log: UserActionLoggable) async throws { logs.append(log) guard logs.count >= batchRequestSize else { return } let sendingLogs = logs.prefix(batchRequestSize) try await LogAPI.postActionLogs(sendingLogs) // count = 5 let remainingSize = logs.count - sendingLogs.count logs = logs.suffix(remainingSize) } } try await UserActionLogger.shared.pushLog(someLog) try await UserActionLogger.shared.pushLog(someLog)
  50. actor UserActionLogger { private var logs: [UserActionLoggable] // count =

    1 func pushLog(_ log: UserActionLoggable) async throws { logs.append(log) guard logs.count >= batchRequestSize else { return } let sendingLogs = logs.prefix(batchRequestSize) try await LogAPI.postActionLogs(sendingLogs) // count = 5 let remainingSize = logs.count - sendingLogs.count logs = logs.suffix(remainingSize) } } try await UserActionLogger.shared.pushLog(someLog) try await UserActionLogger.shared.pushLog(someLog)
  51. actor UserActionLogger { private var logs: [UserActionLoggable] // count =

    1 func pushLog(_ log: UserActionLoggable) async throws { logs.append(log) guard logs.count >= batchRequestSize else { return } let sendingLogs = logs.prefix(batchRequestSize) try await LogAPI.postActionLogs(sendingLogs) let remainingSize = logs.count - sendingLogs.count // 1 - 5 logs = logs.suffix(remainingSize) } } try await UserActionLogger.shared.pushLog(someLog) try await UserActionLogger.shared.pushLog(someLog)
  52. ⛔BTVG fi YPGOFHBUJWFMFOHUI actor UserActionLogger { private var logs: [UserActionLoggable]

    // count = 1 func pushLog(_ log: UserActionLoggable) async throws { logs.append(log) guard logs.count >= batchRequestSize else { return } let sendingLogs = logs.prefix(batchRequestSize) try await LogAPI.postActionLogs(sendingLogs) let remainingSize = logs.count - sendingLogs.count logs = logs.suffix(remainingSize) // -4 } } try await UserActionLogger.shared.pushLog(someLog) try await UserActionLogger.shared.pushLog(someLog)
  53. actor UserActionLogger { private var logs: [UserActionLoggable] func pushLog(_ log:

    UserActionLoggable) async throws { logs.append(log) guard logs.count >= batchRequestSize else { return } let sendingLogs = logs.prefix(batchRequestSize) try await LogAPI.postActionLogs(sendingLogs) let remainingSize = logs.count - sendingLogs.count logs = logs.suffix(remainingSize) } } try await UserActionLogger.shared.pushLog(someLog) try await UserActionLogger.shared.pushLog(someLog)
  54. actor UserActionLogger { private var logs: [UserActionLoggable] func pushLog(_ log:

    UserActionLoggable) async throws { logs.append(log) guard logs.count >= batchRequestSize else { return } let sendingLogs = logs.prefix(batchRequestSize) try await LogAPI.postActionLogs(sendingLogs) let remainingSize = logs.count - sendingLogs.count logs = logs.suffix(remainingSize) } } try await UserActionLogger.shared.pushLog(someLog) try await UserActionLogger.shared.pushLog(someLog)
  55. actor UserActionLogger { private var logs: [UserActionLoggable] func pushLog(_ log:

    UserActionLoggable) async throws { logs.append(log) guard logs.count >= batchRequestSize else { return } let sendingLogs = logs.prefix(batchRequestSize) try await LogAPI.postActionLogs(sendingLogs) let remainingSize = logs.count - sendingLogs.count logs = logs.suffix(remainingSize) } } try await UserActionLogger.shared.pushLog(someLog) try await UserActionLogger.shared.pushLog(someLog)
  56. actor UserActionLogger { private var logs: [UserActionLoggable] func pushLog(_ log:

    UserActionLoggable) async throws { logs.append(log) guard logs.count >= batchRequestSize else { return } let sendingLogs = logs.prefix(batchRequestSize) try await LogAPI.postActionLogs(sendingLogs) let remainingSize = logs.count - sendingLogs.count logs = logs.suffix(remainingSize) } } try await UserActionLogger.shared.pushLog(someLog) try await UserActionLogger.shared.pushLog(someLog)
  57. *TPMBUJPOઁয*TPMBUFE1BSBNFUFS actor SomeActor { var mutableState: State } func updateState(of

    someActor: isolated SomeActor) async { let newState = await SomeAPI.fetchNewState() someActor.state = newState }
  58. *TPMBUJPOઁয*TPMBUFE1BSBNFUFS actor SomeActor { var mutableState: State } func updateState(of

    someActor: isolated SomeActor) async { let newState = await SomeAPI.fetchNewState() someActor.state = newState }
  59. *TPMBUJPOઁয*TPMBUFE1BSBNFUFS actor SomeActor { var mutableState: State } func updateState(of

    someActor: isolated SomeActor) async { let newState = await SomeAPI.fetchNewState() someActor.state = newState }
  60. *TPMBUJPO࢚ࣘ.BDSPJTPMBUJPO func updateState(of someActor: isolated SomeActor) async { doSomePreActions() let

    newState = await fetchNewState() someActor.state = newState } func fetchNewState() async -> State { let request = prepareNetworking() let data = await session.data(from: request) let newState = process(data) return newState }
  61. *TPMBUJPO࢚ࣘ.BDSPJTPMBUJPO func updateState(of someActor: isolated SomeActor) async { doSomePreActions() let

    newState = await fetchNewState() someActor.state = newState } func fetchNewState() async -> State { let request = prepareNetworking() let data = await session.data(from: request) let newState = process(data) return newState }
  62. *TPMBUJPO࢚ࣘ.BDSPJTPMBUJPO func updateState(of someActor: isolated SomeActor) async { doSomePreActions() let

    newState = await fetchNewState() someActor.state = newState } func fetchNewState() async -> State { let request = prepareNetworking() let data = await session.data(from: request) let newState = process(data) return newState }
  63. *TPMBUJPO࢚ࣘ.BDSPJTPMBUJPO func updateState(of someActor: isolated SomeActor) async { doSomePreActions() let

    newState = await fetchNewState() someActor.state = newState } func fetchNewState() async -> State { let request = prepareNetworking() let data = await session.data(from: request) let newState = process(data) return newState }
  64. *TPMBUJPO࢚ࣘ.BDSPJTPMBUJPO func updateState(of someActor: isolated SomeActor) async { doSomePreActions() let

    newState = await fetchNewState() someActor.state = newState } func fetchNewState() async -> State { let request = prepareNetworking() let data = await session.data(from: request) let newState = process(data) return newState }
  65. *TPMBUJPO࢚ࣘ.BDSPJTPMBUJPO func updateState(of someActor: isolated SomeActor) async { doSomePreActions() let

    newState = await fetchNewState() someActor.state = newState } func fetchNewState() async -> State { let request = prepareNetworking() let data = await session.data(from: request) let newState = process(data) return newState }
  66. *TPMBUJPO࢚ࣘ.BDSPJTPMBUJPO func updateState(of someActor: isolated SomeActor) async { doSomePreActions() let

    newState = await fetchNewState() someActor.state = newState } func fetchNewState() async -> State { let request = prepareNetworking() let data = await session.data(from: request) let newState = process(data) return newState }
  67. *TPMBUJPO࢚ࣘ.BDSPJTPMBUJPO func updateState(of someActor: isolated SomeActor) async { doSomePreActions() let

    request = prepareNetworking() let data = await session.data(from: request) let newState = process(data) someActor.state = newState }
  68. *TPMBUJPO࢚ࣘ.BDSPJTPMBUJPO func updateState(of someActor: isolated SomeActor) async { doSomePreActions() let

    request = prepareNetworking() let data = await session.data(from: request) let newState = process(data) someActor.state = newState }
  69. *TPMBUJPO࢚ࣘ.BDSPJTPMBUJPO func updateState(of someActor: isolated SomeActor) async { doSomePreActions() let

    request = prepareNetworking() let data = await session.data(from: request) let newState = process(data) someActor.state = newState } 4PNF"DUPS
  70. *TPMBUJPO࢚ࣘ.BDSPJTPMBUJPO func updateState(of someActor: isolated SomeActor) async { doSomePreActions() let

    request = prepareNetworking() let data = await session.data(from: request) let newState = process(data) someActor.state = newState } 4PNF"DUPS (MPCBM
  71. *TPMBUJPO࢚ࣘ.BDSPJTPMBUJPO func updateState(of someActor: isolated SomeActor) async { doSomePreActions() let

    request = prepareNetworking() let data = await session.data(from: request) let newState = process(data) someActor.state = newState } 4PNF"DUPS (MPCBM (MPCBM
  72. *TPMBUJPO࢚ࣘ.BDSPJTPMBUJPO func updateState(of someActor: isolated SomeActor) async { doSomePreActions() let

    request = prepareNetworking() let data = await session.data(from: request) let newState = process(data) someActor.state = newState } 4PNF"DUPS (MPCBM (MPCBM (MPCBM
  73. *TPMBUJPO࢚ࣘ.BDSPJTPMBUJPO func updateState(of someActor: isolated SomeActor) async { doSomePreActions() let

    request = prepareNetworking() let data = await session.data(from: request) let newState = process(data) someActor.state = newState } 4PNF"DUPS (MPCBM (MPCBM (MPCBM 4PNF"DUPS
  74. *TPMBUJPO࢚ࣘ.BDSPJTPMBUJPO func updateState(of someActor: isolated SomeActor) async { doSomePreActions() let

    request = prepareNetworking() let data = await session.data(from: request) let newState = process(data) someActor.state = newState } 4PNF"DUPS (MPCBM (MPCBM (MPCBM 4PNF"DUPS
  75. *TPMBUJPO࢚ࣘ.BDSPJTPMBUJPO func updateState(of someActor: isolated SomeActor) async { doSomePreActions() let

    request = prepareNetworking() let data = await session.data(from: request) let newState = process(data) someActor.state = newState } 4PNF"DUPS (MPCBM (MPCBM (MPCBM 4PNF"DUPS
  76. *TPMBUJPO࢚ࣘ.BDSPJTPMBUJPO func updateState(of someActor: isolated SomeActor) async { doSomePreActions() let

    newState = await fetchNewState() someActor.state = newState } func fetchNewState() async -> State { let request = prepareNetworking() let data = await session.data(from: request) let newState = process(data) return newState }
  77. *TPMBUJPO࢚ࣘ.BDSPJTPMBUJPO func updateState(of someActor: isolated SomeActor) async { doSomePreActions() let

    newState = await fetchNewState() someActor.state = newState } func fetchNewState() async -> State { let request = prepareNetworking() let data = await session.data(from: request) let newState = process(data) return newState }
  78. *TPMBUJPO࢚ࣘ.BDSPJTPMBUJPO func updateState(of someActor: isolated SomeActor) async { doSomePreActions() let

    newState = await fetchNewState() someActor.state = newState } func fetchNewState( isolation: isolated (any Actor)? = #isolation ) async -> State { let request = prepareNetworking() let data = await session.data(from: request) let newState = process(data) return newState }
  79. *TPMBUJPO࢚ࣘ.BDSPJTPMBUJPO func updateState(of someActor: isolated SomeActor) async { doSomePreActions() let

    request = prepareNetworking() let data = await session.data(from: request) let newState = process(data) someActor.state = newState }
  80. *TPMBUJPO࢚ࣘ.BDSPJTPMBUJPO func updateState(of someActor: isolated SomeActor) async { doSomePreActions() let

    request = prepareNetworking() let data = await session.data(from: request) let newState = process(data) someActor.state = newState }
  81. *TPMBUJPO࢚ࣘ.BDSPJTPMBUJPO func updateState(of someActor: isolated SomeActor) async { doSomePreActions() let

    request = prepareNetworking() let data = await session.data(from: request) let newState = process(data) someActor.state = newState } 4PNF"DUPS
  82. *TPMBUJPO࢚ࣘ.BDSPJTPMBUJPO func updateState(of someActor: isolated SomeActor) async { doSomePreActions() let

    request = prepareNetworking() let data = await session.data(from: request) let newState = process(data) someActor.state = newState } 4PNF"DUPS (MPCBM
  83. *TPMBUJPO࢚ࣘ.BDSPJTPMBUJPO func updateState(of someActor: isolated SomeActor) async { doSomePreActions() let

    request = prepareNetworking() let data = await session.data(from: request) let newState = process(data) someActor.state = newState } 4PNF"DUPS (MPCBM 4PNF"DUPS
  84. 3FHJPO#BTFE*TPMBUJPO ⛔4FOEJOHrVOTBGF*OGPSNBUJPOsSJTLTj Task { var unsafeInformation = NonSendableInfo() await someActor.add(unsafeInformation)

    unsafeInformation.mutate() } actor SomeActor { func add(_ information: sending NonSendableInfo) }
  85. 3FHJPO#BTFE*TPMBUJPO actor SomeActor { var informations: [NonSendableInfo] func getLastInformation() ->

    sending NonSendableInfo { return informations.removeLast() // Not allowed! } }
  86. 3FHJPO#BTFE*TPMBUJPO actor SomeActor { var informations: [NonSendableInfo] func getLastInformation() ->

    sending NonSendableInfo { return NonSendableInfo(copying: informations.removeLast()) } }
  87. 2"