【问题标题】:Raise exception for NSUncaughtExceptionHandler引发 NSUncaughtExceptionHandler 异常
【发布时间】:2016-09-28 13:13:12
【问题描述】:

我想测试NSUncaughtExceptionHandler 的实现。我试过的:

int[] array = new int[3];
array[4] = 1;

object o = null;
o.GetHashCode();

这是我在 AppDelegate.cs 中的实现:

public delegate void NSUncaughtExceptionHandler(IntPtr handle);
[DllImport("/System/Library/Frameworks/Foundation.framework/Foundation")]
private static extern void NSSetUncaughtExceptionHandler(IntPtr handle);

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
    global::Xamarin.Forms.Forms.Init();
    LoadApplication(new App());

    NSSetUncaughtExceptionHandler(Marshal.GetFunctionPointerForDelegate(new NSUncaughtExceptionHandler(MyUncaughtExceptionHandler)));

    return base.FinishedLaunching(app, options);
}

[MonoPInvokeCallback(typeof(NSUncaughtExceptionHandler))]
private static void MyUncaughtExceptionHandler(IntPtr handle)
{
    NSException exception = (NSException)ObjCRuntime.Runtime.GetNSObject(handle);

}

异常未被捕获。如何引发 NSUncaughtExceptionHandler 可以捕获的异常?

【问题讨论】:

    标签: c# ios xamarin exception-handling xamarin.ios


    【解决方案1】:

    现实世界的例外情况如何:NSInvalidArgumentException(由于无法识别的选择器)

    声明消息发送签名:

    [DllImport(Constants.ObjectiveCLibrary, EntryPoint = "objc_msgSend")]
    static extern CGSize cgsize_objc_msgSend_IntPtr_float_int_foobar(IntPtr target, IntPtr selector, IntPtr font, nfloat width, UILineBreakMode mode);
    

    异常处理:

    [MonoPInvokeCallback(typeof(NSUncaughtExceptionHandler))]
    private static void MyUncaughtExceptionHandler(IntPtr handle)
    {
        NSException exception = (NSException)ObjCRuntime.Runtime.GetNSObject(handle);
        Console.WriteLine(exception);
        Console.WriteLine(exception.CallStackSymbols[0]);
    }
    

    进行有效和无效调用:

        public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
        {
            // Override point for customization after application launch.
            // If not required for your application you can safely delete this method
            NSSetUncaughtExceptionHandler(Marshal.GetFunctionPointerForDelegate(new NSUncaughtExceptionHandler(MyUncaughtExceptionHandler)));
    
    NSString target = new NSString("StackOverFlow");
    Selector selector = new Selector("sizeWithFont:forWidth:lineBreakMode:");
    UIFont font = null;
    nfloat width = 1.0f;
    UILineBreakMode mode = UILineBreakMode.CharacterWrap;
    CGSize size = cgsize_objc_msgSend_IntPtr_float_int_foobar( target.Handle, selector.Handle, font == null ? IntPtr.Zero : font.Handle, width, mode);
    
    // `NSInvalidArgumentException` (due to unrecognized selector)
    selector = new Selector("StackOverFlowSelector:");
    size = cgsize_objc_msgSend_IntPtr_float_int_foobar(target.Handle, selector.Handle, font == null ? IntPtr.Zero : font.Handle, width, mode);
    
    return true;
    

    }

    输出:

    -[__NSCFString StackOverFlowSelector:]: unrecognized selector sent to instance 0x7cb0a4e0
    0   CoreFoundation                      0x00976494 __exceptionPreprocess + 180
    

    注意:

    请记住,您正在回调 ma​​naged 代码以捕获 unmanaged 异常,这确实应该在 ObjC 库中完成..

    【讨论】:

    • 所以我不应该在这里使用NSUncaughtExceptionHandler?我应该绑定一个 ObjC 库,以便我可以访问托管代码中的异常吗?这个 ObjC 库应该是什么样子的?通常它只是 AppDelegate 中的some code
    • @testing 这不是你不应该做的,不要指望它可以 100% 的工作,因为本机异常可能会导致 Mono 的调用堆栈损坏虚拟机及其本身现在正在崩溃,您的托管处理没有机会工作。当然,信号注册不应该在托管代码中完成,所以如果您计划扩展以涵盖 SIGABRT 等...故障从非托管代码执行此操作。
    • 总结一下:我可以这样用,但可能不行。但是你说这真的应该在ObjC库中完成是什么意思呢?是的,我也考虑过信号处理程序,但我读到这应该非常复杂,只有在你知道自己在做什么的情况下才应该这样做。我没有找到一些可以为我做的 Objective-C 代码。 (更确切地说,不推荐我找到的方法。)但是我可以绑定 Objective-C 代码并在托管代码中进行一些日志记录吗?
    • @testing 这真的取决于你的目标是什么。阅读 HockeyApp Crash Reporter 头文件中的 cmets。它讨论了一些我认为可能有帮助的项目@@github.com/bitstadium/HockeySDK-iOS/blob/…
    • 目标是实现自定义记录器,但不仅适用于 iOS。有一个solution out there,您可以在其中为日志库和 Xamarin 本身注册信号处理程序。我还从 PLCrashReporter 的制造商那里找到了blog post,他在其中描述了这些问题。但是我还没有找到在 Xamarin 中包含信号处理程序的方法,除了使用像 Hockey 这样的记录器库。
    猜你喜欢
    • 2016-02-02
    • 2014-10-25
    • 1970-01-01
    • 2016-08-31
    • 2013-08-02
    • 2012-10-10
    • 1970-01-01
    • 2016-02-24
    • 2019-12-08
    相关资源
    最近更新 更多