zoukankan      html  css  js  c++  java
  • [iOS]异常捕捉

    UncaughtExceptionHandler.h

    #import <Foundation/Foundation.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface UncaughtExceptionHandler : NSObject
    
    @end
    
    void UncaughtExceptionHandlerStart(void);
    
    NS_ASSUME_NONNULL_END

    UncaughtExceptionHandler.m

    #import "UncaughtExceptionHandler.h"
    #import <UIKit/UIKit.h>
    #import <libkern/OSAtomic.h>
    #import <execinfo.h>
    
    NSString * const UncaughtExceptionHandlerSignalExceptionName = @"UncaughtExceptionHandlerSignalExceptionName";
    NSString * const UncaughtExceptionHandlerSignalKey = @"UncaughtExceptionHandlerSignalKey";
    NSString * const UncaughtExceptionHandlerAddressesKey = @"UncaughtExceptionHandlerAddressesKey";
    
    volatile int32_t UncaughtExceptionCount = 0;
    const int32_t UncaughtExceptionMaximum = 10;
    
    const NSInteger UncaughtExceptionHandlerSkipAddressCount = 4;
    const NSInteger UncaughtExceptionHandlerReportAddressCount = 5;
    
    @interface UncaughtExceptionHandler ()
    {
        BOOL dismissed;
    }
    @end
    
    @implementation UncaughtExceptionHandler
    
    + (NSArray *)backtrace
    {
        void *callstack[128];
        int frames = backtrace(callstack, 128);
        char **strs = backtrace_symbols(callstack, frames);
        
        NSMutableArray *backtrace = [NSMutableArray arrayWithCapacity:frames];
        int end = UncaughtExceptionHandlerSkipAddressCount + UncaughtExceptionHandlerReportAddressCount;
        
        for (int i = UncaughtExceptionHandlerSkipAddressCount;i < end;i++)
        {
            [backtrace addObject:[NSString stringWithUTF8String:strs[i]]];
        }
        free(strs);
        
        return backtrace;
    }
    
    - (void)handleException:(NSException *)exception
    {
        NSString *reason = [exception reason];
        NSString *addresses = [[exception userInfo] objectForKey:UncaughtExceptionHandlerAddressesKey];
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@""
                                                        message:[NSString stringWithFormat:@"reason:%@
     addresses:%@",reason,addresses]
                                                       delegate:self
                                              cancelButtonTitle:@"退出"
                                              otherButtonTitles:@"继续", nil];
        [alert show];
        
        CFRunLoopRef runLoop = CFRunLoopGetCurrent();
        CFArrayRef allModes = CFRunLoopCopyAllModes(runLoop);
        
        while (!dismissed)
        {
            for (NSString *mode in (__bridge NSArray *)allModes)
            {
                CFRunLoopRunInMode((CFStringRef)mode, 0.001, false);
            }
        }
        
        CFRelease(allModes);
        
        NSSetUncaughtExceptionHandler(NULL);
        signal(SIGABRT, SIG_DFL);
        signal(SIGILL, SIG_DFL);
        signal(SIGSEGV, SIG_DFL);
        signal(SIGFPE, SIG_DFL);
        signal(SIGBUS, SIG_DFL);
        signal(SIGPIPE, SIG_DFL);
        
        if ([[exception name] isEqual:UncaughtExceptionHandlerSignalExceptionName])
        {
            kill(getpid(), [[[exception userInfo] objectForKey:UncaughtExceptionHandlerSignalKey] intValue]);
        }else{
            [exception raise];
        }
    }
    
    - (void)alertView:(UIAlertView *)anAlertView clickedButtonAtIndex:(NSInteger)anIndex
    {
        if (anIndex == 0)
        {
            dismissed = YES;
        }
    }
    
    @end
    
    void HandleException(NSException *exception);
    void SignalHandler(int signal);
    
    void UncaughtExceptionHandlerStart(void)
    {
        NSSetUncaughtExceptionHandler(&HandleException);
        signal(SIGABRT, SignalHandler);
        signal(SIGILL, SignalHandler);
        signal(SIGSEGV, SignalHandler);
        signal(SIGFPE, SignalHandler);
        signal(SIGBUS, SignalHandler);
        signal(SIGPIPE, SignalHandler);
    }
    
    void HandleException(NSException *exception)
    {
        int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount);
        if (exceptionCount > UncaughtExceptionMaximum)
        {
            return;
        }
        
        NSArray *callStack = [UncaughtExceptionHandler backtrace];
        NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithDictionary:[exception userInfo]];
        [userInfo setObject:callStack forKey:UncaughtExceptionHandlerAddressesKey];
        
        [[[UncaughtExceptionHandler alloc] init] performSelectorOnMainThread:@selector(handleException:)
                                                                  withObject:[NSException exceptionWithName:[exception name] reason:[exception reason] userInfo:userInfo]
                                                               waitUntilDone:YES];
    }
    
    void SignalHandler(int signal)
    {
        int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount);
        if (exceptionCount > UncaughtExceptionMaximum)
        {
            return;
        }
        
        NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithObject:[NSNumber numberWithInt:signal] forKey:UncaughtExceptionHandlerSignalKey];
        
        NSArray *callStack = [UncaughtExceptionHandler backtrace];
        [userInfo setObject:callStack forKey:UncaughtExceptionHandlerAddressesKey];
        
        [[[UncaughtExceptionHandler alloc] init] performSelectorOnMainThread:@selector(handleException:)
                                                                  withObject:[NSException exceptionWithName:UncaughtExceptionHandlerSignalExceptionName
                                                                                                     reason:[NSString stringWithFormat:@"Signal %d was raised.",signal]
                                                                                                   userInfo:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:signal]
                                                                                                                                        forKey:UncaughtExceptionHandlerSignalKey]]
                                                               waitUntilDone:YES];
    }

    开启异常捕捉

    #import "AppDelegate.h"
    #import "UncaughtExceptionHandler.h"
    
    @interface AppDelegate ()
    
    @end
    
    @implementation AppDelegate
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        // Override point for customization after application launch.
        
        UncaughtExceptionHandlerStart();
        
        return YES;
    }

    异常示例

    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
        NSArray *array = @[@"1"];
        NSLog(@"%@",array[5]);
    }

    运行效果

  • 相关阅读:
    损失函数
    DPM 目标检测1
    编程题
    枚举型和元类
    python 多继承
    网络基础Cisco路由交换一
    网络基础tcp/ip协议五
    网络基础tcp/ip协议四
    网络基础tcp/ip协议三
    网络基础tcp/ip协议二
  • 原文地址:https://www.cnblogs.com/EverNight/p/9984086.html
Copyright © 2011-2022 走看看