🔖
【Swift Concurrency】引数に付与するsendingキーワードについて
sending
キーワード
引数に付与する現在sending
キーワードは、「引数に付与するケース」と「返り値に付与するケース」があります。本記事では、引数に付与する場合のsending
キーワードについて解説していきます。
引数に付与するsending
キーワードは、「関数がnon-Sendable
な値を引数として受け取るときに、その値が呼び出し元で引き渡し後に使用されないこと」を保証させるキーワードです。
これにより、引数として受け取ったnon-Sendable
な値が隔離境界(isolation boundary
)を超えることができるようになります。[1]
以下のコードでは、action2
関数内でNonSendableClass
のインスタンスを生成し、action1
関数の引数として、生成したインスタンスを渡しています。
class NonSendableClass { var num = 0 }
func action1(nonSendableClass: sending NonSendableClass) {
Task { @MainActor in
print(nonSendableClass)
}
}
func action2() {
let nonSendableClass = NonSendableClass()
action1(nonSendableClass: nonSendableClass)
}
action1
関数の引数として受け取るNonSendableClass
のインスタンスは、action1
関数内でnon-isolated
な隔離領域からMainActor
の隔離領域に渡ります。(つまりは隔離境界を超える。)
そのため、「関数がnon-Sendable
な値を引数として受け取るときに、その値が呼び出し元で引き渡し後に使用されないこと」を保証させるsending
キーワードが必要です。
蛇足
もし、以下コードのように引き渡し後にnonSendableClass
にアクセスした場合は、エラーで教えてくれます。
class NonSendableClass { var num = 0 }
func action1(nonSendableClass: sending NonSendableClass) {
Task { @MainActor in
print(nonSendableClass)
}
}
func action2() {
let nonSendableClass = NonSendableClass()
action1(nonSendableClass: nonSendableClass) // ※1
print(nonSendableClass) // nonSendableClassにアクセス
}
// ※1: Sending 'nonSendableClass' risks causing data races
参考
Xcode 16 & Swift 6 キャッチアップ: Swift Concurrencyの基礎と最重要ポイントを総復習 - YouTube
swift-evolution/proposals/0430-transferring-parameters-and-results.md at main · swiftlang/swift-evolution · GitHub
-
このような隔離境界を超えることができる値を
sending value
と呼びます。 ↩︎
Discussion