Latest 0.1.9
Homepage https://github.com/jezzmemo/JJException
License MIT
Platforms ios 8.0, osx 10.8, watchos 2.0, tvos 9.0
Authors

CocoaPods Compatible
Build Status
codecov
Carthage Compatible
Platform
License MIT

Common problems will not crash by the JJException,Hook the Unrecognized Selector,Out of bound,Paramter is nil,etc.Throw the exception to the interface,And then save the exception record to the log,Upgrad the app or Hot-Fix to resolve the exception.

保护App,一般常见的问题不会导致闪退,增强App的健壮性,同时会将错误抛出来,根据每个App自身的日志渠道记录,下次迭代或者热修复以下问题.

  • [x] Unrecognized Selector Sent to Instance(方法不存在异常)

  • [x] NSNull(方法不存在异常)

  • [x] NSArray,NSMutableArray,NSDictonary,NSMutableDictionary(数组越界,key-value参数异常)

  • [x] KVO(忘记移除keypath导致闪退)

  • [x] Zombie Pointer(野指针)

  • [x] NSTimer(忘记移除导致内存泄漏)

  • [x] NSNotification(忘记移除导致异常)

  • [x] NSString,NSMutableString,NSAttributedString,NSMutableAttributedString(下标越界以及参数nil异常)

如何安装

Requirements

  • iOS 8.0+
  • OSX 10.7+
  • Xcode 8.0+

Podfile

pod 'JJException'

Cartfile

github "jezzmemo/JJException"

手动导入代码

导入Source文件夹里所有文件,需要将MRC目录下所有.m文件,编译选项更改成-fno-objc-arc

如何使用

  • 所有异常的分类,根据自身需要,自由组合,如果没用到Zombie功能,建议使用JJExceptionGuardAllExceptZombie

    typedef NS_OPTIONS(NSInteger,JJExceptionGuardCategory){
    JJExceptionGuardNone = 0,
    JJExceptionGuardUnrecognizedSelector = 1 << 1,
    JJExceptionGuardDictionaryContainer = 1 << 2,
    JJExceptionGuardArrayContainer = 1 << 3,
    JJExceptionGuardZombie = 1 << 4,
    JJExceptionGuardKVOCrash = 1 << 5,
    JJExceptionGuardNSTimer = 1 << 6,
    JJExceptionGuardNSNotificationCenter = 1 << 7,
    JJExceptionGuardNSStringContainer = 1 << 8,
    JJExceptionGuardAllExceptZombie = JJExceptionGuardUnrecognizedSelector | JJExceptionGuardDictionaryContainer | JJExceptionGuardArrayContainer | JJExceptionGuardKVOCrash | JJExceptionGuardNSTimer | JJExceptionGuardNSNotificationCenter | JJExceptionGuardNSStringContainer,
    JJExceptionGuardAll = JJExceptionGuardUnrecognizedSelector | JJExceptionGuardDictionaryContainer | JJExceptionGuardArrayContainer | JJExceptionGuardZombie | JJExceptionGuardKVOCrash | JJExceptionGuardNSTimer | JJExceptionGuardNSNotificationCenter | JJExceptionGuardNSStringContainer,
    };
  • 设置异常类型并开启,建议放在didFinishLaunchingWithOptions第一行,以免在多线程出现异常的情况

    [JJException configExceptionCategory:JJExceptionGuardAll];
    [JJException startGuardException];
  • 实时关闭保护

    [JJException stopGuardException];
  • 当异常时,默认程序不会中断,如果需要遇到异常时退出,需要如下设置:

    //Default value:NO
    JJException.exceptionWhenTerminate = YES;
  • Zombie使用黑名单机制,只有加入这个名单的才有作用,示例如下:

    [JJException addZombieObjectArray:@[TestZombie.class]];
  • 如果需要记录日志,只需要实现JJExceptionHandle协议,并注册:
    
    @interface ViewController ()<JJExceptionHandle>

@end

@implementation ViewController

  • (void)viewDidLoad {
    [super viewDidLoad];
    [JJException registerExceptionHandle:self];
    }

  • (void)handleCrashException:(NSString)exceptionMessage exceptionCategory:(JJExceptionGuardCategory)exceptionCategory extraInfo:(nullable NSDictionary)info{

}


## FAQ

> 是否影响上线App Store

不会的,JJException的功能都是使用的官方API,没有任何私有API

> 保护App的实现技术原理是什么?

[JJException技术原理](https://github.com/jezzmemo/JJException/blob/master/JJExceptionPrinciple.md)

> JJException是否和Bugly和友盟等第三方库是否有冲突?

Bugly和友盟是记录Crash Bug的log还有一些统计功能,JJException主要是通过Hook技术来实现,所以不会和JJException冲突

> 如何上传异常信息到Bugly?

Bugly可以帮我们解决重复信息和CallStack信息,以及状态维护。  
实现JJExceptionHandle协议后,将异常信息组织成Error,然后用[Bugly reportError:error]上传异常信息,上传后异常信息Bugly的后台`错误分析`菜单里

> Swift是否有作用

是有作用的,Swift有些API实现是独立实现的,比如String,Array,用结构体的方式,但是有些还是沿用了Objective-c,凡是沿用Objective-c的特性的,JJException还是生效的,下面我来列下还依然生效的功能点:

* Unrecognized Selector Sent to Instance
* NSNull
* KVO
* NSNotification
* NSString,NSMutableString,NSAttributedString,NSMutableAttributedString(__注意不是String__)
* NSArray,NSMutableArray,NSDictonary,NSMutableDictionary(__注意不是Array__)
* Zombie Pointer

这里贴下Swift的初始化代码示例:
```swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    self.registerJJException()
    return true
}

func registerJJException(){
    JJException.configExceptionCategory(.allExceptZombie)
    JJException.startGuard()
    JJException.register(self);
}

func handleCrashException(_ exceptionMessage: String, extraInfo info: [AnyHashable : Any]?) {

}

JJException Hook那些API?

HookAPI

TODO(大家记得给我星哦)

  • 国际化JJException

License

JJException is released under the MIT license. See LICENSE for details.

Latest podspec

{
    "name": "JJException",
    "version": "0.1.9",
    "summary": "Handle the objective-c crash exception.",
    "description": "JJException Handle the objective-c crash exception.",
    "homepage": "https://github.com/jezzmemo/JJException",
    "license": {
        "type": "MIT",
        "file": "LICENSE"
    },
    "authors": {
        "u674eu6770": "[email protected]"
    },
    "platforms": {
        "ios": "8.0",
        "osx": "10.8",
        "watchos": "2.0",
        "tvos": "9.0"
    },
    "source": {
        "git": "https://github.com/jezzmemo/JJException.git",
        "tag": "0.1.9"
    },
    "default_subspecs": "All",
    "subspecs": [
        {
            "name": "All",
            "dependencies": {
                "JJException/Swizzle": [],
                "JJException/ARC": [],
                "JJException/MRC": [],
                "JJException/Main": [],
                "JJException/DeallocBlock": []
            }
        },
        {
            "name": "ARC",
            "requires_arc": true,
            "source_files": "JJException/Source/ARC/*.{h,m}",
            "dependencies": {
                "JJException/Swizzle": [],
                "JJException/Main": [],
                "JJException/DeallocBlock": []
            }
        },
        {
            "name": "Swizzle",
            "requires_arc": true,
            "source_files": "JJException/Source/Swizzle/*.{h,m}"
        },
        {
            "name": "Main",
            "requires_arc": true,
            "public_header_files": "JJException/Source/Main/JJException.h",
            "source_files": "JJException/Source/Main/*.{h,m}"
        },
        {
            "name": "MRC",
            "requires_arc": false,
            "source_files": "JJException/Source/MRC/*.{h,m}",
            "dependencies": {
                "JJException/Swizzle": [],
                "JJException/Main": []
            }
        },
        {
            "name": "DeallocBlock",
            "requires_arc": true,
            "source_files": "JJException/Source/DeallocBlock/*.{h,m}"
        }
    ]
}

Pin It on Pinterest

Share This