xamarin.ios – 为什么MonoTouch GC无法使用refcount> 1来杀死托管对象?

我想我已经接近理解 how Mono GC and ObjC ref counting live together了.

The way it works is that when a native object has a reference count of 1,we do not prevent the managed instance from getting garbage collected. As soon as the reference count increases above 1,we prevent the managed instance from getting garbage collected.

This is because a managed object may contain user state. For managed objects which are mirroring a corresponding native object (such as the managed UIView instance) MonoTouch kNows that the instance can not contain any state,so as soon as no managed code has a reference to the managed instance,the GC can collect it. If a managed instance is required at a later stage,we just create a new one.

因此,如果我创建一个继承UIButton的CustomButton,将其作为子视图添加到我的View中,让托管参考滑出范围然后运行GC,这个托管的CustomButton仍然不符合收集条件.

为什么不能收集它?当然它可能具有类似属性的托管状态,但是如果没有来自托管对象的链接,谁关心这个状态?它也可能只是消失,为什么不能呢?

我正在考虑一个可能的原因:订阅CustomButton事件不会使GC保持活动状态,因此当收集对象时,事件会停止触发.这可能会导致意外行为.

它是否正确?即使没有人链接,是否有其他原因可以保持托管对象的存活?

解决方法

Why can’t it be collected? Of course it may have managed state like properties,but if there is no link to it from managed objects,who cares about this state? It may as well just disappear,why can’t it?

本机代码可能具有对该对象的引用,这可能导致该对象稍后再次重新出现到托管代码.

我相信代码示例会说明会发生什么:

class MyView : UIView {
    public string ImportantSecret;
}

class AppDelegate : UIApplicationDelegate {
    UIViewController vc;
    public override bool FinishedLaunching (UIApplication app,NSDictionary options)
    {
        var myView = new MyView ();
        myView.ImportantSecret = "MonoTouchRocks";

        vc = new UIViewController ();
        vc.View = new UIView ();
        vc.View.AddSubView (myView);

        // When this method returns the only place where myView is referenced
        // is from inside the *native* Subviews collection.

        BeginInvokeOnMainThread (() =>
        {
            Console.WriteLine (((MyView) vc.Subviews [0]).ImportantSecret);
            // If the MyView instance was garbage collected and recreated
            // automatically at this point,ImportantSecret would be null.
        });
    }
}

重要提示:此代码仅用于说明GC无法收集可能具有状态的托管对象的原因.这个特定的示例实际上不会忘记重要的秘密,因为Subviews数组会自动缓存在托管代码中 – 但这通常不正确.

相关文章

UITabBarController 是 iOS 中用于管理和显示选项卡界面的一...
UITableView的重用机制避免了频繁创建和销毁单元格的开销,使...
Objective-C中,类的实例变量(instance variables)和属性(...
从内存管理的角度来看,block可以作为方法的传入参数是因为b...
WKWebView 是 iOS 开发中用于显示网页内容的组件,它是在 iO...
OC中常用的多线程编程技术: 1. NSThread NSThread是Objecti...