在UITableView上的SIGSEGV错误IOS – UiGestureRecognizer

我有一个UITableView我附加一个UIGestureRecognizer ,与ImageView与自定义单元格。 识别器在tableview的最后一行工作正常,但如果我在最后一次尝试任何单元格,应用程序崩溃与下面的错误。 我不完全确定如何debugging,或者实际上这是我应该直接向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: 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/xxxxxx/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. ================================================================= 

! – 单元格调整

  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) { 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 = new UITableViewCell(UITableViewCellStyle.Default, this._cellIdentifier); 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; } cell.TextLabel.Text = wrkitem.title.ToString (); cell.ImageView.Image = UIImage.FromFile("images/splash-text.png"); return cell; }// *new error* 2014-07-04 07:28:57.263 gestures[22619:1303] MonoTouch: Socket error while connecting to MonoDevelop on 127.0.0.1:10000: Connection refused 2014-07-04 07:29:16.139 gestures[22619:80b] -[__NSSetM target]: unrecognized selector sent to instance 0xe6ce030 Unhandled Exception: MonoTouch.Foundation.MonoTouchException: Objective-C exception thrown. Name: NSInvalidArgumentException Reason: -[__NSSetM target]: unrecognized selector sent to instance 0xe6ce030 at (wrapper managed-to-native) MonoTouch.UIKit.UIApplication:UIApplicationMain (int,string[],intptr,intptr) at MonoTouch.UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x0004c] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:38 at gestures.Application.Main (System.String[] args) [0x00008] in /Users/xxxxxx/Projects/gestures/gestures/Main.cs:17 NSInvalidArgumentException: -[__NSSetM target]: unrecognized selector sent to instance 0xe6ce030 0 CoreFoundation 0x0161e5e4 __exceptionPreprocess + 180 1 libobjc.A.dylib 0x04e898b6 objc_exception_throw + 44 2 CoreFoundation 0x016bb903 -[NSObject(NSObject) doesNotRecognizeSelector:] + 275 3 CoreFoundation 0x0160e90b ___forwarding___ + 1019 4 CoreFoundation 0x0160e4ee _CF_forwarding_prep_0 + 14 5 UIKit 0x02ccee8c _UIGestureRecognizerSendActions + 230 6 UIKit 0x02ccdb00 -[UIGestureRecognizer _updateGestureWithEvent:buttonEvent:] + 383 7 UIKit 0x02ccf56d -[UIGestureRecognizer _delayedUpdateGesture] + 60 8 UIKit 0x02cd2acd ___UIGestureRecognizerUpdate_block_invoke + 57 9 UIKit 0x02cd2a4e _UIGestureRecognizerRemoveObjectsFromArrayAndApplyBlocks + 317 10 UIKit 0x02cc9148 _UIGestureRecognizerUpdate + 199 11 UIKit 0x0299519a -[UIWindow _sendGesturesForEvent:] + 1291 12 UIKit 0x029960ba -[UIWindow sendEvent:] + 1030 13 UIKit 0x02969e86 -[UIApplication sendEvent:] + 242 14 UIKit 0x0295418f _UIApplicationHandleEventQueue + 11421 15 CoreFoundation 0x015a783f __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15 16 CoreFoundation 0x015a71cb __CFRunLoopDoSources0 + 235 17 CoreFoundation 0x015c429e __CFRunLoopRun + 910 18 CoreFoundation 0x015c3ac3 CFRunLoopRunSpecific + 467 19 CoreFoundation 0x015c38db CFRunLoopRunInMode + 123 20 GraphicsServices 0x060969e2 GSEventRunModal + 192 21 GraphicsServices 0x06096809 GSEventRun + 104 22 UIKit 0x02956d3b UIApplicationMain + 1225 23 ??? 0x127f82ac 0x0 + 310346412 24 ??? 0x127f713c 0x0 + 310341948 25 ??? 0x127f6ec0 0x0 + 310341312 26 ??? 0x127f6f4f 0x0 + 310341455 27 gestures 0x000f655b mono_jit_runtime_invoke + 843 28 gestures 0x00194b5f mono_runtime_invoke + 127 29 gestures 0x0019a671 mono_runtime_exec_main + 401 30 gestures 0x0019a434 mono_runtime_run_main + 628 31 gestures 0x00054ffd mono_jit_exec + 93 32 gestures 0x00235a70 main + 2784 33 gestures 0x00003a15 start + 53 2014-07-04 07:29:16.150 gestures[22619:80b] Unhandled managed exception: Objective-C exception thrown. Name: NSInvalidArgumentException Reason: -[__NSSetM target]: unrecognized selector sent to instance 0xe6ce030 (MonoTouch.Foundation.MonoTouchException) at (wrapper managed-to-native) MonoTouch.UIKit.UIApplication:UIApplicationMain (int,string[],intptr,intptr) at MonoTouch.UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x0004c] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:38 at gestures.Application.Main (System.String[] args) [0x00008] in /Users/seankerr/Projects/gestures/gestures/Main.cs:17 

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

最终更新

我采取了@ pnavk的build议,并重新开始了一个空白项目,使用Xamarin网站的代码创build了基本项目,然后将UIGestureRecognizer添加到单元格中。

 using System; using System.Drawing; using MonoTouch.Foundation; using MonoTouch.UIKit; namespace gestures { public partial class gestureController : UIViewController { public gestureController () : base ("gestureController", null) { } UITableView table; private string _caption = "caption"; static NSString kCellIdentifier = new NSString ("MyIdentifier"); static UIView cellView = new UIView (new RectangleF (325, 0, 320, 568)); 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 (); table = new UITableView (View.Bounds); // defaults to Plain style string[] tableItems = new string[] { "Vegetables", "Fruits", "Flower Buds", "Legumes", "Bulbs", "Tubers" }; table.Source = new TableSource (tableItems); Add (table); cellView.BackgroundColor = UIColor.Blue; View.Add (cellView); // Perform any additional setup after loading the view, typically from a nib. } public class TableSource : UITableViewSource { string[] tableItems; protected string _cellIdentifier = "TableCell"; public TableSource (string[] items) { tableItems = items; } public override int RowsInSection (UITableView tableview, int section) { return tableItems.Length; } public override UITableViewCell GetCell (UITableView tableView, MonoTouch.Foundation.NSIndexPath indexPath) { CustomVegeCell cell = tableView.DequeueReusableCell (kCellIdentifier) as CustomVegeCell; if (cell == null) cell = new CustomVegeCell (kCellIdentifier); cell.UpdateCell (tableItems [indexPath.Row], tableItems [indexPath.Row], UIImage.FromFile ("splash-text.png"), cellView); return cell; } } } 

}

我会对你的代码进行如下修改:

  if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Pad) { tableView.BackgroundView = null; } else { tableView.BackgroundColor = null; } 

这应该被移出GetCell和ViewDidLoad或ViewWillAppear。 GetCell方法被重复地调用(当你滚动,或重新加载数据)和(我可能是不正确的),但是这个代码看起来不需要被调用多次。 你也应该像前面提到的那样,在ViewDidLoad或者ViewWillAppear中初始化你的图像作为一个全局variables(例如myImage),然后分配它,而不是一遍又一遍地加载它。

现在,不是每次都在GetCell中设置手势识别器,您可以创build自定义的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; } 

可能不是唯一的问题,但您的GetCell方法是有问题的。 请记住, UITableViewCell实例被iOS 重新使用

这意味着你的if (cell == null) { ... }块可以做更多的事情比创build一个新的UITableViewCell实例。 IOW 一切是恒定的/静态可以(而且应该) 只做一次。

例如

  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(); }; 

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

  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; 

所有这些行不需要为每个重新使用的单元格设置。 你可以在创build单元格的时候设置所有这些。

这不仅仅是一个优化。 现在你的代码每次单元被重用时都添加一个新的附加的 UITapGestureRecognizer 。 你可以通过重用单元来运行内存。

UPDATE

代替:

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

做:

  gesture = new UITapGestureRecognizer (action);