🔖
【Swift】@_implicitSelfCaptureについて
@_implicitSelfCaptureとは
escaping属性が指定されているクロージャ内でselfを参照し、そのselfが参照型である場合は基本的にselfを付けて明示的にキャプチャを行わなければなりません。
この制約を排除できるのが@_implicitSelfCaptureです。
以下のコードでは、escaping属性が指定されているクロージャ内でselfを参照していますが、明示的なキャプチャが行われていないため、コンパイルエラーが発生しています。
var someAction: () -> Void = {}
func setAction(_ action: @escaping () -> Void) {
someAction = action
}
class Sample {
var value = 0
func action() {
setAction {
value = 777 // 【Error】
}
}
}
// ※ メモリリークに関しては無視してください。
setActionの引数に@_implicitSelfCaptureを付与すると、上記のエラーは発生しなくなります。
var someAction: () -> Void = {}
func setAction(@_implicitSelfCapture _ action: @escaping () -> Void) { // 変更
someAction = action
}
class Sample {
var value = 0
func action() {
setAction {
value = 777
}
}
}
// ※ メモリリークに関しては無視してください。
@_implicitSelfCaptureはどこで使われているのか
@_implicitSelfCaptureはTaskのイニシャライザの引数operationなどに対して付けられています。

そのためTask内では、明示的なキャプチャを示すためのselfを記入する必要はありません。
@MainActor
final class ViewModel: ObservableObject {
@Published private(set) var num = 0
func action() {
Task {
try? await Task.sleep(for: .seconds(3))
num += 1
}
}
}
※ 本題から逸れますが、operationがViewModelインスタンスを強参照するため、解放遅延が生じる可能性があります。
参考
Discussion