Swift 3, tüm kapanışları
Hayır, Swift 3'te, yalnızca kapatma işlev argümanları (kendileri fonksiyonlardır yani fonksiyon girişler) tarafından sigara kaçan olan varsayılan olarak sigara kaçan vardır varsayılan (SE-0103 uyarınca). Örneğin:
class A {
let n = 5
var bar :() -> Void = {}
func foo(_ closure:() -> Void) {
bar = closure // As closure is non-escaping, it is illegal to store it.
}
func baz() {
foo {
// no explict 'self.' required in order to capture n,
// as foo's closure argument is non-escaping,
// therefore n is guaranteed to only be captured for the lifetime of foo(_:)
print(n)
}
}
}
yukarıdaki örnekte closure
olmayan çıkış, hafızaya alınabilir veya bu şekilde fonksiyon foo(_:)
ömrü ile ömrünü sınırlayan, yakalanan yasaklanmış edilir. Bu nedenle, yakaladığı herhangi bir değerin, işlev çıktıktan sonra yakalanmayacağı garanti edilir - bu, döngü tutma gibi yakalama ile oluşabilecek sorunlardan endişelenmeniz gerekmediği anlamına gelir. Ancak
, bir kapak depolanmış özelliği (yukarıdaki örnekte olduğu gibi bar
) tanımı ömrü gibi (o @noescape
ile işaretlemek için anlamsız olacaktır) kaçan tarafından olmayan belirli bir işleve sınırlı - o (ve dolayısıyla yakalanan tüm değişkenler), verilen örnek bellekte kaldığı sürece bellekte kalır. Bu nedenle döngüleri tutma gibi problemlere kolayca yol açabilir, bu nedenle, yakalama semantiklerini açık hale getirmek için açık bir self.
kullanmanız gerekir. someClosure
kuvvetle self
yakalar olarak
noktada Aslında, durumda, örnek kod, çağrılan viewDidLoad()
üzerine bir muhafaza döngüsü yaratacak ve bir depolanmış özellik olduğu gibi self
şiddetle someClosure
başvurur. Tabii
, sen @noescape
özellik kullanmak edebilmek için beklenebilir bir yerde bir işlevde yerel değişken olan bir kapatma üzerindedir. Böyle bir kapanış, işlevin dışında saklanmadığı veya yakalanmadığı sürece öngörülebilir bir ömre sahip olacaktır. Örneğin: @noescape
Swift 3'te kaldırılıyor olarak
class A {
let n = 5
func foo() {
let f : @noescape() -> Void = {
print(n)
}
f()
}
}
yazık ki, bu (İlginç olan Xcode 8 GM, bu mümkün, ama bir kullanımdan kaldırılması uyarı vermesidir) mümkün olmayacaktır. Jon Shier says olarak, dilin yeniden eklenmesini beklememiz gerekecek.
Açıklama için teşekkür ederiz! Sadece, kontrolörün kendisinin tahsis edildiği zaman, kapatmanın ve görünümün de tahsis edileceği veya bir bellek sızıntısına neden olabileceği açıklığa kavuşturmak için mi? – beingadrian
@beingadrian 'SomeClosure 'özelliğinize' self '(örneğin viewDidLoad'daki örneğinizde olduğu gibi) yakalayan bir kapak atandığında, gerçekten bir kurtarma döngüsü oluşturacaktır ve bu nedenle başka bir güçlü olmadığında sızacaktır görünüm denetleyicinize yapılan başvurular (bu görünümü, görüntü denetleyicinizin sınıfında bir 'print' ifadesiyle 'deinit' uygulayarak kendiniz doğrulayabilirsiniz). En basit çözüm, “ben” i “zayıf” olarak ele almaktır (kapanmayı “{[zayıf benlik” in ...}) olarak tanımlar. Daha sonra kapağın içindeki isteğe bağlı zincirlemeyi, görünümün katmanını atayabilmek için kullanabilirsiniz, 'self? .view.layer = CALayer()' – Hamish
@beingadrian Başka bir potansiyel çözüm, 'kendini' kapamada 'unowned 'olarak yakalamaktır. Görünüm denetleyici örneği ayrıldıktan sonra kapatma işlemi başlatılırsa çökme olasılığı yüksek olabilir. Bu nedenle, sadece 'someClosure' bir 'private' özelliği ise bunu yapmamızı tavsiye ederim (o zaman başka bir sınıfın referans almasına imkan yok). – Hamish