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