UITableView上的SIGSEGV错误IOS-UIgestureRecognitor

UITableView上的SIGSEGV错误IOS-UIgestureRecognitor,ios,uitableview,xamarin.ios,xamarin,Ios,Uitableview,Xamarin.ios,Xamarin,我有一个UITableView,我正在为它将一个uigestureRecognitor附加到带有自定义单元格的ImageView。识别器在tableview的最后一行工作正常,但如果我在最后一行之前尝试任何单元格,应用程序就会崩溃,出现以下错误。我不完全确定如何调试它,或者实际上这是否是我应该直接向Xamarin提出的问题 感谢您的帮助 using System; using System.Drawing; using MonoTouch.Foundation; using MonoTouch

我有一个
UITableView
,我正在为它将一个
uigestureRecognitor
附加到带有自定义单元格的ImageView。识别器在tableview的最后一行工作正常,但如果我在最后一行之前尝试任何单元格,应用程序就会崩溃,出现以下错误。我不完全确定如何调试它,或者实际上这是否是我应该直接向Xamarin提出的问题

感谢您的帮助

using System;
using System.Drawing;

using MonoTouch.Foundation;
using MonoTouch.UIKit;
using System.Collections.Generic;

namespace gestures
{
public partial class gestureTest : UIViewController
{
    #region Private Variables
    private bool imageHighlighted = false;
    private bool touchStartedInside;
    #endregion


    public gestureTest () : base ("gestureTest", null)
    {
    }

    public override void DidReceiveMemoryWarning ()
    {
        // Releases the view if it doesn't have a superview.
        base.DidReceiveMemoryWarning ();

        // Release any cached data, images, etc that aren't in use.
    }

    public override void ViewDidLoad ()
    {
        base.ViewDidLoad ();



//          UIView viewGesture = new UIView ();
//
//          viewGesture.Add (tblGesture);

        fillTabele ();
        // Perform any additional setup after loading the view, typically from a nib.
    }



    protected void fillTabele( ) {



        List<WorkItem> list = new List<WorkItem>();
        list.Add (new WorkItem ("soemthing"));
        list.Add (new WorkItem ("soemthing else"));
        list.Add (new WorkItem ("soemthing other than else"));


        UITableView table = new UITableView(View.Bounds); // defaults to Plain style

        table.Source = new TableSource(list,"sptring",this);
        Add (table);

    }


    public class WorkItem  {

        public WorkItem() {}
        public WorkItem(string reftitle) {
            this.myTitle = reftitle;
        }

        private string myTitle;

        public string title
        {
            get 
            {
                return myTitle; 
            }
            set 
            { 
                myTitle = value; 
            }
        }
    }

    public class TableSource : UITableViewSource { 
        protected WorkItem[] 
        _tableItems; protected string _cellIdentifier = "TableCell"; 
        string vc; 
        UIImageView img; 
        UIViewController vController;
        UIAlertView alert; 
        UITapGestureRecognizer gesture = null; 
        //TaskViewController addTaskController;

        public TableSource(List<WorkItem> tblItemGroups, string sprint,UIViewController vCon)
        {
            this._tableItems = tblItemGroups.ToArray();
            this.vc = sprint;
            this.vController = vCon;
        }



        public override int RowsInSection(UITableView tableview, int section)
        {
            if (_tableItems != null)
            {
                return this._tableItems.Length;
            }
            else
            {
                return 0;
            }
        }
        public override UIView GetViewForHeader(UITableView tableView, int section)
        {

            return BuildSectionHeaderView(vc.ToString());
        }

        public static UIView BuildSectionHeaderView(string caption)
        {
            UIView view = new UIView(new System.Drawing.RectangleF(0, 0, 320, 20));
            UILabel label = new UILabel();
            label.BackgroundColor = UIColor.Clear;
            label.Opaque = false;
            label.TextColor = UIColor.Black;
            label.Font = UIFont.FromName("Helvetica-Bold", 16f);
            label.Frame = new System.Drawing.RectangleF(15, 0, 290, 20);
            label.Text = caption;
            view.AddSubview(label);
            return view;
        }
        public override float GetHeightForRow(UITableView tableView, NSIndexPath indexPath)
        {
            return 50f;
        }

        public override string TitleForHeader(UITableView tableView, int section)
        {

            return vc.ToString();
        }

        public static void ClearEmptyTableViewSpacer(UITableView oTableView)
        {
            UIView oViewSpacerClear = new UIView(new RectangleF(0, 0, oTableView.Frame.Width, 10));
            oViewSpacerClear.BackgroundColor = UIColor.Clear;
            oTableView.TableFooterView = oViewSpacerClear;

        }

        public override UITableViewCell GetCell(UITableView tableView, MonoTouch.Foundation.NSIndexPath indexPath)
        {

            if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Pad)
            {
                tableView.BackgroundView = null;
            }
            else
            {
                tableView.BackgroundColor = null;
            }
            WorkItem wrkitem = _tableItems[indexPath.Row];


            UITableViewCell cell = tableView.DequeueReusableCell(this._cellIdentifier);

            if (cell == null)
            {
                cell = new UITableViewCell(UITableViewCellStyle.Default, this._cellIdentifier);
            }


            NSAction action = () => {
                //alert=new UIAlertView("gesture recognized","tap me image tapped @" + gesture.LocationOfTouch (0, img).ToString (),null,"Ok","Cancel");
                alert=new UIAlertView("gesture recognized","tap me image tapped @",null,"Ok","Cancel");
                alert.Show();
            };

            cell.TextLabel.Text = wrkitem.title.ToString ();
            cell.ImageView.Image = UIImage.FromFile("images/splash-text.png");
            cell.ImageView.UserInteractionEnabled = true;
            gesture = new UITapGestureRecognizer();
            gesture.AddTarget(()=>action());
            cell.ImageView.AddGestureRecognizer(gesture);
            cell.ImageView.Frame = new RectangleF(10, 14, 5, 5);
            cell.TextLabel.Lines = 0;
            cell.TextLabel.LineBreakMode = UILineBreakMode.WordWrap;


            return cell;
        }


    }


    }
}
mono rt:Stacktrace:

  mono-rt: 
  Native stacktrace:


  mono-rt:  0   gestures                            0x000c4777 mono_handle_native_sigsegv + 327

  mono-rt:  1   gestures                            0x000cf5ba sigabrt_signal_handler + 122

  mono-rt:  2   libsystem_platform.dylib            0x05427deb _sigtramp + 43

  mono-rt:  3   ???                                 0xffffffff 0x0 + 4294967295

  mono-rt:  4   libsystem_sim_c.dylib               0x05144e12 abort + 127

 mono-rt:   5   gestures                            0x0024db33    monotouch_unhandled_exception_handler + 291

 mono-rt:   6   gestures                            0x000c4fbb   mono_invoke_unhandled_exception_hook + 91

mono-rt:    7   gestures                            0x000c3fcc mono_handle_exception_internal + 6620

mono-rt:    8   gestures                            0x000c25e9 mono_handle_exception + 41

mono-rt:    9   gestures                            0x0005cdd9 mono_x86_throw_exception + 137   

mono-rt:    10  ???                                 0x0ee30e57 0x0 + 249761367

mono-rt:    11  gestures                            0x0023d001 monotouch_exception_handler + 177

mono-rt:    12  CoreFoundation                      0x016aea1d __handleUncaughtException + 749

mono-rt:    13  libobjc.A.dylib                     0x04e89b5c _ZL15_objc_terminatev + 100

mono-rt:    14  libc++abi.dylib                     0x0535df60 _ZSt11__terminatePFvvE + 14

 mono-rt:   15  libc++abi.dylib                     0x0535db97 __cxa_rethrow + 103

mono-rt:    16  libobjc.A.dylib                     0x04e89a57 objc_exception_rethrow + 47

mono-rt:    17  CoreFoundation                      0x015c3b55 CFRunLoopRunSpecific + 613

mono-rt:    18  CoreFoundation                      0x015c38db CFRunLoopRunInMode + 123

mono-rt:    19  GraphicsServices                    0x060969e2 GSEventRunModal + 192

mono-rt:    20  GraphicsServices                    0x06096809 GSEventRun + 104

mono-rt:    21  UIKit                               0x02956d3b UIApplicationMain + 1225

mono-rt:    22  ???                                 0x127f82ac 0x0 + 310346412

mono-rt:    23  ???                                 0x127f713c 0x0 + 310341948

mono-rt:    24  ???                                 0x127f6ec0 0x0 + 310341312

mono-rt:    25  ???                                 0x127f6f4f 0x0 + 310341455

mono-rt:    26  gestures                            0x000f655b mono_jit_runtime_invoke + 843

mono-rt:    27  gestures                            0x00194b5f mono_runtime_invoke + 127

mono-rt:    28  gestures                            0x0019a671 mono_runtime_exec_main + 401

 mono-rt:   29  gestures                            0x0019a434 mono_runtime_run_main + 628

 mono-rt:   30  gestures                            0x00054ffd mono_jit_exec + 93

  mono-rt:  31  gestures                            0x00235a70 main + 2784

  mono-rt:  32  gestures                            0x00003a15 start + 53

    mono-rt: 
  =================================================================
  Got a SIGABRT while executing native code. This usually indicates
  a fatal error in the mono runtime or one of the native libraries 
  used by your application.
  =================================================================
更新的堆栈跟踪

mono-rt:   at <unknown> <0xffffffff>

mono-rt:   at (wrapper managed-to-native) MonoTouch.UIKit.UIApplication.UIApplicationMain   (int,string[],intptr,intptr) <IL 0x0009f, 0xffffffff>

mono-rt:   at MonoTouch.UIKit.UIApplication.Main (string[],string,string) [0x0004c] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:38

mono-rt:   at gestures.Application.Main (string[]) [0x00008] in /Users/seankerr/Projects/gestures/gestures/Main.cs:17

mono-rt:   at (wrapper runtime-invoke) <Module>.runtime_invoke_void_object (object,intptr,intptr,intptr) <IL 0x00050, 0xffffffff>

mono-rt: 
Native stacktrace:


mono-rt: 
=================================================================
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.
=================================================================
}这可能不是唯一的问题,但是您的
GetCell
方法有问题。请记住,
UITableViewCell
实例被iOS重新使用

这意味着您的
if(cell==null){…}
块可以做的远不止创建一个新的
UITableViewCell
实例。low任何恒定/静态的事情都可以(也应该)只做一次

例如

没有理由在每次重复使用单元格时创建新的
操作。事实上,表视图可能只有一个(这取决于最终代码,它可能不会显示警报)

前一行不能重复使用,即每次重复使用单元格时执行它是正确的

cell.ImageView.Image = UIImage.FromFile("images/splash-text.png");
cell.ImageView.UserInteractionEnabled = true;
gesture = new UITapGestureRecognizer();
gesture.AddTarget(()=>action());
cell.ImageView.AddGestureRecognizer(gesture);
cell.ImageView.Frame = new RectangleF(10, 14, 5, 5);
cell.TextLabel.Lines = 0;
cell.TextLabel.LineBreakMode = UILineBreakMode.WordWrap;
需要为每个重复使用的
单元格设置所有这些行。您可以在创建单元时(如果)设置所有这些

这样做不仅仅是一种优化。现在,每次重复使用单元格时,您的代码都会添加一个(另一个)新的附加的
UITapgestureRecognitor
。您可以通过重用单元来运行内存

更新

而不是:

gesture = new UITapGestureRecognizer();
gesture.AddTarget(()=>action());
做:


我将对您的代码进行以下更改:

if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Pad)
{
    tableView.BackgroundView = null;
}
else
{
    tableView.BackgroundColor = null;
}
应将其移出GetCell并放入ViewDidLoad或ViewWillDisplay。GetCell方法会被反复调用(当您滚动或重新加载数据时)和(我可能不正确),但这段代码看起来不需要多次调用。您还应该像前面提到的那样,在ViewDidLoad中初始化图像一次,否则ViewWill将显示为全局变量(例如myImage),并只分配它,而不是反复加载它

现在,不必每次在GetCell中设置手势识别器,您可以创建一个自定义UITableViewCell,并在自定义单元格的AwakeFromNib方法中的ImageView上实现手势识别器:

namespace gestures
{
    public partial class gestureTestCell : UITableViewCell
    {
        public static string _cellIdentifier = "gestureTestCell"; // whatever you name it in Interface Builder

        public gestureTestCell () : base ()
        {

        }

        public gestureTestCell (IntPtr handle) : base (handle)
        {

        }

        protected override void Dispose (bool disposing)
        {
            myImageView.RemoveGestureRecognizer(gesture)

            base.Dispose (disposing);
        }

        public override void AwakeFromNib ()
        {
            base.AwakeFromNib ();

            var gesture = new UITapGestureRecognizer (HandleTapGesture);
            myImageView.AddGestureRecognizer (gesture);
        }

        public override void LayoutSubviews ()
        {
            base.LayoutSubviews ();

            myImageView.UserInteractionEnabled = true;
            myImageView.Frame = new RectangleF(10, 14, 5, 5);
            myTextLabel.Lines = 0;
            myTextLabel.LineBreakMode = UILineBreakMode.WordWrap;
        }

       void HandleTapGesture (UITapGestureRecognizer gesture)
       {
        var alert = new UIAlertView("gesture recognized","tap me image tapped     @",null,"Ok","Cancel");
        alert.Show();
        }

        public override void PrepareForReuse ()
        {
            base.PrepareForReuse ();
        }


        public void SetupCell(string text, UIImage image)
        {
            myImageView.Image = image;
            myTextLabel.Text  = text;   
        }
    }
  }
现在,您的
GetCell
方法可以如下所示:

public override UITableViewCell GetCell(UITableView tableView, MonoTouch.Foundation.NSIndexPath indexPath)
{
    gestureTestCell cell = tableView.DequeueReusableCell(gestureTestCell._cellIdentifier) ?? new gestureTestCell();

    cell.SetupCell(_tableItems[indexPath.Row].ToString(), myImage);

    return cell;
}

嗨@poupou,谢谢你的全面回答。考虑到我犯了不少错误,我想从最高层开始。对于空检查的第一个问题,然后是创建一个新实例,如果(cell==null),您将如何编写它?当
cell==null
时,您需要实例化一个新的单元格(就像您已经做的那样),然后初始化所有内容(最后一块代码)。否则(当
cell!=null
)您已经有一个初始化的单元格(如您所需),只需设置其状态,即使用
wrkitem的行。
。嗨@poupou,我对GetCell方法进行了更改,我移动了if(cell==null){…}下的所有公共属性,除了单元格本身的实际文本和图像。行为仍然是一样的,但现在我得到了一个错误,告诉我更多。我已经发布了上面的堆栈跟踪。我更新了我的答案。请注意,
cell.ImageView.Image=UIImage.FromFile(“images/splash text.png”)仍然不需要在每次重复使用单元格时执行(除非每次在同一位置动态生成新位图)。如果您总是使用同一个图像,那么您应该只加载一次(并多次分配)。您好@poupou,我将图像移回If语句下。不过我还是有错误。我已经发布了堆栈跟踪。还有什么我可以试试的吗?嗨@pnavk,我还在处理你提供的代码,谢谢你的帮助。我很快就回来。很好,没问题。希望能有帮助。如果您遇到困难或有任何问题,请告诉我!您好@pnavk,我从gestureTestCell类中得到一些声明错误,我是否需要myImageView、myTextLabel等?您是否为gestureCell创建了单独的XIB文件?如果是这样,这些将是您在XCode中连接的插座。如果完全以编程方式进行,则需要在构造函数中适当地创建和定位它们。查看本教程:
cell.ImageView.Image = UIImage.FromFile("images/splash-text.png");
cell.ImageView.UserInteractionEnabled = true;
gesture = new UITapGestureRecognizer();
gesture.AddTarget(()=>action());
cell.ImageView.AddGestureRecognizer(gesture);
cell.ImageView.Frame = new RectangleF(10, 14, 5, 5);
cell.TextLabel.Lines = 0;
cell.TextLabel.LineBreakMode = UILineBreakMode.WordWrap;
gesture = new UITapGestureRecognizer();
gesture.AddTarget(()=>action());
gesture = new UITapGestureRecognizer (action);
if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Pad)
{
    tableView.BackgroundView = null;
}
else
{
    tableView.BackgroundColor = null;
}
namespace gestures
{
    public partial class gestureTestCell : UITableViewCell
    {
        public static string _cellIdentifier = "gestureTestCell"; // whatever you name it in Interface Builder

        public gestureTestCell () : base ()
        {

        }

        public gestureTestCell (IntPtr handle) : base (handle)
        {

        }

        protected override void Dispose (bool disposing)
        {
            myImageView.RemoveGestureRecognizer(gesture)

            base.Dispose (disposing);
        }

        public override void AwakeFromNib ()
        {
            base.AwakeFromNib ();

            var gesture = new UITapGestureRecognizer (HandleTapGesture);
            myImageView.AddGestureRecognizer (gesture);
        }

        public override void LayoutSubviews ()
        {
            base.LayoutSubviews ();

            myImageView.UserInteractionEnabled = true;
            myImageView.Frame = new RectangleF(10, 14, 5, 5);
            myTextLabel.Lines = 0;
            myTextLabel.LineBreakMode = UILineBreakMode.WordWrap;
        }

       void HandleTapGesture (UITapGestureRecognizer gesture)
       {
        var alert = new UIAlertView("gesture recognized","tap me image tapped     @",null,"Ok","Cancel");
        alert.Show();
        }

        public override void PrepareForReuse ()
        {
            base.PrepareForReuse ();
        }


        public void SetupCell(string text, UIImage image)
        {
            myImageView.Image = image;
            myTextLabel.Text  = text;   
        }
    }
  }
public override UITableViewCell GetCell(UITableView tableView, MonoTouch.Foundation.NSIndexPath indexPath)
{
    gestureTestCell cell = tableView.DequeueReusableCell(gestureTestCell._cellIdentifier) ?? new gestureTestCell();

    cell.SetupCell(_tableItems[indexPath.Row].ToString(), myImage);

    return cell;
}