2013-06-14 23 views
5

Xem Advanced Memory Management bởi Mark Probst và Rodrigo Kumpera, tôi đã học các kỹ thuật mới như lược tả Mono GC và sử dụng WeakReference.Làm cách nào để sửa chu kỳ GC do trình xử lý sự kiện lambda gây ra?

Tuy nhiên, tôi vẫn không hiểu làm thế nào để “sửa chữa” các Puzzle 2 từ phút 28:

public class CustomButton : UIButton { 
    public CustomButton() { } 
} 

public class Puzzle2Controller : UIViewController 
{ 
    public override void ViewDidLoad() 
    { 
     var button = new CustomButton(); 
     View.Add (button); 
     button.TouchUpInside += (sender, e) => 
      this.RemoveFromParentViewController(); 
    } 
} 

Bộ điều khiển giữ một ref để nút chứa một ref để xử lý sự kiện chứa một ref đến điều khiển.

Một cách để phá vỡ chu trình sẽ là vô hiệu hóa nút. Một cách khác là tách trình xử lý (nhưng chúng ta phải từ bỏ việc sử dụng lamdas).

Có cách nào khác/thanh lịch hơn/cách phá vỡ chu trình không? Chúng tôi có thể bằng cách nào đó dính WeakReference vào đây không?

Cảm ơn.

Chỉnh sửa: Trong trường hợp này, nút này thậm chí không phải là trường. Nhưng vẫn còn một chu kỳ, phải không? Nó nằm trong phần xem của View's Controller. Chúng ta có phải xóa chúng không? Tôi bối rối.

Trả lời

6

Chu kỳ thường không phải là vấn đề trong môi trường được thu gom rác - Tôi phải giả định từ câu hỏi rằng điều này bằng cách nào đó khác biệt trong monotouch? Chỉnh sửa: không, giả định của tôi ở đây vẫn hợp lệ - lúc 7:50 trong video bạn liên kết với nó chứng minh một chu kỳ bị loại bỏ bởi "quét".

Chu kỳ có thể thường là bị bỏ toàn bộ bán hàng, ngay khi toàn bộ chu kỳ trở nên không thể truy cập được. Đây có thể là sự cố trong hệ thống được tính tham chiếu.

Tuy nhiên! Liên quan đến câu hỏi của bạn - nút (khi đã thêm) có biết về bộ điều khiển không? nếu có, bạn có thể đến đó từ sender:

button.TouchUpInside += (sender, e) => 
      ((UIButton)sender).Parent.RemoveFromParentViewController(); 

Lambda này hiện không liên quan đến biến bị bắt và không liên quan đến bối cảnh chụp; nó không giữ bất kỳ tham chiếu đến bộ điều khiển - và thực sự hầu hết các trình biên dịch sẽ làm cho một trình xử lý tĩnh đơn hơn là một trình xử lý cho mỗi lần sử dụng, vì vậy nó hiệu quả hơn cả về các sáng tạo đại biểu.


Re bối cảnh MonoTouch cụ thể, sau đó có, bạn sẽ cần phải sử dụng WeakReference<T>:

var controller = new WeakReference<Puzzle2Controller>(this); 
button.TouchUpInside += (sender, e) => { 
    var parent = controller.Object; 
    if(parent != null) parent.RemoveFromParentViewController(); 
}; 
+0

Hi, nhờ trả lời. Điều này chắc chắn sẽ là một lựa chọn, nhưng tiếc là 'UIView' s không giữ tham chiếu đến bộ điều khiển của họ. Nếu sự hiểu biết của tôi là chính xác, các chu kỳ trong MonoTouch * là * một vấn đề bởi vì các đối tượng ObjC gốc dưới mui xe sử dụng tính tham chiếu. (Xem 21:30) –

+0

@DanAbramov trong trường hợp đó, xem chỉnh sửa –

+0

Cảm ơn bạn! Điều này hoàn toàn có ý nghĩa. –