Adding a button to a UICollectionViewCell using a click handler using Xamarin.iOS

I am rewriting a screen that used a UITableView before a UICollectionView. But I'm having problems with the click handler on the button inside the cell.

collectionView.RegisterNibForCell (DocumentViewCell.Nib, docCellId); ... public override UICollectionViewCell GetCell (UICollectionView collectionView, MonoTouch.Foundation.NSIndexPath indexPath) { var docCell = (DocumentViewCell)collectionView.DequeueReusableCell (docCellId, indexPath); docCell.BtnDelete.Hidden = !EditMode; docCell.BtnDelete.TouchUpInside += delegate(object sender, EventArgs e) { Logging.Debug("Crashes before if reaches here"); }; return docCell; } 

I know that the cell is restarted, and this most likely will not work when this happens, but now it immediately crashes immediately with one item in the list when the delete button is clicked. Everything works fine until I hit a button and then I get a stack. I see no reason for this, based on my UITableView code, which is almost identical.

Has anyone done this using Nib-based CellView cells? Any help is much appreciated!

Stacktrace:

  at (wrapper managed-to-native) MonoTouch.UIKit.UIApplication.UIApplicationMain (int,string[],intptr,intptr) <IL 0x0009f, 0xffffffff> at MonoTouch.UIKit.UIApplication.Main (string[],string,string) [0x0004c] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:38 at SalesApp.Application.Main (string[]) [0x00000] in /MyApp/Main.cs:18 at (wrapper runtime-invoke) <Module>.runtime_invoke_void_object (object,intptr,intptr,intptr) <IL 0x00050, 0xffffffff> Native stacktrace: 0 SalesApp 0x0009a85c mono_handle_native_sigsegv + 284 1 SalesApp 0x0000e138 mono_sigsegv_signal_handler + 248 2 libsystem_c.dylib 0x990a78cb _sigtramp + 43 3 ??? 0xffffffff 0x0 + 4294967295 4 UIKit 0x01990258 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 61 5 UIKit 0x01a51021 -[UIControl sendAction:to:forEvent:] + 66 6 UIKit 0x01a5157f -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 578 7 UIKit 0x01a506e8 -[UIControl touchesEnded:withEvent:] + 546 8 UIKit 0x01c541d3 _UIGestureRecognizerUpdate + 7407 9 CoreFoundation 0x03ecbafe __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 30 

Update

This code works great

 public override UICollectionViewCell GetCell (UICollectionView collectionView, MonoTouch.Foundation.NSIndexPath indexPath) { var docCell = (DocumentViewCell)collectionView.DequeueReusableCell (DocumentViewCell.Key, indexPath); docCell.BtnDelete.Hidden = !EditMode; docCell.BtnDelete.TouchUpInside -= HandleTouchUpInside; docCell.BtnDelete.TouchUpInside += HandleTouchUpInside; return docCell; } void HandleTouchUpInside (object sender, EventArgs e) { Logging.Debug("No crash"); } 
+4
source share
2 answers

The problem is that there is no managed reference to the docCell instance that you are returning from the GetCell method. This means that the GC can collect it whenever it wants.

When it is needed again, it will be returned to the managed world (using the IntPtr constructor). This will be the same (reused) native instance, but a new managed instance. Your crash happens because the event points to an old, managed instance (which was assembled).

A simple solution is to keep the cache of the created cells the same as the view. This ensures that the GC will not collect (managed) cells until they are used. There several answers show this for a UITableView .

Note. I thought we fixed this in a recent version of Xamarin.iOS. Maybe it was just for a UITableView !?! need to check it out ...

+4
source

I assume that DequeueReusableCell returns null as it takes out the first cell.

Instead, your code should look like this:

 public override UICollectionViewCell GetCell (UICollectionView collectionView, MonoTouch.Foundation.NSIndexPath indexPath) { var docCell = (DocumentViewCell)collectionView.DequeueReusableCell (docCellId, indexPath); if (docCell == null) docCell = new UICollectionViewCell (...); docCell.BtnDelete.TouchUpInside += delegate(object sender, EventArgs e) { Logging.Debug("Crashes before if reaches here"); }; return docCell; } 

replace the ellipses (...) with what creates your cell.

+1
source

Source: https://habr.com/ru/post/1483779/


All Articles