11using CoreGraphics ;
22using Foundation ;
33using Microsoft . Maui . Platform ;
4+ using System . Diagnostics . CodeAnalysis ;
45using UIKit ;
56
67namespace Microsoft . Maui ;
@@ -9,27 +10,41 @@ internal class CvCell : UICollectionViewCell
910{
1011 public VirtualListViewHandler Handler { get ; set ; }
1112
12- public NSIndexPath IndexPath { get ; set ; }
13+ public WeakReference < NSIndexPath > IndexPath { get ; set ; }
1314
1415 public PositionInfo PositionInfo { get ; set ; }
1516
16- public Action < IView > ReuseCallback { get ; set ; }
17+ public WeakReference < Action < IView > > ReuseCallback { get ; set ; }
1718
1819 [ Export ( "initWithFrame:" ) ]
1920 public CvCell ( CGRect frame ) : base ( frame )
2021 {
2122 this . ContentView . AddGestureRecognizer ( new UITapGestureRecognizer ( ( ) => InvokeTap ( ) ) ) ;
2223 }
2324
24- public Action < CvCell > TapHandler { get ; set ; }
25+ public WeakReference < Action < CvCell > > TapHandler { get ; set ; }
2526
26- UIKeyCommand [ ] keyCommands ;
27+ WeakReference < UIKeyCommand [ ] > keyCommands ;
2728
28- public override UIKeyCommand [ ] KeyCommands => keyCommands ??= new [ ]
29+ public override UIKeyCommand [ ] KeyCommands
2930 {
30- UIKeyCommand . Create ( new NSString ( "\r " ) , 0 , new ObjCRuntime . Selector ( "keyCommandSelect" ) ) ,
31- UIKeyCommand . Create ( new NSString ( " " ) , 0 , new ObjCRuntime . Selector ( "keyCommandSelect" ) ) ,
32- } ;
31+ get
32+ {
33+ if ( keyCommands ? . TryGetTarget ( out var commands ) ?? false )
34+ return commands ;
35+
36+ var v = new [ ]
37+ {
38+ UIKeyCommand . Create ( new NSString ( "\r " ) , 0 , new ObjCRuntime . Selector ( "keyCommandSelect" ) ) ,
39+ UIKeyCommand . Create ( new NSString ( " " ) , 0 , new ObjCRuntime . Selector ( "keyCommandSelect" ) ) ,
40+ } ;
41+
42+ keyCommands = new WeakReference < UIKeyCommand [ ] > ( v ) ;
43+
44+ return v ;
45+ }
46+
47+ }
3348
3449 [ Export ( "keyCommandSelect" ) ]
3550 public void KeyCommandSelect ( )
@@ -40,54 +55,85 @@ public void KeyCommandSelect()
4055 void InvokeTap ( )
4156 {
4257 if ( PositionInfo . Kind == PositionKind . Item )
43- TapHandler ? . Invoke ( this ) ;
58+ {
59+ if ( TapHandler ? . TryGetTarget ( out var handler ) ?? false )
60+ handler ? . Invoke ( this ) ;
61+ }
62+ }
63+
64+ public void UpdateSelected ( bool selected )
65+ {
66+ PositionInfo . IsSelected = selected ;
67+
68+ if ( VirtualView ? . TryGetTarget ( out var virtualView ) ?? false )
69+ {
70+ if ( virtualView is IPositionInfo positionInfo )
71+ {
72+ positionInfo . IsSelected = selected ;
73+ virtualView . Handler ? . UpdateValue ( nameof ( PositionInfo . IsSelected ) ) ;
74+ }
75+ }
4476 }
4577
4678 public override UICollectionViewLayoutAttributes PreferredLayoutAttributesFittingAttributes ( UICollectionViewLayoutAttributes layoutAttributes )
4779 {
48- if ( NativeView == null || VirtualView == null )
49- return layoutAttributes ;
80+ if ( ( NativeView is not null && NativeView . TryGetTarget ( out var _ ) )
81+ && ( VirtualView is not null && VirtualView . TryGetTarget ( out var virtualView ) ) )
82+ {
83+ var measure = virtualView . Measure ( layoutAttributes . Size . Width , double . PositiveInfinity ) ;
5084
51- var measure = VirtualView . Measure ( layoutAttributes . Size . Width , double . PositiveInfinity ) ;
85+ layoutAttributes . Frame = new CGRect ( 0 , layoutAttributes . Frame . Y , layoutAttributes . Frame . Width , measure . Height ) ;
5286
53- layoutAttributes . Frame = new CGRect ( 0 , layoutAttributes . Frame . Y , layoutAttributes . Frame . Width , measure . Height ) ;
87+ return layoutAttributes ;
88+ }
5489
5590 return layoutAttributes ;
5691 }
5792
5893 public bool NeedsView
59- => NativeView == null ;
94+ => NativeView == null || ! NativeView . TryGetTarget ( out var _ ) ;
6095
61- public IView VirtualView { get ; private set ; }
96+ public WeakReference < IView > VirtualView { get ; set ; }
6297
63- public UIView NativeView { get ; private set ; }
98+ public WeakReference < UIView > NativeView { get ; set ; }
6499
65100 public override void PrepareForReuse ( )
66101 {
67102 base . PrepareForReuse ( ) ;
68103
69104 // TODO: Recycle
70- if ( VirtualView != null )
71- ReuseCallback ? . Invoke ( VirtualView ) ;
105+ if ( ( VirtualView ? . TryGetTarget ( out var virtualView ) ?? false )
106+ && ( ReuseCallback ? . TryGetTarget ( out var reuseCallback ) ?? false ) )
107+ {
108+ reuseCallback ? . Invoke ( virtualView ) ;
109+ }
72110 }
73111
74112 public void SwapView ( IView newView )
75113 {
76- if ( VirtualView == null || VirtualView . Handler == null || NativeView == null )
114+ // Create a new platform native view if we don't have one yet
115+ if ( ! ( NativeView ? . TryGetTarget ( out var nativeView ) ?? false ) )
116+ {
117+ nativeView = newView . ToPlatform ( this . Handler . MauiContext ) ;
118+ nativeView . Frame = this . ContentView . Frame ;
119+ nativeView . AutoresizingMask = UIViewAutoresizing . FlexibleHeight | UIViewAutoresizing . FlexibleWidth ;
120+ this . ContentView . AddSubview ( nativeView ) ;
121+ NativeView = new WeakReference < UIView > ( nativeView ) ;
122+ }
123+
124+ // Create a new virtual view if we don't have one yet
125+ if ( ! ( VirtualView ? . TryGetTarget ( out var virtualView ) ?? false ) || ( virtualView ? . Handler is null ) )
77126 {
78- NativeView = newView . ToPlatform ( this . Handler . MauiContext ) ;
79- VirtualView = newView ;
80- NativeView . Frame = this . ContentView . Frame ;
81- NativeView . AutoresizingMask = UIViewAutoresizing . FlexibleHeight | UIViewAutoresizing . FlexibleWidth ;
82- this . ContentView . AddSubview ( NativeView ) ;
127+ virtualView = newView ;
128+ VirtualView = new WeakReference < IView > ( virtualView ) ;
83129 }
84130 else
85131 {
86- var handler = VirtualView . Handler ;
87- VirtualView . Handler = null ;
132+ var handler = virtualView . Handler ;
133+ virtualView . Handler = null ;
88134 newView . Handler = handler ;
89135 handler . SetVirtualView ( newView ) ;
90- VirtualView = newView ;
136+ VirtualView . SetTarget ( newView ) ;
91137 }
92- }
138+ }
93139}
0 commit comments