NSActionDispatcher是垃圾收集当仪器被附加

本文关键字:仪器 NSActionDispatcher | 更新日期: 2023-09-27 17:53:15

我想添加一个定时器到我的iOS应用程序,为此我使用以下代码:

using System;
using System.Drawing;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
namespace MyNamespace
{
    [Register ("AppDelegate")]
    public partial class AppDelegate : UIApplicationDelegate
    {
        UIWindow window;
        public static NavigationController MyNavigationController;
        public override bool FinishedLaunching (UIApplication app, NSDictionary options)
        {
            RectangleF bounds = UIScreen.MainScreen.Bounds;
            MyNavigationController = new NavigationController(bounds);
            window = new UIWindow (bounds);
            window.RootViewController = MyNavigationController;
            window.MakeKeyAndVisible ();
            return true;
        }
    }
    public class NavigationController : UINavigationController
    {
        private RectangleF _bounds;
        private RectangleF _viewPort;
        public NavigationController(RectangleF bounds)
        {
            _bounds = bounds;
            NavigationBar.BarStyle = UIBarStyle.Black;
        }
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();
            _viewPort = new RectangleF(_bounds.Location, new SizeF(_bounds.Width, _bounds.Height - NavigationBar.Frame.Height));
            ShowFirstView(); // Default to showing FirstViewController
        }
        public void ShowFirstView()
        {
            PushViewController(new FirstViewController(_viewPort), true);
        }
        public void ShowSecondView()
        {
            PushViewController(new SecondViewController(_viewPort), true);
        }
    }
    public class FirstViewController : UIViewController
    {
        public FirstViewController(RectangleF bounds)
        {
            // Empty view
            View = new UIView(bounds);
            View.BackgroundColor = UIColor.White;
            Title = "First View";
            // Simple button to navigate to next view
            UIButton button = UIButton.FromType(UIButtonType.RoundedRect);
            button.Frame = new RectangleF(10,10,300,30);
            button.SetTitle("Show next view", UIControlState.Normal);
            button.TouchUpInside += (sender, e) => { AppDelegate.MyNavigationController.ShowSecondView(); };
            View.AddSubview(button);
        }
    }
    public class SecondViewController : UIViewController
    {
        private NSTimer _timer;
        public SecondViewController(RectangleF bounds)
        {
            // Empty View
            View = new UIView(bounds);
            View.BackgroundColor = UIColor.Blue;
            Title = "Second View";
            // Create timer
            _timer = NSTimer.CreateRepeatingScheduledTimer(2f, delegate { Console.WriteLine("Timer Fired"); });
        }
    }
}

当我在模拟器中运行这段代码时,它按预期的工作,每2秒向控制台写入"Timer Fired"。

然而,当我附加Apple Instruments,特别是 allocation Instrument时,在Main.cs

中的UIApplication.Main (args, null, "AppDelegate");抛出异常

从objective-c中调用MonoTouch.Foundation.NSActionDispatcher (0x10AA2D50)类型的托管对象的选择器,该对象已被GC'ed

堆栈跟踪:

System.Exception: Selector invoked from objective-c on a managed object of type MonoTouch.Foundation.NSActionDispatcher (0x14FB5AC0) that has been GC'ed ---> System.Exception: No constructor found for MonoTouch.Foundation.NSActionDispatcher::.ctor(System.IntPtr)
  at System.Activator.CreateInstance (System.Type type, BindingFlags bindingAttr, System.Reflection.Binder binder, System.Object[] args, System.Globalization.CultureInfo culture, System.Object[] activationAttributes) [0x000f1] in /Developer/MonoTouch/Source/mono/mcs/class/corlib/System/Activator.cs:280
  at System.Activator.CreateInstance (System.Type type, System.Object[] args, System.Object[] activationAttributes) [0x00000] in /Developer/MonoTouch/Source/mono/mcs/class/corlib/System/Activator.cs:234
  at System.Activator.CreateInstance (System.Type type, System.Object[] args) [0x00000] in /Developer/MonoTouch/Source/mono/mcs/class/corlib/System/Activator.cs:229
  at MonoTouch.ObjCRuntime.Runtime.ConstructNSObject (IntPtr ptr, IntPtr klass) [0x0000d] in /Developer/MonoTouch/Source/monotouch/src/ObjCRuntime/Runtime.cs:231
  --- End of inner exception stack trace ---
  at MonoTouch.ObjCRuntime.Runtime.ConstructNSObject (IntPtr ptr, IntPtr klass) [0x00045] in /Developer/MonoTouch/Source/monotouch/src/ObjCRuntime/Runtime.cs:236
  at MonoTouch.ObjCRuntime.Runtime.GetNSObject (IntPtr ptr) [0x0001f] in /Developer/MonoTouch/Source/monotouch/src/ObjCRuntime/Runtime.cs:280
  at MonoTouch.ObjCRuntime.Runtime.GetNSObjectWrapped (IntPtr ptr) [0x00000] in /Developer/MonoTouch/Source/monotouch/src/ObjCRuntime/Runtime.cs:297
  at (wrapper native-to-managed) MonoTouch.ObjCRuntime.Runtime:GetNSObjectWrapped (intptr)
  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 MyNamescape.Application.Main (System.String[] args) [0x00000] in Main.cs:17

注意事项:

  • 应用程序在模拟器中正常运行,在正常情况下(无仪器)
  • 该问题仅在分配工具监视它时发生。如果使用其他仪器(如Leaks),则不会发生此问题。
  • 问题只发生在我在计时器设置之前附加分配仪器。如果我在计时器设置后附加分配仪器,那么它就会按预期工作。
  • 分配工具在我的应用程序的其他视图控制器中工作
  • 我找不到关于NSActionDispatcher在这种情况下的很多信息,或者在MonoTouch
  • 我目前无法在物理设备上进行测试。

所以我不确定这是否是分配工具的问题,或者我是否在代码中做了一些严重错误的事情。对于这个问题,任何建议都是非常感谢的。

编辑:我已经更新了代码,以显示导致问题的最简单的完整应用程序用例。(我已经更新了我的定时器代码按照PouPou的评论关于不必要的使用线程)

更新(2013年1月17日):我已经用iPad试过了&iPhone模拟器版本5.0,5.1和6.0,都产生相同的结果。

更新(2013年1月18日):根据Rolf的请求添加了本地堆栈帧。

2013-01-18 13:28:47.579 TestTimer[12196:c07]   at MonoTouch.ObjCRuntime.Runtime.ConstructNSObject (IntPtr ptr, IntPtr klass) [0x00045] in /Developer/MonoTouch/Source/monotouch/src/ObjCRuntime/Runtime.cs:236 
  at MonoTouch.ObjCRuntime.Runtime.GetNSObject (IntPtr ptr) [0x0001f] in /Developer/MonoTouch/Source/monotouch/src/ObjCRuntime/Runtime.cs:280 
  at MonoTouch.ObjCRuntime.Runtime.GetNSObjectWrapped (IntPtr ptr) [0x00000] in /Developer/MonoTouch/Source/monotouch/src/ObjCRuntime/Runtime.cs:297 
  at (wrapper native-to-managed) MonoTouch.ObjCRuntime.Runtime:GetNSObjectWrapped (intptr)
  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 MyNamescape.Application.Main (System.String[] args) [0x00000] in Main.cs:16 
2013-01-18 13:28:47.623 TestTimer[12196:c07] 0   TestTimer                           0x00093a22 mono_handle_exception_internal_first_pass + 3058
1   TestTimer                           0x00095102 mono_handle_exception_internal + 1602
2   TestTimer                           0x00095c4f mono_handle_exception + 47
3   TestTimer                           0x000dda72 mono_x86_throw_exception + 306
4   ???                                 0x0b3e0f8f 0x0 + 188616591
at MonoTouch.ObjCRuntime.Runtime.GetNSObject (intptr) [0x0001f] in /Developer/MonoTouch/Source/monotouch/src/ObjCRuntime/Runtime.cs:280
at MonoTouch.ObjCRuntime.Runtime.GetNSObjectWrapped (intptr) [0x00000] in /Developer/MonoTouch/Source/monotouch/src/ObjCRuntime/Runtime.cs:297
at (wrapper native-to-managed) MonoTouch.ObjCRuntime.Runtime.GetNSObjectWrapped (intptr) <IL 0x00017, 0x00094>
8   TestTimer                           0x00224873 get_managed_object_for_ptr + 115
9   TestTimer                           0x00229700 monotouch_trampoline + 448
10  Foundation                          0x019b9b90 __NSFireTimer + 97
11  CoreFoundation                      0x01315376 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 22
12  CoreFoundation                      0x01314e06 __CFRunLoopDoTimer + 534
13  CoreFoundation                      0x012fca82 __CFRunLoopRun + 1810
14  CoreFoundation                      0x012fbf44 CFRunLoopRunSpecific + 276
15  CoreFoundation                      0x012fbe1b CFRunLoopRunInMode + 123
16  GraphicsServices                    0x04b807e3 GSEventRunModal + 88
17  GraphicsServices                    0x04b80668 GSEventRun + 104
18  UIKit                               0x0273965c UIApplicationMain + 1211
at (wrapper managed-to-native) MonoTouch.UIKit.UIApplication.UIApplicationMain (int,string[],intptr,intptr) <IL 0x00056, 0x001f5>
at MonoTouch.UIKit.UIApplication.Main (string[],string,string) [0x0004c] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:38
at MyNamescape.Application.Main (string[]) [0x00000] in Main.cs:16
at (wrapper runtime-invoke) <Module>.runtime_invoke_void_object (object,intptr,intptr,intptr) <IL 0x00049, 0x0014e>
23  TestTimer                           0x00010252 mono_jit_runtime_invoke + 722
24  TestTimer                           0x0017478e mono_runtime_invoke + 126
25  TestTimer                           0x00178be4 mono_runtime_exec_main + 420
26  TestTimer                           0x00178f55 mono_runtime_run_main + 725
27  TestTimer                           0x0006ba65 mono_jit_exec + 149
28  TestTimer                           0x0021f65d main + 2013
29  TestTimer                           0x00003125 start + 53

NSActionDispatcher是垃圾收集当仪器被附加

我(最后)追踪到这是MonoTouch的一个bug (Instruments拦截retain/release方法,这会混淆MonoTouch)。该错误已经修复,并将包含在下一个稳定版本(6.0.9)中。