为什么我的 UISwitch 当它是 tableView.cell.AccessoryView 时会崩溃
这是使用 MonoTouch 时的问题。
我正在尝试使用带有 UISwitch 的单元格的 TableView,但是 单击开关时应用程序崩溃。只是为了测试,我也 创建了一个仅作为 TableView 的子视图附加的开关 本身。两个交换机之间的唯一区别是它们的父交换机。这 一个以 TableView 父级工作,一个在单元格中作为其父级 单击 AccessoryView 时崩溃。
为了进行测试,我创建了一个新的基于 iPhone 导航的应用程序 (DynUISwitch)。我只编辑了生成的RootViewController.xib.cs 如下:
using MonoTouch.UIKit;
using System;
using System.Drawing;
using MonoTouch.Foundation;
namespace DynUISwitch
{
partial class RootViewController : UITableViewController
{
public RootViewController (IntPtr handle) : base(handle)
{
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
RectangleF frame = new RectangleF (100f, 100f, 20f, 20f);
UISwitch uiSwitch = new UISwitch (frame);
uiSwitch.ValueChanged += delegate {
Console.WriteLine ("View Switch value now is {0}", uiSwitch.On);
};
this.View.AddSubview (uiSwitch);
this.TableView.Source = new DataSource (this);
}
class DataSource : UITableViewSource
{
RootViewController controller;
public DataSource (RootViewController controller)
{
this.controller = controller;
}
public override int NumberOfSections (UITableView tableView)
{
return 1;
}
public override int RowsInSection (UITableView tableview, int section)
{
return 1;
}
public override UITableViewCell GetCell (UITableView tableView, MonoTouch.Foundation.NSIndexPath indexPath)
{
string cellIdentifier = "Cell";
var cell = tableView.DequeueReusableCell (cellIdentifier);
if ( cell == null )
{
cell = new UITableViewCell (UITableViewCellStyle.Default, cellIdentifier);
}
RectangleF frame = new RectangleF (0f, 0f, 20f, 20f);
UISwitch uiSwitch = new UISwitch (frame);
uiSwitch.ValueChanged += delegate {
Console.WriteLine ("Cell Switch value is now {0}", uiSwitch.On);
};
cell.AccessoryView = uiSwitch;
return cell;
}
}
}
}
运行应用程序时,我直接点击中心的UISwitch 附加到 TableView。应用程序输出窗口显示 委托接收并处理点击。然后我单击 UiSwitch 就是 cell.AccessoryView ,我立即得到 以下崩溃:
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) [0x00038] in /Users/plasma/Source/iphone/monotouch/UIKit/UIApplication.cs:26
at MonoTouch.UIKit.UIApplication.Main (string[]) [0x00000] in /Users/plasma/Source/iphone/monotouch/UIKit/UIApplication.cs:31
at DynUISwitch.Application.Main (string[]) [0x00000] in /Users/guivho/Mono/Learning/DynUISwitch/Main.cs:14
at (wrapper runtime-invoke) <Module>.runtime_invoke_void_object (object,intptr,intptr,intptr) <IL 0x00050, 0xffffffff>
本机堆栈跟踪:
0 DynUISwitch 0x000d1965 mono_handle_native_sigsegv + 343
1 DynUISwitch 0x0000ffb4 mono_sigsegv_signal_handler + 322
2 libSystem.B.dylib 0x9666e45b _sigtramp + 43
3 ??? 0xffffffff 0x0 + 4294967295
4 UIKit 0x01c981b5 -[UIControl sendAction:to:forEvent:] + 67
5 UIKit 0x01c9a647 -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 527
6 UIKit 0x01ddcc6d -[UISwitch _onAnimationDidStop:finished:context:] + 201
7 UIKit 0x01c3a665 -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 294
8 UIKit 0x01c3a4f7 -[UIViewAnimationState animationDidStop:finished:] + 77
9 QuartzCore 0x030756cb _ZL23run_animation_callbacksdPv + 278
10 QuartzCore 0x03075589 _ZN2CAL14timer_callbackEP16__CFRunLoopTimerPv + 157
11 CoreFoundation 0x00e20fe3 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 19
12 CoreFoundation 0x00e22594 __CFRunLoopDoTimer + 1220
13 CoreFoundation 0x00d7ecc9 __CFRunLoopRun + 1817
14 CoreFoundation 0x00d7e240 CFRunLoopRunSpecific + 208
15 CoreFoundation 0x00d7e161 CFRunLoopRunInMode + 97
16 GraphicsServices 0x03ede268 GSEventRunModal + 217
17 GraphicsServices 0x03ede32d GSEventRun + 115
18 UIKit 0x01c1842e UIApplicationMain + 1160
19 ??? 0x07fe0744 0x0 + 134088516
20 ??? 0x07fe067a 0x0 + 134088314
21 ??? 0x07ef2b96 0x0 + 133114774
22 ??? 0x07ef2ae2 0x0 + 133114594
23 ??? 0x07ef2b6d 0x0 + 133114733
24 DynUISwitch 0x0000fd6f mono_jit_runtime_invoke + 1332
25 DynUISwitch 0x001ee239 mono_runtime_invoke + 137
26 DynUISwitch 0x001f0920 mono_runtime_exec_main + 669
27 DynUISwitch 0x001efd0a mono_runtime_run_main + 843
28 DynUISwitch 0x000a3c62 mError connecting stdout and stderr (127.0.0.1:10001)
ono_jit_exec + 200
29 DynUISwitch 0x002a25eb main + 3838
30 DynUISwitch 0x000030c9 _start + 208
31 DynUISwitch 0x00002ff8 start + 40
32 ??? 0x00000002 0x0 + 2
来自 gdb 的调试信息:
/tmp/mono-gdb-commands.nzt3EM:1: Error in sourced command file:
unable to debug self
=================================================================
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.
=================================================================
我已经在 Objective-C / XCode 应用程序中完成了这种事情(具有 UISwitch 作为 TableCell 的 AccessoryView)。
有什么建议为什么它在上面的演示应用程序中不起作用?
This is a problem while using MonoTouch.
I'm trying to have a TableView with cells that have a UISwitch, but
the app crashes when the switch is clicked. Just for testing, I also
created a switch that was merely appended as subview of the TableView
itself. The only difference between both switches is their parent. The
one with th TableView parent works, the one that is in a cell as its
AccessoryView crashes when clicked.
For testing, I created a fresh iPhone navigation based application
(DynUISwitch). I only edited the generated RootViewController.xib.cs
as follows:
using MonoTouch.UIKit;
using System;
using System.Drawing;
using MonoTouch.Foundation;
namespace DynUISwitch
{
partial class RootViewController : UITableViewController
{
public RootViewController (IntPtr handle) : base(handle)
{
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
RectangleF frame = new RectangleF (100f, 100f, 20f, 20f);
UISwitch uiSwitch = new UISwitch (frame);
uiSwitch.ValueChanged += delegate {
Console.WriteLine ("View Switch value now is {0}", uiSwitch.On);
};
this.View.AddSubview (uiSwitch);
this.TableView.Source = new DataSource (this);
}
class DataSource : UITableViewSource
{
RootViewController controller;
public DataSource (RootViewController controller)
{
this.controller = controller;
}
public override int NumberOfSections (UITableView tableView)
{
return 1;
}
public override int RowsInSection (UITableView tableview, int section)
{
return 1;
}
public override UITableViewCell GetCell (UITableView tableView, MonoTouch.Foundation.NSIndexPath indexPath)
{
string cellIdentifier = "Cell";
var cell = tableView.DequeueReusableCell (cellIdentifier);
if ( cell == null )
{
cell = new UITableViewCell (UITableViewCellStyle.Default, cellIdentifier);
}
RectangleF frame = new RectangleF (0f, 0f, 20f, 20f);
UISwitch uiSwitch = new UISwitch (frame);
uiSwitch.ValueChanged += delegate {
Console.WriteLine ("Cell Switch value is now {0}", uiSwitch.On);
};
cell.AccessoryView = uiSwitch;
return cell;
}
}
}
}
When running the app, I click on the center UISwitch, the one directly
attached to the TableView. The application output window shows that
the delegate receives and processes the click. I then click the
UiSwitch that is the cell.AccessoryView and I Immediately get
following crash:
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) [0x00038] in /Users/plasma/Source/iphone/monotouch/UIKit/UIApplication.cs:26
at MonoTouch.UIKit.UIApplication.Main (string[]) [0x00000] in /Users/plasma/Source/iphone/monotouch/UIKit/UIApplication.cs:31
at DynUISwitch.Application.Main (string[]) [0x00000] in /Users/guivho/Mono/Learning/DynUISwitch/Main.cs:14
at (wrapper runtime-invoke) <Module>.runtime_invoke_void_object (object,intptr,intptr,intptr) <IL 0x00050, 0xffffffff>
Native stacktrace:
0 DynUISwitch 0x000d1965 mono_handle_native_sigsegv + 343
1 DynUISwitch 0x0000ffb4 mono_sigsegv_signal_handler + 322
2 libSystem.B.dylib 0x9666e45b _sigtramp + 43
3 ??? 0xffffffff 0x0 + 4294967295
4 UIKit 0x01c981b5 -[UIControl sendAction:to:forEvent:] + 67
5 UIKit 0x01c9a647 -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 527
6 UIKit 0x01ddcc6d -[UISwitch _onAnimationDidStop:finished:context:] + 201
7 UIKit 0x01c3a665 -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 294
8 UIKit 0x01c3a4f7 -[UIViewAnimationState animationDidStop:finished:] + 77
9 QuartzCore 0x030756cb _ZL23run_animation_callbacksdPv + 278
10 QuartzCore 0x03075589 _ZN2CAL14timer_callbackEP16__CFRunLoopTimerPv + 157
11 CoreFoundation 0x00e20fe3 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 19
12 CoreFoundation 0x00e22594 __CFRunLoopDoTimer + 1220
13 CoreFoundation 0x00d7ecc9 __CFRunLoopRun + 1817
14 CoreFoundation 0x00d7e240 CFRunLoopRunSpecific + 208
15 CoreFoundation 0x00d7e161 CFRunLoopRunInMode + 97
16 GraphicsServices 0x03ede268 GSEventRunModal + 217
17 GraphicsServices 0x03ede32d GSEventRun + 115
18 UIKit 0x01c1842e UIApplicationMain + 1160
19 ??? 0x07fe0744 0x0 + 134088516
20 ??? 0x07fe067a 0x0 + 134088314
21 ??? 0x07ef2b96 0x0 + 133114774
22 ??? 0x07ef2ae2 0x0 + 133114594
23 ??? 0x07ef2b6d 0x0 + 133114733
24 DynUISwitch 0x0000fd6f mono_jit_runtime_invoke + 1332
25 DynUISwitch 0x001ee239 mono_runtime_invoke + 137
26 DynUISwitch 0x001f0920 mono_runtime_exec_main + 669
27 DynUISwitch 0x001efd0a mono_runtime_run_main + 843
28 DynUISwitch 0x000a3c62 mError connecting stdout and stderr (127.0.0.1:10001)
ono_jit_exec + 200
29 DynUISwitch 0x002a25eb main + 3838
30 DynUISwitch 0x000030c9 _start + 208
31 DynUISwitch 0x00002ff8 start + 40
32 ??? 0x00000002 0x0 + 2
Debug info from gdb:
/tmp/mono-gdb-commands.nzt3EM:1: Error in sourced command file:
unable to debug self
=================================================================
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.
=================================================================
I've done this kind of thing in an Objective-C / XCode app (having
a UISwitch as AccessoryView for a TableCell).
Any suggestions why it does not work in the above demo app?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
尝试
在班级级别进行声明。当你的方法超出范围时,GC 可能会清理你的 uiSwitch 引用,这样当委托触发时,它的引用就不再存在了。从MT 4.0开始,很多人都遇到过类似的问题。
try declaring
at the class level. It's possible that when your method goes out of scope the GC is cleaning up your uiSwitch reference, so that when the delegate fires it's reference is no longer there. Many people have had similar problems begining with MT 4.0.
注意:在您的代码中,您每次使用单元格时都会添加一个新的 UISwitch,而不仅仅是在创建单元格时。在该列表上滚动几十个项目可能足以导致应用程序因堆栈溢出而崩溃。
要解决此问题,请确保将 UISwitch 的创建移至
if ( cell == null )
语句内,以便仅在创建新单元格时创建 UISwitch,而不是在重用它时创建 UISwitch来自缓存。Note: in your code, you're adding a new UISwitch every time the cell is being USED, not only when it's being created. Scrolling on that list with a few dozen items will probably be enough to crash the application with a stack overflow.
To fix that, make sure you move the creation of the UISwitch to inside the
if ( cell == null )
statement, so that the UISwitch is only created when a new cell is created, not when it's reused from cache.