Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ios] fix memory leak in TimePicker #16265

Merged
merged 3 commits into from
Aug 7, 2023

Commits on Aug 3, 2023

  1. [ios] fix memory leak in TimePicker

    After working on some tooling to proactively find memory leaks, I found
    a few in the `TimePicker`. This kind of highlights the pattern:
    
    * `MauiTimePicker` is a subclass of `UIDatePicker`
    
    * `TimePickerHandler` has a strong reference to `MauiTimePicker`
      as the `PlatformView`.
    
    * `TimePickerHandler` subscribes to various events and has a strong
      reference to `MauiTimePicker`: creating a cycle.
    
    This effectively causes entire pages to leak, because
    `TimePicker.Parent.Parent`, etc. will hold a strong reference up to the
    entire `Page`.
    
    It is not enough to unsubscribe from these events in `DisconnectHandler`,
    because it is not called in many cases.
    
    For example, take the test:
    
        await InvokeOnMainThreadAsync(() =>
        {
            var layout = new Grid();
            var picker = new TimePicker();
            layout.Add(picker);
            var handler = CreateHandler<LayoutHandler>(layout);
            viewReference = new WeakReference(handler);
            handlerReference = new WeakReference(picker.Handler);
            platformViewReference = new WeakReference(picker.Handler.PlatformView);
        });
    
        await AssertionExtensions.WaitForGC(viewReference, handlerReference, platformViewReference);
        Assert.False(viewReference.IsAlive, "TimePicker should not be alive!");
        Assert.False(handlerReference.IsAlive, "Handler should not be alive!");
        Assert.False(platformViewReference.IsAlive, "PlatformView should not be alive!");
    
    In this case, `Grid`'s `LayoutHandler.DisconnectHandler` is called, but
    not the `TimePickerHandler`.
    
    To solve this problem, I moved 5 events to the `MauiTimePicker` class
    and was able to remove one.
    
    I also found a similar problem with `MauiDoneAccessoryView` and converted
    various `Action` callbacks to use `WeakReference` instead.
    
    The test did not pass until solving all of the above.
    jonathanpeppers committed Aug 3, 2023
    Configuration menu
    Copy the full SHA
    9079f91 View commit details
    Browse the repository at this point in the history

Commits on Aug 4, 2023

  1. Configuration menu
    Copy the full SHA
    2f4a48c View commit details
    Browse the repository at this point in the history
  2. Configuration menu
    Copy the full SHA
    081964a View commit details
    Browse the repository at this point in the history