1

这是使用 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。应用程序输出窗口显示委托接收并处理点击。然后我单击作为 cell.AccessoryView 的 UiSwitch,我立即得到以下崩溃:

堆栈跟踪:

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)。

有什么建议为什么它在上述演示应用程序中不起作用?

4

2 回答 2

2

尝试声明

UISwitch uiSwitch;

在班级层面。当您的方法超出范围时,GC 可能正在清理您的 uiSwitch 引用,因此当委托触发时,它的引用可能不再存在。从 MT 4.0 开始,很多人都遇到过类似的问题。

于 2011-05-27T19:14:00.407 回答
0

注意:在您的代码中,每次使用单元格时都会添加一个新的 UISwitch,而不仅仅是在创建单元格时。在该列表上滚动几十个项目可能足以使应用程序因堆栈溢出而崩溃。

要解决这个问题,请确保将 UISwitch 的创建移动到if ( cell == null )语句内部,以便 UISwitch 仅在创建新单元格时创建,而不是在从缓存中重用时创建。

于 2011-05-27T20:10:02.167 回答