-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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 leaks in ContentView #15193
Conversation
View = scrollView.PresentedContent, | ||
#pragma warning disable CS0618 // Type or member is obsolete | ||
CrossPlatformMeasure = ConstrainToScrollView(scrollView.CrossPlatformMeasure, platformScrollView, scrollView), | ||
#pragma warning restore CS0618 | ||
Tag = ContentPanelTag | ||
}; | ||
|
||
#pragma warning disable CS0618 // Type or member is obsolete | ||
contentContainer.CrossPlatformArrange = ArrangeScrollViewContent(scrollView.CrossPlatformArrange, contentContainer, platformScrollView, scrollView); | ||
#pragma warning restore CS0618 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hartez Is this something we need to consider for this PR? @jonathanpeppers will this still cause scroll views to live forever?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we need a new way that allows for also attaching static methods? This way we can still use the delegates, but be static so they don't capture anything?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@PureWeen what were your findings for using static methods? Did that help?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea, if I was able to make a delegate static that would always fix the issue. I think this came down to how much we want to try and protect someone (us?) that's using these APIs. Instead of using a delegate, if you just have to set the View
that's a path that's easy for us to make safe. That being said, it is possible to just use statics and make these not leak. Closures being very leaky on iOS isn't anything that's going away, so if you're writing iOS code and you don't have proper tests, or know how to make code not leak it's probably going to leak.
From a design perspective, if we favor the delegates I would be in favor of keeping them and relying on testing and possibly future tooling to keep us safe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But you can still create leaks with static methods, see the closures here:
return (rect) => |
return (widthConstraint, heightConstraint) => |
Should we just avoid using all delegates? Otherwise we need to make it a build error if you use non-static ones -- or closures.
[Obsolete("Use View instead. This member causes memory leaks.")] | ||
internal Func<double, double, Size>? CrossPlatformMeasure { get; set; } | ||
[Obsolete("Use View instead. This member causes memory leaks.")] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jonathanpeppers @hartez since this is internal, should we maybe change the API so we can use a static delegate and rather pass around some sort of state - I am looking at the code for scroll view and the fact that it seems to sort of make some decisions with these 2 delegates.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left these here for ScrollView
to be fixed later.
How do we enforce the delegate will always be static?
I've got an alternative version of this in the works that I think fixes the problem and preserves the original design intent. Hopefully I can get a PR in soon, I've just got to put out some other fires first. Then we can compare and see how we feel about each option. |
@hartez do you have any qualms about merging this, and add your changes later? We have an email thread that says "CUSTOMER URGENT DTS" in all caps. |
/rebase |
1d23135
to
030cc1c
Compare
030cc1c
to
99c8590
Compare
/rebase |
Context: https://github.com/jonathanpeppers/MemoryLeaksOniOS Related to: dotnet#14664 There are a couple cycles on iOS that causes memory leaks in all controls based on `ContentView`: * `Microsoft.Maui.Controls.ContentView` -> * `ContentViewHandler` -> * `Microsoft.Maui.Platform` -> * `CrossPlatformArrange/Measure` property -> * `Microsoft.Maui.Controls.ContentView` cycle To fix this, I made `CrossPlatformArrange/Measure` properties obsolete, using the weak `View` property directly instead. This applies to various other controls like `Border`, `RadioButton`, `SwipeItemView`, `SwipeView`. I did not yet fix `ScrollView` that appears to be more complicated to solve. For now, it supports both code paths. `ScrollView` will continue to have leaks in: * Closures with captured variables * https://github.com/dotnet/maui/blob/3b620952425ca3c4542c4632e05d09eb4f583e22/src/Core/src/Handlers/ScrollView/ScrollViewHandler.iOS.cs#L195 * https://github.com/dotnet/maui/blob/3b620952425ca3c4542c4632e05d09eb4f583e22/src/Core/src/Handlers/ScrollView/ScrollViewHandler.iOS.cs#L227 * `CrossPlatformArrange/Measure` * https://github.com/dotnet/maui/blob/3b620952425ca3c4542c4632e05d09eb4f583e22/src/Core/src/Handlers/ScrollView/ScrollViewHandler.iOS.cs#L182-L186
99c8590
to
7091309
Compare
Closing this one in favor of: #15303 As the other one also resolves issues around |
Context: https://github.com/jonathanpeppers/MemoryLeaksOniOS
Related to: #14664
There are a couple cycles on iOS that causes memory leaks in all controls based on
ContentView
:Microsoft.Maui.Controls.ContentView
->ContentViewHandler
->Microsoft.Maui.Platform.ContentView
->CrossPlatformArrange/Measure
property ->Microsoft.Maui.Controls.ContentView
cycleTo fix this, I made
CrossPlatformArrange/Measure
properties obsolete, using the weakView
property directly instead. This applies to various other controls likeBorder
,RadioButton
,SwipeItemView
,SwipeView
.I did not yet fix
ScrollView
that appears to be more complicated to solve. For now, it supports both code paths.ScrollView
will continue to have leaks in:Closures with captured variables
maui/src/Core/src/Handlers/ScrollView/ScrollViewHandler.iOS.cs
Line 195 in 3b62095
maui/src/Core/src/Handlers/ScrollView/ScrollViewHandler.iOS.cs
Line 227 in 3b62095
CrossPlatformArrange/Measure
maui/src/Core/src/Handlers/ScrollView/ScrollViewHandler.iOS.cs
Lines 182 to 186 in 3b62095