(discord/swift/2018/03/13/0) inout atributeの挙動について
概要
- discord ios dev
- #swift
- 2018/03/13
- inout atributeの挙動について
log
koher
- 2018/03/13
最近、 inout 的に @escaping
なクロージャ式の中からアクセスできないようにするけど、特に out
したいわけじゃないというのを表せるものがあればいいんじゃないかという気がしてるですがどうでしょう
↓の asyncAfter
のクロージャ式から p
にアクセスするのを防ぎたい。
import Foundation func foo() { let a = [2, 3, 5] a.withUnsafeBufferPointer { p in DispatchQueue.global().asyncAfter(deadline: .now() + .seconds(3)) { print(p[0]) } } } foo() Thread.sleep(forTimeInterval: 5)
0
omochimetaru
- 2018/03/13
エスケープさせたくないってことですか?
koher
- 2018/03/13
↑だと a が解放された後にそのバッファのポインタ p
にアクセスしちゃってるよね?
omochimetaru
- 2018/03/13
そうですね、これはだめ
koher
- 2018/03/13
↓だと inout だからコンパイルエラーになる。
import Foundation func foo() { var a = [2, 3, 5] a.withUnsafeMutableBufferPointer { p in DispatchQueue.global().asyncAfter(deadline: .now() + .seconds(3)) { print(p[0]) } } } foo() Thread.sleep(forTimeInterval: 5)
'escaping closures can only capture inout parameters explicitly by value'
closure_implicit_capture_without_noescape <- (DiagnosticSema.def)
omochimetaru
- 2018/03/13
あ〜、なるほど、inout的にってそういう意味か。
koher
- 2018/03/13
withUnsafeBufferPointer
はクロージャに渡される引数がそのクロージャ式のスコープの中でのみ有効なのに、せっかく @escaping
を区別してるのにコンパイラがそれを強制する術がない。
omochimetaru
- 2018/03/13
え、もう一個のケースでも、pはinoutじゃないのでは?
普通の引数で型がUnsafeMutableBufferPointerですよね
koher
- 2018/03/13
それが inout なんですよ。意味わかんないんだけど。
あれ?違う??
omochimetaru
- 2018/03/13
public mutating func withUnsafeMutableBufferPointer<R>(_ body: (inout UnsafeMutableBufferPointer<Array.Element>) throws -> R) rethrows -> R
ほんとだ、あれ?なにこれ。
koher
- 2018/03/13
いや、あってた。
withUnsafeMutableBufferPointer(_:) - Array | Apple Developer Documentation
なんで inout なのかもよくわかんないんだけど、とりあえずそれのおかげで↑の asyncAfter
に渡すのはコンパイラが防いでくれる。
で、この inout
の out
の除いたようなものがほしいなぁと。
あと、↓みたいなのも防げるかと。
fooAsync { [weak self] in guard let zelf = self else { return } zelf.foo(...) barAsync { [weak zelf] in // ←この [weak zelf] を忘れないようにしたい guard let zelf = zelf else { return } zelf.bar(...) } }
rintaro
- 2018/03/13
クラッシャー
func after(_ fn: @escaping () -> Void) {} func with(_ fn: (inout Int) -> Void ) {} func test() { with { p in after { [p] in } } }
koher
- 2018/03/13
@rintaro それは明示的だから仕方ないですw
明示的にしかできなくできたらいいかなと。