Migrating to Unified API and new reference countin

2019-04-15 06:31发布

问题:

I had a Xamarin.iOS Classic project and migrated it to Unified API.

I have a view controller in my code (simplified version):

public class TestViewController : UIViewController
{
    private WeakReference<UIView> _viewRef;

    public override void ViewDidLoad()
    {
        base.ViewDidLoad();

        _viewRef = new WeakReference<UIView>(View);
        StartTimer();
    }

    private async void StartTimer()
    {
        await Task.Delay(1000);
        // _viewRef is not alive here
    }
}

[Register("AppDelegate")]
public class AppDelegate : UIApplicationDelegate
{
    UIWindow _window;

    public override bool FinishedLaunching(UIApplication app, NSDictionary options)
    {
        _window = new UIWindow(UIScreen.MainScreen.Bounds);

        var testController = new TestViewController();
        _window.RootViewController = testController;

        _window.MakeKeyAndVisible();

        return true;
    }
}

The strange behaviour here is that _viewRef weak reference becomes not alive. So it seems like view controller's managed view instance is garbage collected. Nonetheless I can access UIView using UIViewController.View property without any problems.

Classic API project didn't have this problem. I suppose the difference here is caused by using Xamarin's new Refcount by Unified API.

What is really strange is that then I start a Unified API project from blank the problem also cannot be reproduced.

What can cause such a behaviour?

回答1:

This is by design, there is no reason to keep the managed peer for the native UIView instance alive (in your particular test case), so it's garbage collected.

If we find that we need a managed peer at a later point, a new instance is created.

This answer provides a more in-depth explanation of what's happening: Is this a bug in MonoTouch GC? (however you need to read a bit between the lines, because this answers the reverse question).