我已经使用按钮自定义了我的表视图单元附件。一切都很好,直到事件处理程序。
这是我的代码。 的 [编辑]
public class ProductTableSource: UITableViewSource
{
protected List<Product> tableItems = new List<Product> ();
protected string cellIdentifier = "producdetailscell";
private RootViewController controller;
protected Transaction transaction;
public UIButton addItemButton;
public UIImage Image;
public ProductTableSource (List<Product> items, RootViewController controller)
{
this.tableItems = items;
this.controller = controller;
Image = UIImage.FromFile ("Images/plus.png");
addItemButton = UIButton.FromType(UIButtonType.Custom);
var buttonFrame = new RectangleF (0f, 0f, Image.Size.Width, Image.Size.Height);
addItemButton.Frame = buttonFrame;
addItemButton.SetImage(Image, UIControlState.Normal);
addItemButton.TouchUpInside += delegate {
Console.WriteLine ("Touched");
};
}
public void setTableItem (List<Product> tableItems)
{
this.tableItems = tableItems;
}
/// <summary>
/// Called by the TableView to determine how many cells to create for that particular section.
/// </summary>
public override int RowsInSection (UITableView tableview, int section)
{
return tableItems.Count;
}
/// <summary>
/// Called when a row is touched
/// </summary>
public override void AccessoryButtonTapped (UITableView tableView, NSIndexPath indexPath)
{
var prod = controller.Productdetails[indexPath.Row];
Double amount = 1*prod.SellingPriceA;
transaction = new Transaction();
transaction.SetTransaction(controller.CustomerID, prod.ID, prod.Description1,1, prod.SellingPriceA,0.0,amount);
controller.UpdateOrderedItemsTableView();
}
/// <summary>
/// Called by the TableView to get the actual UITableViewCell to render for the particular row
/// </summary>
public override UITableViewCell GetCell (UITableView tableView, MonoTouch.Foundation.NSIndexPath indexPath)
{
// request a recycled cell to save memory
UITableViewCell cell = tableView.DequeueReusableCell (cellIdentifier);
// if there are no cells to reuse, crate a new one
if (cell == null) {
cell = new UITableViewCell (UITableViewCellStyle.Default, cellIdentifier);
}
var cust = controller.Productdetails [indexPath.Row];
cell.TextLabel.Text = cust.Description1;
cell.AccessoryView = this.controller.addItemButton;
return cell;
}
}
这是我得到的错误。不确定发生了什么。也许我使用了不适当的功能请建议我!!!
**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 SalesOrder.Application.Main (string[]) [0x00000] in /Users/Mac/Projects/SalesOrderPolarisnet/SalesOrder/Main.cs:17
at (wrapper runtime-invoke) <Module>.runtime_invoke_void_object (object,intptr,intptr,intptr) <IL 0x00050, 0xffffffff>
Native stacktrace:
0 SalesOrder 0x000908cc mono_handle_native_sigsegv + 284
1 SalesOrder 0x000056f8 mono_sigsegv_signal_handler + 248
2 libsystem_c.dylib 0x9613559b _sigtramp + 43
3 ??? 0xffffffff 0x0 + 4294967295
4 UIKit 0x022620e6 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 61
5 UIKit 0x02308ade -[UIControl sendAction:to:forEvent:] + 66
6 UIKit 0x02308fa7 -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 503
7 UIKit 0x02307d8a -[UIControl touchesBegan:withEvent:] + 264
8 UIKit 0x02523a1a _UIGestureRecognizerUpdate + 6725
9 CoreFoundation 0x011b099e __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 30
10 CoreFoundation 0x01147640 __CFRunLoopDoObservers + 384
11 CoreFoundation 0x011134c6 __CFRunLoopRun + 1174
12 CoreFoundation 0x01112d84 CFRunLoopRunSpecific + 212
13 CoreFoundation 0x01112c9b CFRunLoopRunInMode + 123
14 GraphicsServices 0x048307d8 GSEventRunModal + 190
15 GraphicsServices 0x0483088a GSEventRun + 103
16 UIKit 0x0225f626 UIApplicationMain + 1163
17 ??? 0x0d4d41f4 0x0 + 223166964
18 ??? 0x0d4d2f50 0x0 + 223162192
19 ??? 0x0d4d27c0 0x0 + 223160256
20 ??? 0x0d4d284f 0x0 + 223160399
21 SalesOrder 0x00009ab2 mono_jit_runtime_invoke + 722
22 SalesOrder 0x0016b34e mono_runtime_invoke + 126
23 SalesOrder 0x0016f4d4 mono_runtime_exec_main + 420
24 SalesOrder 0x001748c5 mono_runtime_run_main + 725
25 SalesOrder 0x00066cb5 mono_jit_exec + 149
26 SalesOrder 0x00203911 main + 2209
27 SalesOrder 0x00002ab5 start + 53
=================================================================
Got a SIGSEGV while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries
used by your application.
=================================================================**
答案 0 :(得分:4)
当您的GetCell
方法返回cell
实例时,不再有托管引用。此时GC可以收集它。
然而,UITableViewCell
的原生部分仍然存在(它们是原生引用的),因此看起来很好 - 但是当您使用事件处理程序时试图回到托管的代码......而且这种代码不再存在(它会崩溃)。
有几种方法可以解决这个问题。一个简单的方法是保留对您创建的每个cell
的引用,例如将它们添加到静态List<UITableViewCell>
。 GC将无法收集它们,因此事件处理程序将在以后工作。
但是,重新使用单元格可能会更好。现在你重新使用UITableViewCell
但不是它的内容,即你总是创建UIImage
和UIButton
。您可以轻松地共享它们(至少UIImage
)并节省内存。您也可以只保留对按钮(不是整个单元格)的引用,并在修复问题时节省内存。
编辑:这应该是这样的:
static UIImage shared_image = UIImage.FromFile ("Images/plus.png");
static List<UITableViewCell> cells = new List<UITableViewCell> ();
public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
{
UITableViewCell cell = tableView.DequeueReusableCell (cellIdentifier);
if (cell == null) {
// create a cell that will be reused (some initialization steps skipped)
cell = new UITableViewCell (UITableViewCellStyle.Default, cellIdentifier);
var addItemButton = UIButton.FromType (UIButtonType.Custom);
// the same image can be shared in all cells to save memory
addItemButton.SetImage (shared_image, UIControlState.Normal);
addItemButton.TouchUpInside += delegate {
Console.WriteLine ("Touched");
};
cell.AccessoryView = addItemButton;
// keep a reference to the cells so they won't be GC'ed
/// that will ensure you can call back (event handler) into the managed instance
cells.Add (cell);
}
// customize the cell - you should not be adding elements here
// otherwise they will be added each time the cell is shown (not created)
cell.TextLabel.Text = indexPath.Row.ToString ();
return cell;
}
答案 1 :(得分:2)
Mono的GC可能会收集并处理您的UIButton,因为它们被声明为局部变量。我建议您继承UITableViewCell,包含UIButton,然后在GetCell中使用该类。
顺便说一下,最好使用TouchUpInside而不是TouchDown事件。