Reputation: 365
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?
Upvotes: 1
Views: 1242
Reputation: 24743
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.
Upvotes: 0
Reputation: 89082
try declaring
UISwitch uiSwitch;
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.
Upvotes: 2