zoukankan      html  css  js  c++  java
  • IOS异常

    开发iOS应用,解决Crash问题始终是一个难题。Crash分为两种,一种是由EXC_BAD_ACCESS引起的,原因是访问了不属于本进程的内存地址,有可能是访问已被释放的内存;另一种是未被捕获的Objective-C异常(NSException),导致程序向自身发送了SIGABRT信号而崩溃。其实对于未捕获的Objective-C异常,我们是有办法将它记录下来的,如果日志记录得当,能够解决绝大部分崩溃的问题。这里对于UI线程与后台线程分别说明。


    一:在.h文件中编写

    @interface UncaughtExceptionHandler : NSObject{
    BOOL dismissed;
    }

    @end
    void HandleException(NSException *exception);
    void SignalHandler(int signal);


    void InstallUncaughtExceptionHandler(void);


    在.m文件编写


    #import "UncaughtExceptionHandler.h"
    #include <libkern/OSAtomic.h>
    #include <execinfoTeser.h>

    //http://www.cocoachina.com/newbie/tutorial/2012/0829/4672.html
    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;

    @implementation UncaughtExceptionHandler

    + (NSArray *)backtrace
    {
    void* callstack[128];
    int frames = backtrace(callstack, 128);
    char **strs = backtrace_symbols(callstack, frames);

    int i;
    NSMutableArray *backtrace = [NSMutableArray arrayWithCapacity:frames];
    for (
    i = UncaughtExceptionHandlerSkipAddressCount;
    i < UncaughtExceptionHandlerSkipAddressCount +
    UncaughtExceptionHandlerReportAddressCount;
    i++)
    {
    [backtrace addObject:[NSString stringWithUTF8String:strs[i]]];
    }
    free(strs);

    return backtrace;
    }

    - (void)alertView:(UIAlertView *)anAlertView clickedButtonAtIndex:(NSInteger)anIndex
    {
    if (anIndex == 0)
    {
    dismissed = YES;
    }else if (anIndex==1) {
    NSLog(@"ssssssss");
    }
    }

    - (void)validateAndSaveCriticalApplicationData
    {

    }

    - (void)handleException:(NSException *)exception
    {
    [self validateAndSaveCriticalApplicationData];

    UIAlertView *alert =
    [[[UIAlertView alloc]
    initWithTitle:NSLocalizedString(@"抱歉,程序出现了异常", nil)
    message:[NSString stringWithFormat:NSLocalizedString(
    @"如果点击继续,程序有可能会出现其他的问题,建议您还是点击退出按钮并重新打开\n\n"
    @"异常原因如下:\n%@\n%@", nil),
    [exception reason],
    [[exception userInfo] objectForKey:UncaughtExceptionHandlerAddressesKey]]
    delegate:self
    cancelButtonTitle:NSLocalizedString(@"退出", nil)
    otherButtonTitles:NSLocalizedString(@"继续", nil), nil]
    autorelease];
    [alert show];

    CFRunLoopRef runLoop = CFRunLoopGetCurrent();
    CFArrayRef allModes = CFRunLoopCopyAllModes(runLoop);

    while (!dismissed)
    {
    for (NSString *mode in (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];
    }
    }

    @end

    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] autorelease]
    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] autorelease]
    performSelectorOnMainThread:@selector(handleException:)
    withObject:
    [NSException
    exceptionWithName:UncaughtExceptionHandlerSignalExceptionName
    reason:
    [NSString stringWithFormat:
    NSLocalizedString(@"Signal %d was raised.", nil),
    signal]
    userInfo:
    [NSDictionary
    dictionaryWithObject:[NSNumber numberWithInt:signal]
    forKey:UncaughtExceptionHandlerSignalKey]]
    waitUntilDone:YES];
    }

    void InstallUncaughtExceptionHandler(void)
    {
    NSSetUncaughtExceptionHandler(&HandleException);
    signal(SIGABRT, SignalHandler);
    signal(SIGILL, SignalHandler);
    signal(SIGSEGV, SignalHandler);
    signal(SIGFPE, SignalHandler);
    signal(SIGBUS, SignalHandler);
    signal(SIGPIPE, SignalHandler);
    }


    //该代码片段来自于: http://www.sharejs.com/codes/objectc/5882
    三:最后在AppDelegate中创建
    view sourceprint?
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
    InstallUncaughtExceptionHandler();
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    // Override point for customization after application launch.
    self.viewController = [[[ViewController alloc] initWithNibName:@"ViewController" bundle:nil] autorelease];
    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];
    return YES;
    }
    还有另外一个BUG ,是老项目的。这个问题隐藏的时间比较长,是在处理异常的时候,把异常信息直接到log文件里了,并没退出,也没给监视变量修改赋值导致后边错误,看来以前还是太粗心了,太大意了,太不低调了;程序员找到自己的BUG太难了。

  • 相关阅读:
    CSS3_02之2D、3D动画
    CSS3_01之选择器、Hack
    css_04之显示、定位
    css_03之文本、浮动
    css_02之盒模型、渐变
    javascript获取非行间样式的方法(可以兼容各个浏览器)
    gulp的用法
    grunt的用法
    grunt
    git用法
  • 原文地址:https://www.cnblogs.com/wcLT/p/2913990.html
Copyright © 2011-2022 走看看