Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up for free
Swift Concurrency入門
Sato Takeshi
February 22, 2022
Technology
10
2.4k
Swift Concurrency入門
集まれSwift好き!Swift愛好会 vol.65 @ オンライン
https://love-swift.connpass.com/event/238725/
発表資料
Sato Takeshi
February 22, 2022
Tweet
Share
More Decks by Sato Takeshi
See All by Sato Takeshi
Meet passkeys
satotakeshi
2
210
What's new in Vision
satotakeshi
0
500
複数端末のつらさを乗り越えてiOS UITestを実行
satotakeshi
1
250
Xcodegenを個人アプリに導入
satotakeshi
3
510
SwiftUIで作る開閉式メニュー
satotakeshi
3
2.2k
swift-snapshot-testingでVisual Testingを効率化
satotakeshi
0
740
SwiftUIのデータ管理
satotakeshi
6
1.3k
iOS14のTips&Tricks
satotakeshi
1
450
XCUITestのつらさを乗り越えて、iOSアプリにUITestを導入する
satotakeshi
9
7k
Other Decks in Technology
See All in Technology
JAWS-UG 横浜 #54 資料
takakuni
0
210
書籍を書きました。 そう、VS Codeで。
takumanakagame
4
4.2k
PCI DSS に準拠したシステム開発
yutadayo
0
310
NGINXENG JP#2 - 3-NGINX Plus・プロダクトのアップデート
hiropo20
0
220
スクラム導入して変わったチーム、組織のありかた
yumechi
0
180
経営統合をきっかけに会社をエンジニアリングした話 / btconjp-2023
carta_engineering
0
150
MarvelClient Upgrade 64bit クライアントへの自動アップグレード設定
mitsuru_katoh
0
120
データ分析基盤の要件分析の話(202201_JEDAI)
yabooun
0
240
Hatena Engineer Seminar #23 「チームとプロダクトを育てる Mackerel 開発合宿」
arthur1
0
360
証明書って何だっけ? 〜AWSの中間CA移行に備える〜
minorun365
3
2.1k
Airdrop for Open Source Projects
epicsdao
0
650
2年で10→70人へ! スタートアップの 情報セキュリティ課題と施策
miekobayashi
1
470
Featured
See All Featured
The Mythical Team-Month
searls
210
40k
JazzCon 2018 Closing Keynote - Leadership for the Reluctant Leader
reverentgeek
175
9.1k
Mobile First: as difficult as doing things right
swwweet
213
7.8k
Rebuilding a faster, lazier Slack
samanthasiow
69
7.5k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
351
21k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
152
13k
Building an army of robots
kneath
301
40k
Designing for Performance
lara
600
65k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
657
120k
Large-scale JavaScript Application Architecture
addyosmani
499
110k
VelocityConf: Rendering Performance Case Studies
addyosmani
317
22k
Producing Creativity
orderedlist
PRO
335
38k
Transcript
Swift Concurrency 入門 2022 年 2 月 22 日 集まれ
Swift 好き! Swift 愛好会 vol.65 @ オンライン
Who am I • Name • 佐藤タケシ ( さとうたけし )
• Company • Merpay, Inc.(2019/01 ~) • Role • Software Engineer (iOS) • Account • Twitter: @hatakenokakashi • Facebook: 佐藤剛士 • GitHub: SatoTakeshiX
• 一冊で Swift Concurrency の概 要を理解ことを目指して書いて います • まだ執筆中 •
Swift Concurrency は新しい概 念が盛りだくさん • 覚えればあなたの開発がより安 全に、簡単に実装できるように なる 「Swift Concurrency入門」で技術 書典で販売予定
Swift Concurrency • Swift 5.5 から導入 • Xcode 13 から利用可能
• 非同期処理が簡潔、安全に • async/await が Swift にやってき た!
コールバックによる 非同期処理の 欠点
ネストが深くなる
コールバックの呼び忘れ
コールバックの呼び忘れ コールバックを呼ばないで returnしている
呼び出し元で不具合発生 コールバックが呼ばれないので、 エラーが起きているのに、 ローディングビューがずっと出しっぱな しになるかもしれない
async/awaitで解決
async/awaitで非同期処理 • async で非同期関数を定義
async/awaitで非同期処理 • 呼び出し元
非同期関数 • async がつけられた関数・メソッド • プログラムを待機、再開させる • 通常のコードと同じように記述ができる ◦ 呼び出し元で、変数の代入や
try-catch によるエラーハンドリング ◦ 戻り値を定義できるのでコールバックのよう呼び忘れがない。コンパイルの チェックが入る • スレッドは CPU のコア数分用意される ◦ システムが管理し、開発者が直接触ることはない
awaitでプログラムが待機する
awaitでプログラムが待機する
awaitでプログラムが待機する
順次実行の実装の違い
順次実行をする by 同期関数 ネストが深くなる
順次実行をする by 非同期関数
並列実行の実装の違い
並列実行をする by 同期関数
並列実行をする by 非同期関数
データ競合を防ぐ新しい型 Actor
データ競合(Data Race)とは? • 複数のスレッドがデータに同時にアクセスしたためにデータが不正になる状況 ◦ スレッドの少なくとも一つが値を書き込む 値 スレッド 1 スレッド
2
データ競合(Data Race)
データ競合(Data Race) playgroundで実行すると 110,110が出力される場合がある
actorの特徴 • 新しい型の種類 • 参照型 • インスタンスに外からアクセスは同時にひとつのみに限定される ◦ Actor 隔離(
Actor isolated) と呼ぶ ◦ data race を防ぐ • 外からアクセスする場合は await が必要 • イニシャライザー、プロパティ、メソッド定義、プロトコル適応など class, struct, enum を同じ特徴をもつ
actorでデータ競合を防ぐ
actorでデータ競合を防ぐ 必ず100, 110が順不同で出力される -> データ競合がなくなる
actorで競合状態(Race Condition)は防げない • 競合状態 (Race Condition) マルチスレッドにおける典型的な不具合の一つ • プログラミングの実行結果が各スレッドの実行順に依存する状態 ◦
同じ入力を与えても異なるデータを出力する状態
actorで競合状態(Race Condition)は防げない
actorで競合状態(Race Condition)は防げない
actorで競合状態(Race Condition)は防げない 1. ③、④が同時に呼び出す 2. キャッシュはまだない 3. ③が①に到達。待機 4. ④が①に到達。待機
5. ③が再開。👾を返す。 6. ③が②に到達。 return する 7. ④が再開。🎃を返す。 8. ④が②に到達。 return する 9. ③、④同じ URL なのに違うコ ンテンツが返される=>競合 状態
競合状態(Race Condition)の修正 • await の後でプロパティの チェックする • Protect mutable state
with Swift actorsに Task を使った例もあり
MainActor • メインスレッドで実行される特別な Actor • Global Actor の一種 ◦ むしろメインスレッドのために
Global Actor が提案された ◦ 共有の actor インスタンスを通して Actor 分離がされる • @MainActor で型全部、プロパティのみ、メソッドのみなど適応できる
MainActorの適応方法 • MainActor の適応手順をコードで示す
Task
Task • 並行処理の基本単位。すべての非同期関数は Task を通して実行される • 各 Task を Task
Tree とよばれる親子関係を構築する • Task Tree のおかげでキャンセルや優先度をシンプルにハンドリング可能 ◦ 従来の方法だとあるスレッドの処理がキャンセルされた場合に他のスレッドの処 理に伝播させるのが難しかった
Task Tree • ①一番下位のタ スクがすべて終わ ると上位のタスク が始まる • ②子タスクが終わ ると親タスクに伝
播 • ③親タスクが実行
Task Tree • ①がエラー -> 兄弟 タスクはキャンセ ル② • 上位のタスク③が
キャンセル。兄弟 タスク④もキャン セル • ④の下位タスク⑤ もキャンセル • ⑥親タスクに①の エラー伝播
async letバインディングとTask Tree
async letバインディングとTask Tree 親タスク 子タスク 子タスク
同期関数から非同期関数を呼ぶ方法 Task イニシャライザー • 非同期コンテキストを提供 • 同期関数内から非同期関数を呼べる • コールバックはすぐに呼ばれる •
返り値の Task インスタンスからマニュアルで キャンセルできる • 親タスクの優先度や actor, タスクローカル値 を引き継ぐ Task.detached • 非同期コンテキストを提供 • 同期関数内から非同期関数を呼べる • コールバックはすぐに呼ばれる • 返り値の Task インスタンスからマニュアルで キャンセルできる • 親タスクの優先度や actor, タスクローカル値 を引き継がない
TaskイニシャライザーとTask.detached • Task.detached は MainActor を引き継 がない -> ログ送信な どメインスレッドで不
要な処理に向く • Task は MainActor を 引き継ぐ -> メインス レッドで実行
マニュアルキャンセル • Task のイニシャライザーを保持しておけば、キャ ンセルが必要なときに cancel メソッドでキャンセル できる
キャンセルのハンドリング • checkCancellation: Task が キャンセルされている場合に CancellationError を返す ◦ キャンセルを呼び出し元
に伝える • isCancelled: キャンセルかど うか Bool 値で判断 ◦ キャンセル時追加処理が 可能 独自の追加処理
iOS 13, 14で非同期関数を使う
XcodeのリリースとSwift Concurrency対応状況 • Xcode 13 ◦ 2021 年 9 月
21 日リリース ◦ Swift Concurrency 機能は iOS 15 のみ • Xcode 13.2 ◦ 2021 年 12 月 13 日リリース ◦ Swift Concurrency 機能が iOS 13, 14 にもバックポートされた ◦ ただし Swift パッケージがビルドできない不具合が見つかる • Xcode 13.2.1 ◦ 2021 年 12 月 17 日リリース ◦ Swift パッケージの不具合を修正
iOS 13, 14で非同期関数を使う • 言語機能としての Swift Concurrency 機能は使える • Foundation
での非同期関数は iOS 15 以上 ◦ URLSession の data メソッドなど • withCheckedThrowingContinuation と withCheckedContinuation で既存の コールバック関数を非同期関数にラップができる • アプリサポートバージョンが iOS 15 が下限になるまではラップした関数を呼び出 す
withCheckedContinuation • エラーをスローするしないコールバック関数を非同期関数にラップする • クロージャー内でラップする関数を呼ぶ • ラップする関数のコールバック内で continuation は確実に一回 resume
メソッドを 呼び出す ◦ 呼び出さないのはだめ ◦ 2回以上呼び出すのもだめ
withCheckedContinuation •
withCheckedThrowingContinuation • エラーをスローするコールバック関数を非同期関数にラップする • クロージャー内でラップする関数を呼ぶ • ラップする関数のコールバック内で continuation は確実に一回 resume
メソッドを 呼び出す • resume(returning:) メソッド ◦ ラップした関数の戻り値を引数にする • resume(with: ) ◦ Result 型で返す • continuation.resume(throwing:) ◦ エラー型で返す
withCheckedThrowingContinuation •
まとめ
まとめ • async/await で非同期処理を同期関数のように記述できるようになった • それによって読みやすさが向上し、コールバックの呼び忘れなどのミスを防 げるようになった • マルチスレッドでよくある不具合、データ競合を防ぐ新しい型、 actor
が登場 した ◦ ただし、競合状態はまだ防げない • 非同期処理は Task という単位で行われる • iOS 13, 14 でも Swift Concurrency は使える
参考資料 • Race condition vs. Data Race: the differences explained
• データ競合 (data race) と競合状態 (race condition) を混同しない • Protect mutable state with Swift actors • https://github.com/apple/swift-evolution/blob/main/proposals/0316-glo bal-actors.md • Explore structured concurrency in Swift • Meet async/await in Swift