2

テーブルビューのセルアクセサリをボタンでカスタマイズしました。イベントハンドラーまではすべてうまくいきました。

これが私のコードです。 [編集]

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

2 に答える 2

4

GetCellメソッドが返されると、インスタンスにはマネージド参照cellがなくなります。この時点で、GC はそれを収集できます。

ただし、ネイティブ部分はUITableViewCellまだ存在する (ネイティブに参照される) ため、見た目は問題ありませんが、イベント ハンドラーを使用すると、マネージコードに戻ろうとします...そしてそれはもう存在しません (クラッシュします)。 .

これに対処するにはいくつかの方法があります。簡単な方法は、cell作成したそれぞれへの参照を保持することです。たとえば、それらを static に追加します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;
    }
于 2012-09-10T13:44:56.643 に答える
2

UIButton はローカル変数として宣言されているため、Mono の GC が UIButton を収集して破棄する可能性があります。UITableViewCell をサブクラス化し、それに UIButton を含めてから、そのクラスを GetCell で使用することをお勧めします。

ところで、TouchDown イベントの代わりに TouchUpInside を使用することをお勧めします。

于 2012-09-10T08:10:41.263 に答える