Ở đây, tôi đã chơi với rò rỉ, vì vậy tôi đã thực hiện một chu kỳ tham khảo mạnh mẽ cố ý để xem các dụng cụ sẽ phát hiện một cái gì đó, và tôi có kết quả không mong muốn. Sự rò rỉ được hiển thị trong các dụng cụ chắc chắn có ý nghĩa, nhưng vụ tai nạn ngẫu nhiên là một chút bí ẩn (do hai sự kiện tôi sẽ đề cập sau).Sử dụng unowned bên trong một danh sách chụp gây ra một vụ tai nạn ngay cả khối chính nó không được thực hiện
Những gì tôi có ở đây là một lớp được gọi là SomeClass
:
class SomeClass{
//As you can guess, I will use this shady property to make a strong cycle :)
var closure:(()->())?
init(){}
func method(){}
deinit {print("SomeClass deinited")}
}
Ngoài ra tôi có hai cảnh, các GameScene
:
class GameScene: SKScene {
override func didMoveToView(view: SKView) {
backgroundColor = .blackColor()
let someInstance = SomeClass()
let closure = {[unowned self] in
someInstance.method() //This causes the strong reference cycle...
self.method()
}
someInstance.closure = closure
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
if let nextScene = MenuScene(fileNamed: "MenuScene"){
nextScene.scaleMode = .AspectFill
let transition = SKTransition.fadeWithDuration(1)
view?.presentScene(nextScene, transition: transition)
}
}
deinit {print("GameScene deinited")}
func method(){}
}
Và cuối cùng, MenuScene
mà là giống hệt với GameScene
, chỉ với phương thức rỗng didMoveToView
(chỉ có phương thức touchesBegan
được triển khai).
Tái Crash
Vụ tai nạn có thể sinh sản bằng chuyển giữa các cảnh trong một vài lần. Bằng cách đó, sự rò rỉ sẽ xảy ra vì someInstance
được giữ lại bởi biến số closure
và biến số closure
được giữ lại bởi biến số someInstance
, vì vậy chúng tôi có chu kỳ. Tuy nhiên, điều này sẽ không tạo ra sự cố (nó sẽ chỉ bị rò rỉ). Khi tôi thực sự cố gắng thêm self.method()
bên trong đóng cửa, các tai nạn ứng dụng và tôi có được điều này:
và điều này:
Cùng tai nạn chính xác tôi có thể sản xuất nếu tôi cố gắng truy cập tham chiếu unowned
khi đối tượng mà nó tham chiếu được deallocated, ví dụ: khi đóng cửa outlives trường hợp bị bắt. Điều đó có ý nghĩa, nhưng đó không phải là trường hợp ở đây (đóng cửa không bao giờ được thực hiện).
The Mysterious Phần
Phần bí ẩn là vụ tai nạn này xảy ra chỉ trên iOS 9.1 và không phải trên iOS9.3. Và một điều bí ẩn khác là thực tế là ứng dụng bị treo ngẫu nhiên, nhưng chủ yếu là trong mười lần chuyển tiếp đầu tiên. Ngoài ra, phần lạ là lý do tại sao nó bị treo nếu đóng cửa không bao giờ được thực hiện, hoặc trường hợp nó chụp không được truy cập (ít nhất là không phải bởi tôi).
Giải pháp cho các vấn đề nhưng không phải là trả lời cho câu hỏi
Tất nhiên sự sụp đổ có thể được giải quyết trong một vài cách bằng cách phá vỡ chu kỳ, và tôi biết rằng tôi nên sử dụng unowned
chỉ khi tôi hoàn toàn chắc chắn rằng trường hợp đã capture sẽ không bao giờ trở thành 0 sau khi khởi tạo. Nhưng vẫn còn, vì thực tế là tôi đã không thực hiện đóng cửa này ở tất cả, sau khi nó outlived cảnh, vụ tai nạn này là khá khó xử với tôi. Ngoài ra, nó có thể là đáng nói đến là cảnh được deinited thành công sau mỗi quá trình chuyển đổi.
Thú vị
Nếu tôi sử dụng weak self
bên trong một danh sách chụp, ứng dụng sẽ không sụp đổ (rò rỉ vẫn còn tồn tại tất nhiên). Điều đó có ý nghĩa, bởi vì nếu cảnh trở thành nil
trước khi khối được deallocated, truy cập vào cảnh thông qua chuỗi tùy chọn sẽ ngăn ngừa sự cố. Nhưng phần thú vị là ngay cả khi tôi sử dụng forced unwrapping
như thế này, nó sẽ không sụp đổ:
let closure = {[weak self] in
someInstance.method()
self!.method()
}
Mà làm cho tôi suy nghĩ ... Đánh giá cao bất kỳ gợi ý về cách để gỡ lỗi này hoặc giải thích về những gì gây ra tai nạn .. .
EDIT:
đây là Github repo
Nếu nó không bị lỗi trên 9.3 thì đó có thể là lỗi. Đây có phải là báo cáo của bạn không? [SR-1006] (https://bugs.swift.org/browse/SR-1006) Có vẻ như cùng một vấn đề. – Sulthan
@Sulthan Không, đó không phải là báo cáo lỗi của tôi ... Vâng, tôi bắt đầu một tiền thưởng để xem nếu ai đó thực sự có thể chứng minh rằng đây là một lỗi hay không, và giải thích những gì nên là hành vi mong đợi trong tình huống này. Cá nhân, tôi nghĩ rằng nó nên bị rò rỉ, nhưng không nên sụp đổ, nhưng chúng ta sẽ thấy ... – Whirlwind
Tôi khá chắc chắn nó không nên sụp đổ nếu bạn không thực sự thực hiện các khối. – Sulthan