monotouch按钮中的事件处理程序问题

时间:2012-09-10 04:36:27

标签: ios uitableview xamarin.ios uibutton

我已经使用按钮自定义了我的表视图单元附件。一切都很好,直到事件处理程序。

这是我的代码。 的 [编辑]

 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.
=================================================================**

2 个答案:

答案 0 :(得分:4)

当您的GetCell方法返回cell实例时,不再有托管引用。此时GC可以收集它。

然而,UITableViewCell原生部分仍然存在(它们是原生引用的),因此看起来很好 - 但是当您使用事件处理程序时试图回到托管的代码......而且这种代码不再存在(它会崩溃)。

有几种方法可以解决这个问题。一个简单的方法是保留对您创建的每个cell的引用,例如将它们添加到静态List<UITableViewCell>。 GC将无法收集它们,因此事件处理程序将在以后工作。

但是,重新使用单元格可能会更好。现在你重新使用UITableViewCell但不是它的内容,即你总是创建UIImageUIButton。您可以轻松地共享它们(至少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事件。

相关问题