Slide 1

Slide 1 text

Swift 6.2時代の concurrencyを考える会 @ynoseda

Slide 2

Slide 2 text

Swift 6.2の新しい機能 ● Approachable concurrency ● Default Actor Isolation ● @concurrent

Slide 3

Slide 3 text

Swift 6.2の新しい機能 ● Approachable concurrency ● Swift 6だと以下の2つを有効にするのと同じ ○ NonisolatedNonsendingByDefault ○ InferIsolatedConformances

Slide 4

Slide 4 text

Swift 6.2の新しい機能 ● Approachable concurrency ● Swift 5だと以下の5つを有効にするのと同じ ○ NonisolatedNonsendingByDefault ○ InferIsolatedConformances ○ InferSendableFromCaptures ○ DisableOutwardActorInference ○ GlobalActorIsolatedTypesUsability

Slide 5

Slide 5 text

NonisolatedNonsendingByDefault ● nonisolatedな非同期関数の挙動が変わる ● https://docs.swift.org/compiler/documentation/diagnostics/nonisolated-nonsen ding-by-default/ ● NonisolatedNonsendingByDefaultが無効 ○ nonisolatedな非同期関数はsendingがデフォルト ● NonisolatedNonsendingByDefaultが有効 ○ nonisolatedな非同期関数はnonsendingがデフォルト ○ asyncなnonisolated関数を呼んだとき、呼び出し元の actor上で処理が実行される ○ MainActorから呼び出すとMainActorで実行されるようになる

Slide 6

Slide 6 text

InferIsolatedConformances ● isolated conformanceの概念が導入される ● https://github.com/swiftlang/swift-evolution/blob/main/proposals/0470-isolated- conformances.md ● nonisolatedなprotocolをactor隔離された状態でのみ適合する感じ ● MainActorのclassにprotocolの準拠を追加しようとしたとき、protocolが nonisolatedを要求していて困っていた事象が解決される ○ NonisolatedNonsendingByDefault ○ InferIsolatedConformances

Slide 7

Slide 7 text

Default Actor Isolation ● 何もactorを指定してない状態のときにnonisolatedとMainActorのどちらをデフォル トにするか設定できる ● Default Actor IsolationをMainActorにしているとSwift 5系までと近い感覚で実装 できるようになる

Slide 8

Slide 8 text

@concurrent ● DispatchQueue.globalみたいなもの ● バックグラウンドで処理したい関数に@concurrentをつけるだけでよくなる

Slide 9

Slide 9 text

Swift 6.2時代のconcurrency ● Default Actor Isolation = MainActor ● Approachable concurrency = true ● こうするとどうなるか?

Slide 10

Slide 10 text

Swift 6.2時代のconcurrency ● Default Actor Isolation = MainActor & Approachable concurrency = true ● 非同期処理が必要になるまでは全てがMainActorになる

Slide 11

Slide 11 text

Swift 6.2時代のconcurrency ● Default Actor Isolation = MainActor & Approachable concurrency = true ● 非同期処理が必要になるまでは全てがMainActorになる ○ static varも許される ○ Swift 5系と同じ感覚で実装できる

Slide 12

Slide 12 text

Swift 6.2時代のconcurrency ● Default Actor Isolation = MainActor & Approachable concurrency = true ● 非同期処理が必要になるまでは全てがMainActorになる ● 非同期処理が必要な場合も基本的に async 関数にするだけでいい ● URLSessionなど標準のAPIのasync関数を叩く時もMainActorから叩いていい ● 良い感じに必要ならバックグラウンドスレッドで処理してくれる

Slide 13

Slide 13 text

● Default Actor Isolation = MainActor & Approachable concurrency = true ● 非同期処理が必要になるまでは全てがMainActorになる ● 非同期処理が必要な場合も基本的に async 関数にするだけでいい ● 重い処理をバックグラウンドで処理したい場合は@concurrentを付けるだけでいい ● 同じactorで処理したい要件が出てくるまで(非同期処理に真面目に向き合う必要 が出るまで)はactorをあまり意識しなくていい Swift 6.2時代のconcurrency

Slide 14

Slide 14 text

Swift 5からSwift 6で苦しんでいる人へ ● Default Actor Isolation = MainActor & Approachable concurrency = true ● この設定でかなり修正量が減るのでおすすめ ● Xcode 26対応と合わせてSwift 6対応を進めるのが良い感じ

Slide 15

Slide 15 text

iOSアプリでどこまでactorを意識する? ● 同じactorでも同じスレッドで処理するわけじゃない ● 同じactorのインスタンスを作ってawait関数を2回叩いたら、違うスレッドで処理され ることもある ● nonisolatedな関数を叩いたときにスレッドが変わる?変わらない ● そもそもnonisolatedとかnonsendingとか何 ● etc

Slide 16

Slide 16 text

iOSアプリでどこまでactorを意識する? ● Swift5系まで意識しなかったはずのあれこれが、Swift 6~6.1では意識させられるよ うになった ● Swift 6.2 x Approachable Concurrency x Default Actor Isolation = MainActorで 「必要になるまでは意識しない」という環境になった

Slide 17

Slide 17 text

大規模アプリならactorを意識する? ● アーキテクチャーとしてマルチパッケージでわけている場合に、全てをDefault Actor Isolation = MainActorにすべき? ● 例えばRepositoryか実際のデータアクセスはactorにすべき? ● Entityはnonisolatedの方がいい?

Slide 18

Slide 18 text

大規模アプリならactorを意識する? ● アーキテクチャーとしてマルチパッケージでわけている場合に、全てをDefault Actor Isolation = MainActorにすべき? ○ できれば全部MainActorの方が考えることは少ないかも ○ でも明確にactor isolationを意識する必要がある部分をパッケージにわけているなら、 Default Actor Isolationをnonisolatedにしてもいいかも ● 例えばRepositoryか実際のデータアクセスはactorにすべき? ○ 実際のデータアクセスが例えば URLSessionなら勝手にバックグラウンドスレッドで処理してくれる はずなので、MainActorでいい ○ 画像のdecode処理などで特定の重い処理を隔離したい場合は actorにする ● Entityはnonisolatedの方がいい? ○ MainActor外からも呼び出される可能性がある場合は nonisolatedが良い ○ 多分App Intentsとかから呼び出されることとかも考慮すると nonisolatedで良いかも