首次提交

This commit is contained in:
启星
2025-08-08 11:05:33 +08:00
parent 1b3bb91b4a
commit adc1a2a25d
8803 changed files with 708874 additions and 0 deletions

View File

@@ -0,0 +1,116 @@
//
// AvoidCrash.h
// https://github.com/chenfanfang/AvoidCrash
//
// Created by mac on 16/9/21.
// Copyright © 2016年 chenfanfang. All rights reserved.
//
//===================================================
// 使用方法和注意事项:
// https://www.jianshu.com/p/2b90aa96c0a0
//===================================================
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
//category
#import "NSObject+AvoidCrash.h"
#import "NSArray+AvoidCrash.h"
#import "NSMutableArray+AvoidCrash.h"
#import "NSDictionary+AvoidCrash.h"
#import "NSMutableDictionary+AvoidCrash.h"
#import "NSString+AvoidCrash.h"
#import "NSMutableString+AvoidCrash.h"
#import "NSAttributedString+AvoidCrash.h"
#import "NSMutableAttributedString+AvoidCrash.h"
//define
#import "AvoidCrashStubProxy.h"
@interface AvoidCrash : NSObject
//===================================================
// 使用方法和注意事项:
// https://www.jianshu.com/p/2b90aa96c0a0
//===================================================
/**
*
* 开始生效.你可以在AppDelegate的didFinishLaunchingWithOptions方法中调用becomeEffective方法
* 【默认不开启 对”unrecognized selector sent to instance”防止崩溃的处理】
*
* 这是全局生效,若你只需要部分生效,你可以单个进行处理,比如:
* [NSArray avoidCrashExchangeMethod];
* [NSMutableArray avoidCrashExchangeMethod];
* .................
* .................
*
*/
+ (void)becomeEffective;
/**
* 相比于becomeEffective增加
* 对”unrecognized selector sent to instance”防止崩溃的处理
*
* 但是必须配合:
* setupClassStringsArr:和
* setupNoneSelClassStringPrefixsArr
* 这两个方法可以同时使用
*/
+ (void)makeAllEffective;
/**
* 初始化一个需要防止”unrecognized selector sent to instance”的崩溃的类名数组
* ⚠️不可将@"NSObject"加入classStrings数组中
* ⚠不可将UI前缀的字符串加入classStrings数组中
*/
+ (void)setupNoneSelClassStringsArr:(NSArray<NSString *> *)classStrings;
/**
* 初始化一个需要防止”unrecognized selector sent to instance”的崩溃的类名前缀的数组
* ⚠不可将UI前缀的字符串(包括@"UI")加入classStringPrefixs数组中
* ⚠不可将NS前缀的字符串(包括@"NS")加入classStringPrefixs数组中
*/
+ (void)setupNoneSelClassStringPrefixsArr:(NSArray<NSString *> *)classStringPrefixs;
//您可以忽略以下方法
+ (void)exchangeClassMethod:(Class)anClass method1Sel:(SEL)method1Sel method2Sel:(SEL)method2Sel;
+ (void)exchangeInstanceMethod:(Class)anClass method1Sel:(SEL)method1Sel method2Sel:(SEL)method2Sel;
+ (void)noteErrorWithException:(NSException *)exception defaultToDo:(NSString *)defaultToDo;
@end

View File

@@ -0,0 +1,219 @@
//
// AvoidCrash.m
// https://github.com/chenfanfang/AvoidCrash
//
// Created by mac on 16/9/21.
// Copyright © 2016 chenfanfang. All rights reserved.
//
#import "AvoidCrash.h"
#define key_errorName @"errorName"
#define key_errorReason @"errorReason"
#define key_errorPlace @"errorPlace"
#define key_defaultToDo @"defaultToDo"
#define key_callStackSymbols @"callStackSymbols"
#define key_exception @"exception"
@implementation AvoidCrash
+ (void)becomeEffective {
[self effectiveIfDealWithNoneSel:NO];
}
+ (void)makeAllEffective {
[self effectiveIfDealWithNoneSel:YES];
}
+ (void)effectiveIfDealWithNoneSel:(BOOL)dealWithNoneSel {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[NSObject avoidCrashExchangeMethodIfDealWithNoneSel:dealWithNoneSel];
[NSArray avoidCrashExchangeMethod];
[NSMutableArray avoidCrashExchangeMethod];
[NSDictionary avoidCrashExchangeMethod];
[NSMutableDictionary avoidCrashExchangeMethod];
[NSString avoidCrashExchangeMethod];
[NSMutableString avoidCrashExchangeMethod];
[NSAttributedString avoidCrashExchangeMethod];
[NSMutableAttributedString avoidCrashExchangeMethod];
});
}
+ (void)setupNoneSelClassStringsArr:(NSArray<NSString *> *)classStrings {
[NSObject setupNoneSelClassStringsArr:classStrings];
}
/**
* unrecognized selector sent to instance
*/
+ (void)setupNoneSelClassStringPrefixsArr:(NSArray<NSString *> *)classStringPrefixs {
[NSObject setupNoneSelClassStringPrefixsArr:classStringPrefixs];
}
/**
*
*
* @param anClass
* @param method1Sel 1
* @param method2Sel 2
*/
+ (void)exchangeClassMethod:(Class)anClass method1Sel:(SEL)method1Sel method2Sel:(SEL)method2Sel {
Method method1 = class_getClassMethod(anClass, method1Sel);
Method method2 = class_getClassMethod(anClass, method2Sel);
method_exchangeImplementations(method1, method2);
}
/**
*
*
* @param anClass
* @param method1Sel 1()
* @param method2Sel 2()
*/
+ (void)exchangeInstanceMethod:(Class)anClass method1Sel:(SEL)method1Sel method2Sel:(SEL)method2Sel {
Method originalMethod = class_getInstanceMethod(anClass, method1Sel);
Method swizzledMethod = class_getInstanceMethod(anClass, method2Sel);
BOOL didAddMethod =
class_addMethod(anClass,
method1Sel,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod));
if (didAddMethod) {
class_replaceMethod(anClass,
method2Sel,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
}
else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
}
/**
* <>
*
* @param callStackSymbols
*
* @return
*/
+ (NSString *)getMainCallStackSymbolMessageWithCallStackSymbols:(NSArray<NSString *> *)callStackSymbols {
//mainCallStackSymbolMsg +[ ] -[ ]
__block NSString *mainCallStackSymbolMsg = nil;
// +[ ] -[ ]
NSString *regularExpStr = @"[-\\+]\\[.+\\]";
NSRegularExpression *regularExp = [[NSRegularExpression alloc] initWithPattern:regularExpStr options:NSRegularExpressionCaseInsensitive error:nil];
for (int index = 2; index < callStackSymbols.count; index++) {
NSString *callStackSymbol = callStackSymbols[index];
[regularExp enumerateMatchesInString:callStackSymbol options:NSMatchingReportProgress range:NSMakeRange(0, callStackSymbol.length) usingBlock:^(NSTextCheckingResult * _Nullable result, NSMatchingFlags flags, BOOL * _Nonnull stop) {
if (result) {
NSString* tempCallStackSymbolMsg = [callStackSymbol substringWithRange:result.range];
//get className
NSString *className = [tempCallStackSymbolMsg componentsSeparatedByString:@" "].firstObject;
className = [className componentsSeparatedByString:@"["].lastObject;
NSBundle *bundle = [NSBundle bundleForClass:NSClassFromString(className)];
//filter category and system class
if (![className hasSuffix:@")"] && bundle == [NSBundle mainBundle]) {
mainCallStackSymbolMsg = tempCallStackSymbolMsg;
}
*stop = YES;
}
}];
if (mainCallStackSymbolMsg.length) {
break;
}
}
return mainCallStackSymbolMsg;
}
/**
* ()
*
* @param exception
* @param defaultToDo
*/
+ (void)noteErrorWithException:(NSException *)exception defaultToDo:(NSString *)defaultToDo {
//
NSArray *callStackSymbolsArr = [NSThread callStackSymbols];
// -[ ] +[ ]
NSString *mainCallStackSymbolMsg = [AvoidCrash getMainCallStackSymbolMessageWithCallStackSymbols:callStackSymbolsArr];
if (mainCallStackSymbolMsg == nil) {
mainCallStackSymbolMsg = @"崩溃方法定位失败,请您查看函数调用栈来排查错误原因";
}
NSString *errorName = exception.name;
NSString *errorReason = exception.reason;
//errorReason -[__NSCFConstantString avoidCrashCharacterAtIndex:]: Range or index out of bounds
//avoidCrash
errorReason = [errorReason stringByReplacingOccurrencesOfString:@"avoidCrash" withString:@""];
NSString *errorPlace = [NSString stringWithFormat:@"Error Place:%@",mainCallStackSymbolMsg];
NSString *logErrorMessage = [NSString stringWithFormat:@"\n\n%@\n\n%@\n%@\n%@\n%@",AvoidCrashSeparatorWithFlag, errorName, errorReason, errorPlace, defaultToDo];
logErrorMessage = [NSString stringWithFormat:@"%@\n\n%@\n\n",logErrorMessage,AvoidCrashSeparator];
AvoidCrashLog(@"%@",logErrorMessage);
//cocoapods
logErrorMessage = logErrorMessage;
NSDictionary *errorInfoDic = @{
key_errorName : errorName,
key_errorReason : errorReason,
key_errorPlace : errorPlace,
key_defaultToDo : defaultToDo,
key_exception : exception,
key_callStackSymbols : callStackSymbolsArr
};
//
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:AvoidCrashNotification object:nil userInfo:errorInfoDic];
});
}
@end

View File

@@ -0,0 +1,17 @@
//
// AvoidCrashProtocol.h
// https://github.com/chenfanfang/AvoidCrash
//
// Created by chenfanfang on 2017/7/22.
// Copyright © 2017年 chenfanfang. All rights reserved.
//
#import <UIKit/UIKit.h>
@protocol AvoidCrashProtocol <NSObject>
@required
+ (void)avoidCrashExchangeMethod;
@end

View File

@@ -0,0 +1,37 @@
//
// AvoidCrashStubProxy.h
// https://github.com/chenfanfang/AvoidCrash
//
// Created by chenfanfang on 2017/7/25.
// Copyright © 2017年 chenfanfang. All rights reserved.
//
#import <Foundation/Foundation.h>
#define AvoidCrashNotification @"AvoidCrashNotification"
#define AvoidCrashIsiOS(version) ([[UIDevice currentDevice].systemVersion floatValue] >= version)
//user can ignore below define
#define AvoidCrashDefaultReturnNil @"AvoidCrash default is to return nil to avoid crash."
#define AvoidCrashDefaultIgnore @"AvoidCrash default is to ignore this operation to avoid crash."
#define AvoidCrashSeparator @"================================================================"
#define AvoidCrashSeparatorWithFlag @"========================AvoidCrash Log=========================="
#ifdef DEBUG
#define AvoidCrashLog(...) NSLog(@"%@",[NSString stringWithFormat:__VA_ARGS__])
#else
#define AvoidCrashLog(...)
#endif
@interface AvoidCrashStubProxy : NSObject
- (void)proxyMethod;
@end

View File

@@ -0,0 +1,18 @@
//
// AvoidCrashStubProxy.m
// https://github.com/chenfanfang/AvoidCrash
//
// Created by chenfanfang on 2017/7/25.
// Copyright © 2017 chenfanfang. All rights reserved.
//
#import "AvoidCrashStubProxy.h"
@implementation AvoidCrashStubProxy
- (void)proxyMethod {
}
@end

View File

@@ -0,0 +1,25 @@
//
// NSArray+AvoidCrash.h
// https://github.com/chenfanfang/AvoidCrash
//
// Created by mac on 16/9/21.
// Copyright © 2016年 chenfanfang. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "AvoidCrashProtocol.h"
@interface NSArray (AvoidCrash)<AvoidCrashProtocol>
@end
/**
* Can avoid crash method
*
* 1. NSArray的快速创建方式 NSArray *array = @[@"chenfanfang", @"AvoidCrash"]; //这种创建方式其实调用的是2中的方法
* 2. +(instancetype)arrayWithObjects:(const id _Nonnull __unsafe_unretained *)objects count:(NSUInteger)cnt
* 3. - (id)objectAtIndex:(NSUInteger)index
* 4. - (void)getObjects:(__unsafe_unretained id _Nonnull *)objects range:(NSRange)range
*/

View File

@@ -0,0 +1,258 @@
//
// NSArray+AvoidCrash.m
// https://github.com/chenfanfang/AvoidCrash
//
// Created by mac on 16/9/21.
// Copyright © 2016 chenfanfang. All rights reserved.
//
#import "NSArray+AvoidCrash.h"
#import "AvoidCrash.h"
@implementation NSArray (AvoidCrash)
+ (void)avoidCrashExchangeMethod {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//=================
// class method
//=================
//instance array method exchange
[AvoidCrash exchangeClassMethod:[self class] method1Sel:@selector(arrayWithObjects:count:) method2Sel:@selector(AvoidCrashArrayWithObjects:count:)];
//====================
// instance method
//====================
Class __NSArray = NSClassFromString(@"NSArray");
Class __NSArrayI = NSClassFromString(@"__NSArrayI");
Class __NSSingleObjectArrayI = NSClassFromString(@"__NSSingleObjectArrayI");
Class __NSArray0 = NSClassFromString(@"__NSArray0");
//objectsAtIndexes:
[AvoidCrash exchangeInstanceMethod:__NSArray method1Sel:@selector(objectsAtIndexes:) method2Sel:@selector(avoidCrashObjectsAtIndexes:)];
//objectAtIndex:
[AvoidCrash exchangeInstanceMethod:__NSArrayI method1Sel:@selector(objectAtIndex:) method2Sel:@selector(__NSArrayIAvoidCrashObjectAtIndex:)];
[AvoidCrash exchangeInstanceMethod:__NSSingleObjectArrayI method1Sel:@selector(objectAtIndex:) method2Sel:@selector(__NSSingleObjectArrayIAvoidCrashObjectAtIndex:)];
[AvoidCrash exchangeInstanceMethod:__NSArray0 method1Sel:@selector(objectAtIndex:) method2Sel:@selector(__NSArray0AvoidCrashObjectAtIndex:)];
//objectAtIndexedSubscript:
if (AvoidCrashIsiOS(11.0)) {
[AvoidCrash exchangeInstanceMethod:__NSArrayI method1Sel:@selector(objectAtIndexedSubscript:) method2Sel:@selector(__NSArrayIAvoidCrashObjectAtIndexedSubscript:)];
}
//getObjects:range:
[AvoidCrash exchangeInstanceMethod:__NSArray method1Sel:@selector(getObjects:range:) method2Sel:@selector(NSArrayAvoidCrashGetObjects:range:)];
[AvoidCrash exchangeInstanceMethod:__NSSingleObjectArrayI method1Sel:@selector(getObjects:range:) method2Sel:@selector(__NSSingleObjectArrayIAvoidCrashGetObjects:range:)];
[AvoidCrash exchangeInstanceMethod:__NSArrayI method1Sel:@selector(getObjects:range:) method2Sel:@selector(__NSArrayIAvoidCrashGetObjects:range:)];
});
}
//=================================================================
// instance array
//=================================================================
#pragma mark - instance array
+ (instancetype)AvoidCrashArrayWithObjects:(const id _Nonnull __unsafe_unretained *)objects count:(NSUInteger)cnt {
id instance = nil;
@try {
instance = [self AvoidCrashArrayWithObjects:objects count:cnt];
}
@catch (NSException *exception) {
NSString *defaultToDo = @"AvoidCrash default is to remove nil object and instance a array.";
[AvoidCrash noteErrorWithException:exception defaultToDo:defaultToDo];
//nil,
NSInteger newObjsIndex = 0;
id _Nonnull __unsafe_unretained newObjects[cnt];
for (int i = 0; i < cnt; i++) {
if (objects[i] != nil) {
newObjects[newObjsIndex] = objects[i];
newObjsIndex++;
}
}
instance = [self AvoidCrashArrayWithObjects:newObjects count:newObjsIndex];
}
@finally {
return instance;
}
}
//=================================================================
// objectAtIndexedSubscript:
//=================================================================
#pragma mark - objectAtIndexedSubscript:
- (id)__NSArrayIAvoidCrashObjectAtIndexedSubscript:(NSUInteger)idx {
id object = nil;
@try {
object = [self __NSArrayIAvoidCrashObjectAtIndexedSubscript:idx];
}
@catch (NSException *exception) {
NSString *defaultToDo = AvoidCrashDefaultReturnNil;
[AvoidCrash noteErrorWithException:exception defaultToDo:defaultToDo];
}
@finally {
return object;
}
}
//=================================================================
// objectsAtIndexes:
//=================================================================
#pragma mark - objectsAtIndexes:
- (NSArray *)avoidCrashObjectsAtIndexes:(NSIndexSet *)indexes {
NSArray *returnArray = nil;
@try {
returnArray = [self avoidCrashObjectsAtIndexes:indexes];
} @catch (NSException *exception) {
NSString *defaultToDo = AvoidCrashDefaultReturnNil;
[AvoidCrash noteErrorWithException:exception defaultToDo:defaultToDo];
} @finally {
return returnArray;
}
}
//=================================================================
// objectAtIndex:
//=================================================================
#pragma mark - objectAtIndex:
//__NSArrayI objectAtIndex:
- (id)__NSArrayIAvoidCrashObjectAtIndex:(NSUInteger)index {
id object = nil;
@try {
object = [self __NSArrayIAvoidCrashObjectAtIndex:index];
}
@catch (NSException *exception) {
NSString *defaultToDo = AvoidCrashDefaultReturnNil;
[AvoidCrash noteErrorWithException:exception defaultToDo:defaultToDo];
}
@finally {
return object;
}
}
//__NSSingleObjectArrayI objectAtIndex:
- (id)__NSSingleObjectArrayIAvoidCrashObjectAtIndex:(NSUInteger)index {
id object = nil;
@try {
object = [self __NSSingleObjectArrayIAvoidCrashObjectAtIndex:index];
}
@catch (NSException *exception) {
NSString *defaultToDo = AvoidCrashDefaultReturnNil;
[AvoidCrash noteErrorWithException:exception defaultToDo:defaultToDo];
}
@finally {
return object;
}
}
//__NSArray0 objectAtIndex:
- (id)__NSArray0AvoidCrashObjectAtIndex:(NSUInteger)index {
id object = nil;
@try {
object = [self __NSArray0AvoidCrashObjectAtIndex:index];
}
@catch (NSException *exception) {
NSString *defaultToDo = AvoidCrashDefaultReturnNil;
[AvoidCrash noteErrorWithException:exception defaultToDo:defaultToDo];
}
@finally {
return object;
}
}
//=================================================================
// getObjects:range:
//=================================================================
#pragma mark - getObjects:range:
//NSArray getObjects:range:
- (void)NSArrayAvoidCrashGetObjects:(__unsafe_unretained id _Nonnull *)objects range:(NSRange)range {
@try {
[self NSArrayAvoidCrashGetObjects:objects range:range];
} @catch (NSException *exception) {
NSString *defaultToDo = AvoidCrashDefaultIgnore;
[AvoidCrash noteErrorWithException:exception defaultToDo:defaultToDo];
} @finally {
}
}
//__NSSingleObjectArrayI getObjects:range:
- (void)__NSSingleObjectArrayIAvoidCrashGetObjects:(__unsafe_unretained id _Nonnull *)objects range:(NSRange)range {
@try {
[self __NSSingleObjectArrayIAvoidCrashGetObjects:objects range:range];
} @catch (NSException *exception) {
NSString *defaultToDo = AvoidCrashDefaultIgnore;
[AvoidCrash noteErrorWithException:exception defaultToDo:defaultToDo];
} @finally {
}
}
//__NSArrayI getObjects:range:
- (void)__NSArrayIAvoidCrashGetObjects:(__unsafe_unretained id _Nonnull *)objects range:(NSRange)range {
@try {
[self __NSArrayIAvoidCrashGetObjects:objects range:range];
} @catch (NSException *exception) {
NSString *defaultToDo = AvoidCrashDefaultIgnore;
[AvoidCrash noteErrorWithException:exception defaultToDo:defaultToDo];
} @finally {
}
}
@end

View File

@@ -0,0 +1,25 @@
//
// NSAttributedString+AvoidCrash.h
// https://github.com/chenfanfang/AvoidCrash
//
// Created by mac on 16/10/15.
// Copyright © 2016年 chenfanfang. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "AvoidCrashProtocol.h"
@interface NSAttributedString (AvoidCrash)<AvoidCrashProtocol>
@end
/**
* Can avoid crash method
*
* 1.- (instancetype)initWithString:(NSString *)str
* 2.- (instancetype)initWithAttributedString:(NSAttributedString *)attrStr
* 3.- (instancetype)initWithString:(NSString *)str attributes:(NSDictionary<NSString *,id> *)attrs
*
*
*/

View File

@@ -0,0 +1,96 @@
//
// NSAttributedString+AvoidCrash.m
// https://github.com/chenfanfang/AvoidCrash
//
// Created by mac on 16/10/15.
// Copyright © 2016 chenfanfang. All rights reserved.
//
#import "NSAttributedString+AvoidCrash.h"
#import "AvoidCrash.h"
@implementation NSAttributedString (AvoidCrash)
+ (void)avoidCrashExchangeMethod {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class NSConcreteAttributedString = NSClassFromString(@"NSConcreteAttributedString");
//initWithString:
[AvoidCrash exchangeInstanceMethod:NSConcreteAttributedString method1Sel:@selector(initWithString:) method2Sel:@selector(avoidCrashInitWithString:)];
//initWithAttributedString
[AvoidCrash exchangeInstanceMethod:NSConcreteAttributedString method1Sel:@selector(initWithAttributedString:) method2Sel:@selector(avoidCrashInitWithAttributedString:)];
//initWithString:attributes:
[AvoidCrash exchangeInstanceMethod:NSConcreteAttributedString method1Sel:@selector(initWithString:attributes:) method2Sel:@selector(avoidCrashInitWithString:attributes:)];
});
}
//=================================================================
// initWithString:
//=================================================================
#pragma mark - initWithString:
- (instancetype)avoidCrashInitWithString:(NSString *)str {
id object = nil;
@try {
object = [self avoidCrashInitWithString:str];
}
@catch (NSException *exception) {
NSString *defaultToDo = AvoidCrashDefaultReturnNil;
[AvoidCrash noteErrorWithException:exception defaultToDo:defaultToDo];
}
@finally {
return object;
}
}
//=================================================================
// initWithAttributedString
//=================================================================
#pragma mark - initWithAttributedString
- (instancetype)avoidCrashInitWithAttributedString:(NSAttributedString *)attrStr {
id object = nil;
@try {
object = [self avoidCrashInitWithAttributedString:attrStr];
}
@catch (NSException *exception) {
NSString *defaultToDo = AvoidCrashDefaultReturnNil;
[AvoidCrash noteErrorWithException:exception defaultToDo:defaultToDo];
}
@finally {
return object;
}
}
//=================================================================
// initWithString:attributes:
//=================================================================
#pragma mark - initWithString:attributes:
- (instancetype)avoidCrashInitWithString:(NSString *)str attributes:(NSDictionary<NSString *,id> *)attrs {
id object = nil;
@try {
object = [self avoidCrashInitWithString:str attributes:attrs];
}
@catch (NSException *exception) {
NSString *defaultToDo = AvoidCrashDefaultReturnNil;
[AvoidCrash noteErrorWithException:exception defaultToDo:defaultToDo];
}
@finally {
return object;
}
}
@end

View File

@@ -0,0 +1,24 @@
//
// NSDictionary+AvoidCrash.h
// https://github.com/chenfanfang/AvoidCrash
//
// Created by mac on 16/9/21.
// Copyright © 2016年 chenfanfang. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "AvoidCrashProtocol.h"
@interface NSDictionary (AvoidCrash)<AvoidCrashProtocol>
@end
/**
* Can avoid crash method
*
* 1. NSDictionary的快速创建方式 NSDictionary *dict = @{@"frameWork" : @"AvoidCrash"}; //这种创建方式其实调用的是2中的方法
* 2. +(instancetype)dictionaryWithObjects:(const id _Nonnull __unsafe_unretained *)objects forKeys:(const id<NSCopying> _Nonnull __unsafe_unretained *)keys count:(NSUInteger)cnt
*
*/

View File

@@ -0,0 +1,56 @@
//
// NSDictionary+AvoidCrash.m
// https://github.com/chenfanfang/AvoidCrash
//
// Created by mac on 16/9/21.
// Copyright © 2016 chenfanfang. All rights reserved.
//
#import "NSDictionary+AvoidCrash.h"
#import "AvoidCrash.h"
@implementation NSDictionary (AvoidCrash)
+ (void)avoidCrashExchangeMethod {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[AvoidCrash exchangeClassMethod:self method1Sel:@selector(dictionaryWithObjects:forKeys:count:) method2Sel:@selector(avoidCrashDictionaryWithObjects:forKeys:count:)];
});
}
+ (instancetype)avoidCrashDictionaryWithObjects:(const id _Nonnull __unsafe_unretained *)objects forKeys:(const id<NSCopying> _Nonnull __unsafe_unretained *)keys count:(NSUInteger)cnt {
id instance = nil;
@try {
instance = [self avoidCrashDictionaryWithObjects:objects forKeys:keys count:cnt];
}
@catch (NSException *exception) {
NSString *defaultToDo = @"AvoidCrash default is to remove nil key-values and instance a dictionary.";
[AvoidCrash noteErrorWithException:exception defaultToDo:defaultToDo];
//
NSUInteger index = 0;
id _Nonnull __unsafe_unretained newObjects[cnt];
id _Nonnull __unsafe_unretained newkeys[cnt];
for (int i = 0; i < cnt; i++) {
if (objects[i] && keys[i]) {
newObjects[index] = objects[i];
newkeys[index] = keys[i];
index++;
}
}
instance = [self avoidCrashDictionaryWithObjects:newObjects forKeys:newkeys count:index];
}
@finally {
return instance;
}
}
@end

View File

@@ -0,0 +1,26 @@
//
// NSMutableArray+AvoidCrash.h
// https://github.com/chenfanfang/AvoidCrash
//
// Created by mac on 16/9/21.
// Copyright © 2016年 chenfanfang. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "AvoidCrashProtocol.h"
@interface NSMutableArray (AvoidCrash)<AvoidCrashProtocol>
@end
/**
* Can avoid crash method
*
* 1. - (id)objectAtIndex:(NSUInteger)index
* 2. - (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx
* 3. - (void)removeObjectAtIndex:(NSUInteger)index
* 4. - (void)insertObject:(id)anObject atIndex:(NSUInteger)index
* 5. - (void)getObjects:(__unsafe_unretained id _Nonnull *)objects range:(NSRange)range
*/

View File

@@ -0,0 +1,169 @@
//
// NSMutableArray+AvoidCrash.m
// https://github.com/chenfanfang/AvoidCrash
//
// Created by mac on 16/9/21.
// Copyright © 2016 chenfanfang. All rights reserved.
//
#import "NSMutableArray+AvoidCrash.h"
#import "AvoidCrash.h"
@implementation NSMutableArray (AvoidCrash)
+ (void)avoidCrashExchangeMethod {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class arrayMClass = NSClassFromString(@"__NSArrayM");
//objectAtIndex:
[AvoidCrash exchangeInstanceMethod:arrayMClass method1Sel:@selector(objectAtIndex:) method2Sel:@selector(avoidCrashObjectAtIndex:)];
//objectAtIndexedSubscript
if (AvoidCrashIsiOS(11.0)) {
[AvoidCrash exchangeInstanceMethod:arrayMClass method1Sel:@selector(objectAtIndexedSubscript:) method2Sel:@selector(avoidCrashObjectAtIndexedSubscript:)];
}
//setObject:atIndexedSubscript:
[AvoidCrash exchangeInstanceMethod:arrayMClass method1Sel:@selector(setObject:atIndexedSubscript:) method2Sel:@selector(avoidCrashSetObject:atIndexedSubscript:)];
//removeObjectAtIndex:
[AvoidCrash exchangeInstanceMethod:arrayMClass method1Sel:@selector(removeObjectAtIndex:) method2Sel:@selector(avoidCrashRemoveObjectAtIndex:)];
//insertObject:atIndex:
[AvoidCrash exchangeInstanceMethod:arrayMClass method1Sel:@selector(insertObject:atIndex:) method2Sel:@selector(avoidCrashInsertObject:atIndex:)];
//getObjects:range:
[AvoidCrash exchangeInstanceMethod:arrayMClass method1Sel:@selector(getObjects:range:) method2Sel:@selector(avoidCrashGetObjects:range:)];
});
}
//=================================================================
// array set object at index
//=================================================================
#pragma mark - get object from array
- (void)avoidCrashSetObject:(id)obj atIndexedSubscript:(NSUInteger)idx {
@try {
[self avoidCrashSetObject:obj atIndexedSubscript:idx];
}
@catch (NSException *exception) {
[AvoidCrash noteErrorWithException:exception defaultToDo:AvoidCrashDefaultIgnore];
}
@finally {
}
}
//=================================================================
// removeObjectAtIndex:
//=================================================================
#pragma mark - removeObjectAtIndex:
- (void)avoidCrashRemoveObjectAtIndex:(NSUInteger)index {
@try {
[self avoidCrashRemoveObjectAtIndex:index];
}
@catch (NSException *exception) {
[AvoidCrash noteErrorWithException:exception defaultToDo:AvoidCrashDefaultIgnore];
}
@finally {
}
}
//=================================================================
// insertObject:atIndex:
//=================================================================
#pragma mark - set
- (void)avoidCrashInsertObject:(id)anObject atIndex:(NSUInteger)index {
@try {
[self avoidCrashInsertObject:anObject atIndex:index];
}
@catch (NSException *exception) {
[AvoidCrash noteErrorWithException:exception defaultToDo:AvoidCrashDefaultIgnore];
}
@finally {
}
}
//=================================================================
// objectAtIndex:
//=================================================================
#pragma mark - objectAtIndex:
- (id)avoidCrashObjectAtIndex:(NSUInteger)index {
id object = nil;
@try {
object = [self avoidCrashObjectAtIndex:index];
}
@catch (NSException *exception) {
NSString *defaultToDo = AvoidCrashDefaultReturnNil;
[AvoidCrash noteErrorWithException:exception defaultToDo:defaultToDo];
}
@finally {
return object;
}
}
//=================================================================
// objectAtIndexedSubscript:
//=================================================================
#pragma mark - objectAtIndexedSubscript:
- (id)avoidCrashObjectAtIndexedSubscript:(NSUInteger)idx {
id object = nil;
@try {
object = [self avoidCrashObjectAtIndexedSubscript:idx];
}
@catch (NSException *exception) {
NSString *defaultToDo = AvoidCrashDefaultReturnNil;
[AvoidCrash noteErrorWithException:exception defaultToDo:defaultToDo];
}
@finally {
return object;
}
}
//=================================================================
// getObjects:range:
//=================================================================
#pragma mark - getObjects:range:
- (void)avoidCrashGetObjects:(__unsafe_unretained id _Nonnull *)objects range:(NSRange)range {
@try {
[self avoidCrashGetObjects:objects range:range];
} @catch (NSException *exception) {
NSString *defaultToDo = AvoidCrashDefaultIgnore;
[AvoidCrash noteErrorWithException:exception defaultToDo:defaultToDo];
} @finally {
}
}
@end

View File

@@ -0,0 +1,23 @@
//
// NSMutableAttributedString+AvoidCrash.h
// https://github.com/chenfanfang/AvoidCrash
//
// Created by mac on 16/10/15.
// Copyright © 2016年 chenfanfang. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "AvoidCrashProtocol.h"
@interface NSMutableAttributedString (AvoidCrash)<AvoidCrashProtocol>
@end
/**
* Can avoid crash method
*
* 1.- (instancetype)initWithString:(NSString *)str
* 2.- (instancetype)initWithString:(NSString *)str attributes:(NSDictionary<NSString *,id> *)attrs
*/

View File

@@ -0,0 +1,74 @@
//
// NSMutableAttributedString+AvoidCrash.m
// https://github.com/chenfanfang/AvoidCrash
//
// Created by mac on 16/10/15.
// Copyright © 2016 chenfanfang. All rights reserved.
//
#import "NSMutableAttributedString+AvoidCrash.h"
#import "AvoidCrash.h"
@implementation NSMutableAttributedString (AvoidCrash)
+ (void)avoidCrashExchangeMethod {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class NSConcreteMutableAttributedString = NSClassFromString(@"NSConcreteMutableAttributedString");
//initWithString:
[AvoidCrash exchangeInstanceMethod:NSConcreteMutableAttributedString method1Sel:@selector(initWithString:) method2Sel:@selector(avoidCrashInitWithString:)];
//initWithString:attributes:
[AvoidCrash exchangeInstanceMethod:NSConcreteMutableAttributedString method1Sel:@selector(initWithString:attributes:) method2Sel:@selector(avoidCrashInitWithString:attributes:)];
});
}
//=================================================================
// initWithString:
//=================================================================
#pragma mark - initWithString:
- (instancetype)avoidCrashInitWithString:(NSString *)str {
id object = nil;
@try {
object = [self avoidCrashInitWithString:str];
}
@catch (NSException *exception) {
NSString *defaultToDo = AvoidCrashDefaultReturnNil;
[AvoidCrash noteErrorWithException:exception defaultToDo:defaultToDo];
}
@finally {
return object;
}
}
//=================================================================
// initWithString:attributes:
//=================================================================
#pragma mark - initWithString:attributes:
- (instancetype)avoidCrashInitWithString:(NSString *)str attributes:(NSDictionary<NSString *,id> *)attrs {
id object = nil;
@try {
object = [self avoidCrashInitWithString:str attributes:attrs];
}
@catch (NSException *exception) {
NSString *defaultToDo = AvoidCrashDefaultReturnNil;
[AvoidCrash noteErrorWithException:exception defaultToDo:defaultToDo];
}
@finally {
return object;
}
}
@end

View File

@@ -0,0 +1,24 @@
//
// NSMutableDictionary+AvoidCrash.h
// https://github.com/chenfanfang/AvoidCrash
//
// Created by mac on 16/9/22.
// Copyright © 2016年 chenfanfang. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "AvoidCrashProtocol.h"
@interface NSMutableDictionary (AvoidCrash)<AvoidCrashProtocol>
@end
/**
* Can avoid crash method
*
* 1. - (void)setObject:(id)anObject forKey:(id<NSCopying>)aKey
* 2. - (void)removeObjectForKey:(id)aKey
*
*/

View File

@@ -0,0 +1,95 @@
//
// NSMutableDictionary+AvoidCrash.m
// https://github.com/chenfanfang/AvoidCrash
//
// Created by mac on 16/9/22.
// Copyright © 2016 chenfanfang. All rights reserved.
//
#import "NSMutableDictionary+AvoidCrash.h"
#import "AvoidCrash.h"
@implementation NSMutableDictionary (AvoidCrash)
+ (void)avoidCrashExchangeMethod {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class dictionaryM = NSClassFromString(@"__NSDictionaryM");
//setObject:forKey:
[AvoidCrash exchangeInstanceMethod:dictionaryM method1Sel:@selector(setObject:forKey:) method2Sel:@selector(avoidCrashSetObject:forKey:)];
//setObject:forKeyedSubscript:
if (AvoidCrashIsiOS(11.0)) {
[AvoidCrash exchangeInstanceMethod:dictionaryM method1Sel:@selector(setObject:forKeyedSubscript:) method2Sel:@selector(avoidCrashSetObject:forKeyedSubscript:)];
}
//removeObjectForKey:
Method removeObjectForKey = class_getInstanceMethod(dictionaryM, @selector(removeObjectForKey:));
Method avoidCrashRemoveObjectForKey = class_getInstanceMethod(dictionaryM, @selector(avoidCrashRemoveObjectForKey:));
method_exchangeImplementations(removeObjectForKey, avoidCrashRemoveObjectForKey);
});
}
//=================================================================
// setObject:forKey:
//=================================================================
#pragma mark - setObject:forKey:
- (void)avoidCrashSetObject:(id)anObject forKey:(id<NSCopying>)aKey {
@try {
[self avoidCrashSetObject:anObject forKey:aKey];
}
@catch (NSException *exception) {
[AvoidCrash noteErrorWithException:exception defaultToDo:AvoidCrashDefaultIgnore];
}
@finally {
}
}
//=================================================================
// setObject:forKeyedSubscript:
//=================================================================
#pragma mark - setObject:forKeyedSubscript:
- (void)avoidCrashSetObject:(id)obj forKeyedSubscript:(id<NSCopying>)key {
@try {
[self avoidCrashSetObject:obj forKeyedSubscript:key];
}
@catch (NSException *exception) {
[AvoidCrash noteErrorWithException:exception defaultToDo:AvoidCrashDefaultIgnore];
}
@finally {
}
}
//=================================================================
// removeObjectForKey:
//=================================================================
#pragma mark - removeObjectForKey:
- (void)avoidCrashRemoveObjectForKey:(id)aKey {
@try {
[self avoidCrashRemoveObjectForKey:aKey];
}
@catch (NSException *exception) {
[AvoidCrash noteErrorWithException:exception defaultToDo:AvoidCrashDefaultIgnore];
}
@finally {
}
}
@end

View File

@@ -0,0 +1,29 @@
//
// NSMutableString+AvoidCrash.h
// https://github.com/chenfanfang/AvoidCrash
//
// Created by mac on 16/10/6.
// Copyright © 2016年 chenfanfang. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "AvoidCrashProtocol.h"
@interface NSMutableString (AvoidCrash)<AvoidCrashProtocol>
@end
/**
* Can avoid crash method
*
* 1. 由于NSMutableString是继承于NSString,所以这里和NSString有些同样的方法就不重复写了
* 2. - (void)replaceCharactersInRange:(NSRange)range withString:(NSString *)aString
* 3. - (void)insertString:(NSString *)aString atIndex:(NSUInteger)loc
* 4. - (void)deleteCharactersInRange:(NSRange)range
*
*/

View File

@@ -0,0 +1,97 @@
//
// NSMutableString+AvoidCrash.m
// https://github.com/chenfanfang/AvoidCrash
//
// Created by mac on 16/10/6.
// Copyright © 2016 chenfanfang. All rights reserved.
//
#import "NSMutableString+AvoidCrash.h"
#import "AvoidCrash.h"
@implementation NSMutableString (AvoidCrash)
+ (void)avoidCrashExchangeMethod {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class stringClass = NSClassFromString(@"__NSCFString");
//replaceCharactersInRange
[AvoidCrash exchangeInstanceMethod:stringClass method1Sel:@selector(replaceCharactersInRange:withString:) method2Sel:@selector(avoidCrashReplaceCharactersInRange:withString:)];
//insertString:atIndex:
[AvoidCrash exchangeInstanceMethod:stringClass method1Sel:@selector(insertString:atIndex:) method2Sel:@selector(avoidCrashInsertString:atIndex:)];
//deleteCharactersInRange
[AvoidCrash exchangeInstanceMethod:stringClass method1Sel:@selector(deleteCharactersInRange:) method2Sel:@selector(avoidCrashDeleteCharactersInRange:)];
});
}
//=================================================================
// replaceCharactersInRange
//=================================================================
#pragma mark - replaceCharactersInRange
- (void)avoidCrashReplaceCharactersInRange:(NSRange)range withString:(NSString *)aString {
@try {
[self avoidCrashReplaceCharactersInRange:range withString:aString];
}
@catch (NSException *exception) {
NSString *defaultToDo = AvoidCrashDefaultIgnore;
[AvoidCrash noteErrorWithException:exception defaultToDo:defaultToDo];
}
@finally {
}
}
//=================================================================
// insertString:atIndex:
//=================================================================
#pragma mark - insertString:atIndex:
- (void)avoidCrashInsertString:(NSString *)aString atIndex:(NSUInteger)loc {
@try {
[self avoidCrashInsertString:aString atIndex:loc];
}
@catch (NSException *exception) {
NSString *defaultToDo = AvoidCrashDefaultIgnore;
[AvoidCrash noteErrorWithException:exception defaultToDo:defaultToDo];
}
@finally {
}
}
//=================================================================
// deleteCharactersInRange
//=================================================================
#pragma mark - deleteCharactersInRange
- (void)avoidCrashDeleteCharactersInRange:(NSRange)range {
@try {
[self avoidCrashDeleteCharactersInRange:range];
}
@catch (NSException *exception) {
NSString *defaultToDo = AvoidCrashDefaultIgnore;
[AvoidCrash noteErrorWithException:exception defaultToDo:defaultToDo];
}
@finally {
}
}
@end

View File

@@ -0,0 +1,34 @@
//
// NSObject+AvoidCrash.h
// https://github.com/chenfanfang/AvoidCrash
//
// Created by mac on 16/10/11.
// Copyright © 2016年 chenfanfang. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSObject (AvoidCrash)
/**
* ifDealWithNoneSel : 是否开启"unrecognized selector sent to instance"异常的捕获
*/
+ (void)avoidCrashExchangeMethodIfDealWithNoneSel:(BOOL)ifDealWithNoneSel;
+ (void)setupNoneSelClassStringsArr:(NSArray<NSString *> *)classStrings;
+ (void)setupNoneSelClassStringPrefixsArr:(NSArray<NSString *> *)classStringPrefixs;
@end
/**
* Can avoid crash method
*
* 1.- (void)setValue:(id)value forKey:(NSString *)key
* 2.- (void)setValue:(id)value forKeyPath:(NSString *)keyPath
* 3.- (void)setValue:(id)value forUndefinedKey:(NSString *)key //这个方法一般用来重写,不会主动调用
* 4.- (void)setValuesForKeysWithDictionary:(NSDictionary<NSString *,id> *)keyedValues
* 5. unrecognized selector sent to instance
*/

View File

@@ -0,0 +1,221 @@
//
// NSObject+AvoidCrash.m
// https://github.com/chenfanfang/AvoidCrash
//
// Created by mac on 16/10/11.
// Copyright © 2016 chenfanfang. All rights reserved.
//
#import "NSObject+AvoidCrash.h"
#import "AvoidCrash.h"
#import "AvoidCrashStubProxy.h"
@implementation NSObject (AvoidCrash)
+ (void)avoidCrashExchangeMethodIfDealWithNoneSel:(BOOL)ifDealWithNoneSel {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//setValue:forKey:
[AvoidCrash exchangeInstanceMethod:[self class] method1Sel:@selector(setValue:forKey:) method2Sel:@selector(avoidCrashSetValue:forKey:)];
//setValue:forKeyPath:
[AvoidCrash exchangeInstanceMethod:[self class] method1Sel:@selector(setValue:forKeyPath:) method2Sel:@selector(avoidCrashSetValue:forKeyPath:)];
//setValue:forUndefinedKey:
[AvoidCrash exchangeInstanceMethod:[self class] method1Sel:@selector(setValue:forUndefinedKey:) method2Sel:@selector(avoidCrashSetValue:forUndefinedKey:)];
//setValuesForKeysWithDictionary:
[AvoidCrash exchangeInstanceMethod:[self class] method1Sel:@selector(setValuesForKeysWithDictionary:) method2Sel:@selector(avoidCrashSetValuesForKeysWithDictionary:)];
//unrecognized selector sent to instance
if (ifDealWithNoneSel) {
[AvoidCrash exchangeInstanceMethod:[self class] method1Sel:@selector(methodSignatureForSelector:) method2Sel:@selector(avoidCrashMethodSignatureForSelector:)];
[AvoidCrash exchangeInstanceMethod:[self class] method1Sel:@selector(forwardInvocation:) method2Sel:@selector(avoidCrashForwardInvocation:)];
}
});
}
//=================================================================
// unrecognized selector sent to instance
//=================================================================
#pragma mark - unrecognized selector sent to instance
static NSMutableArray *noneSelClassStrings;
static NSMutableArray *noneSelClassStringPrefixs;
+ (void)setupNoneSelClassStringsArr:(NSArray<NSString *> *)classStrings {
if (noneSelClassStrings) {
NSString *warningMsg = [NSString stringWithFormat:@"\n\n%@\n\n[AvoidCrash setupNoneSelClassStringsArr:];\n调用一此即可多次调用会自动忽略后面的调用\n\n%@\n\n",AvoidCrashSeparatorWithFlag,AvoidCrashSeparator];
AvoidCrashLog(@"%@",warningMsg);
}
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
noneSelClassStrings = [NSMutableArray array];
for (NSString *className in classStrings) {
if ([className hasPrefix:@"UI"] == NO &&
[className isEqualToString:NSStringFromClass([NSObject class])] == NO) {
[noneSelClassStrings addObject:className];
} else {
NSString *warningMsg = [NSString stringWithFormat:@"\n\n%@\n\n[AvoidCrash setupNoneSelClassStringsArr:];\n会忽略UI开头的类和NSObject类(请使用NSObject的子类)\n\n%@\n\n",AvoidCrashSeparatorWithFlag,AvoidCrashSeparator];
AvoidCrashLog(@"%@",warningMsg);
}
}
});
}
/**
* unrecognized selector sent to instance
*/
+ (void)setupNoneSelClassStringPrefixsArr:(NSArray<NSString *> *)classStringPrefixs {
if (noneSelClassStringPrefixs) {
NSString *warningMsg = [NSString stringWithFormat:@"\n\n%@\n\n[AvoidCrash setupNoneSelClassStringPrefixsArr:];\n调用一此即可多次调用会自动忽略后面的调用\n\n%@\n\n",AvoidCrashSeparatorWithFlag,AvoidCrashSeparator];
AvoidCrashLog(@"%@",warningMsg);
}
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
noneSelClassStringPrefixs = [NSMutableArray array];
for (NSString *classNamePrefix in classStringPrefixs) {
if ([classNamePrefix hasPrefix:@"UI"] == NO &&
[classNamePrefix hasPrefix:@"NS"] == NO) {
[noneSelClassStringPrefixs addObject:classNamePrefix];
} else {
NSString *warningMsg = [NSString stringWithFormat:@"\n\n%@\n\n[AvoidCrash setupNoneSelClassStringsArr:];\n会忽略UI开头的类和NS开头的类\n若需要对NS开头的类防止”unrecognized selector sent to instance”(比如NSArray),请使用setupNoneSelClassStringsArr:\n\n%@\n\n",AvoidCrashSeparatorWithFlag,AvoidCrashSeparator];
AvoidCrashLog(@"%@",warningMsg);
}
}
});
}
- (NSMethodSignature *)avoidCrashMethodSignatureForSelector:(SEL)aSelector {
NSMethodSignature *ms = [self avoidCrashMethodSignatureForSelector:aSelector];
BOOL flag = NO;
if (ms == nil) {
for (NSString *classStr in noneSelClassStrings) {
if ([self isKindOfClass:NSClassFromString(classStr)]) {
ms = [AvoidCrashStubProxy instanceMethodSignatureForSelector:@selector(proxyMethod)];
flag = YES;
break;
}
}
}
if (flag == NO) {
NSString *selfClass = NSStringFromClass([self class]);
for (NSString *classStrPrefix in noneSelClassStringPrefixs) {
if ([selfClass hasPrefix:classStrPrefix]) {
ms = [AvoidCrashStubProxy instanceMethodSignatureForSelector:@selector(proxyMethod)];
}
}
}
return ms;
}
- (void)avoidCrashForwardInvocation:(NSInvocation *)anInvocation {
@try {
[self avoidCrashForwardInvocation:anInvocation];
} @catch (NSException *exception) {
NSString *defaultToDo = AvoidCrashDefaultIgnore;
[AvoidCrash noteErrorWithException:exception defaultToDo:defaultToDo];
} @finally {
}
}
//=================================================================
// setValue:forKey:
//=================================================================
#pragma mark - setValue:forKey:
- (void)avoidCrashSetValue:(id)value forKey:(NSString *)key {
@try {
[self avoidCrashSetValue:value forKey:key];
}
@catch (NSException *exception) {
NSString *defaultToDo = AvoidCrashDefaultIgnore;
[AvoidCrash noteErrorWithException:exception defaultToDo:defaultToDo];
}
@finally {
}
}
//=================================================================
// setValue:forKeyPath:
//=================================================================
#pragma mark - setValue:forKeyPath:
- (void)avoidCrashSetValue:(id)value forKeyPath:(NSString *)keyPath {
@try {
[self avoidCrashSetValue:value forKeyPath:keyPath];
}
@catch (NSException *exception) {
NSString *defaultToDo = AvoidCrashDefaultIgnore;
[AvoidCrash noteErrorWithException:exception defaultToDo:defaultToDo];
}
@finally {
}
}
//=================================================================
// setValue:forUndefinedKey:
//=================================================================
#pragma mark - setValue:forUndefinedKey:
- (void)avoidCrashSetValue:(id)value forUndefinedKey:(NSString *)key {
@try {
[self avoidCrashSetValue:value forUndefinedKey:key];
}
@catch (NSException *exception) {
NSString *defaultToDo = AvoidCrashDefaultIgnore;
[AvoidCrash noteErrorWithException:exception defaultToDo:defaultToDo];
}
@finally {
}
}
//=================================================================
// setValuesForKeysWithDictionary:
//=================================================================
#pragma mark - setValuesForKeysWithDictionary:
- (void)avoidCrashSetValuesForKeysWithDictionary:(NSDictionary<NSString *,id> *)keyedValues {
@try {
[self avoidCrashSetValuesForKeysWithDictionary:keyedValues];
}
@catch (NSException *exception) {
NSString *defaultToDo = AvoidCrashDefaultIgnore;
[AvoidCrash noteErrorWithException:exception defaultToDo:defaultToDo];
}
@finally {
}
}
@end

View File

@@ -0,0 +1,29 @@
//
// NSString+AvoidCrash.h
// https://github.com/chenfanfang/AvoidCrash
//
// Created by mac on 16/10/5.
// Copyright © 2016年 chenfanfang. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "AvoidCrashProtocol.h"
@interface NSString (AvoidCrash)<AvoidCrashProtocol>
@end
/**
* Can avoid crash method
*
* 1. - (unichar)characterAtIndex:(NSUInteger)index
* 2. - (NSString *)substringFromIndex:(NSUInteger)from
* 3. - (NSString *)substringToIndex:(NSUInteger)to {
* 4. - (NSString *)substringWithRange:(NSRange)range {
* 5. - (NSString *)stringByReplacingOccurrencesOfString:(NSString *)target withString:(NSString *)replacement
* 6. - (NSString *)stringByReplacingOccurrencesOfString:(NSString *)target withString:(NSString *)replacement options:(NSStringCompareOptions)options range:(NSRange)searchRange
* 7. - (NSString *)stringByReplacingCharactersInRange:(NSRange)range withString:(NSString *)replacement
*
*/

View File

@@ -0,0 +1,204 @@
//
// NSString+AvoidCrash.m
// https://github.com/chenfanfang/AvoidCrash
//
// Created by mac on 16/10/5.
// Copyright © 2016 chenfanfang. All rights reserved.
//
#import "NSString+AvoidCrash.h"
#import "AvoidCrash.h"
@implementation NSString (AvoidCrash)
+ (void)avoidCrashExchangeMethod {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class stringClass = NSClassFromString(@"__NSCFConstantString");
//characterAtIndex
[AvoidCrash exchangeInstanceMethod:stringClass method1Sel:@selector(characterAtIndex:) method2Sel:@selector(avoidCrashCharacterAtIndex:)];
//substringFromIndex
[AvoidCrash exchangeInstanceMethod:stringClass method1Sel:@selector(substringFromIndex:) method2Sel:@selector(avoidCrashSubstringFromIndex:)];
//substringToIndex
[AvoidCrash exchangeInstanceMethod:stringClass method1Sel:@selector(substringToIndex:) method2Sel:@selector(avoidCrashSubstringToIndex:)];
//substringWithRange:
[AvoidCrash exchangeInstanceMethod:stringClass method1Sel:@selector(substringWithRange:) method2Sel:@selector(avoidCrashSubstringWithRange:)];
//stringByReplacingOccurrencesOfString:
[AvoidCrash exchangeInstanceMethod:stringClass method1Sel:@selector(stringByReplacingOccurrencesOfString:withString:) method2Sel:@selector(avoidCrashStringByReplacingOccurrencesOfString:withString:)];
//stringByReplacingOccurrencesOfString:withString:options:range:
[AvoidCrash exchangeInstanceMethod:stringClass method1Sel:@selector(stringByReplacingOccurrencesOfString:withString:options:range:) method2Sel:@selector(avoidCrashStringByReplacingOccurrencesOfString:withString:options:range:)];
//stringByReplacingCharactersInRange:withString:
[AvoidCrash exchangeInstanceMethod:stringClass method1Sel:@selector(stringByReplacingCharactersInRange:withString:) method2Sel:@selector(avoidCrashStringByReplacingCharactersInRange:withString:)];
});
}
//=================================================================
// characterAtIndex:
//=================================================================
#pragma mark - characterAtIndex:
- (unichar)avoidCrashCharacterAtIndex:(NSUInteger)index {
unichar characteristic;
@try {
characteristic = [self avoidCrashCharacterAtIndex:index];
}
@catch (NSException *exception) {
NSString *defaultToDo = @"AvoidCrash default is to return a without assign unichar.";
[AvoidCrash noteErrorWithException:exception defaultToDo:defaultToDo];
}
@finally {
return characteristic;
}
}
//=================================================================
// substringFromIndex:
//=================================================================
#pragma mark - substringFromIndex:
- (NSString *)avoidCrashSubstringFromIndex:(NSUInteger)from {
NSString *subString = nil;
@try {
subString = [self avoidCrashSubstringFromIndex:from];
}
@catch (NSException *exception) {
NSString *defaultToDo = AvoidCrashDefaultReturnNil;
[AvoidCrash noteErrorWithException:exception defaultToDo:defaultToDo];
subString = nil;
}
@finally {
return subString;
}
}
//=================================================================
// substringToIndex
//=================================================================
#pragma mark - substringToIndex
- (NSString *)avoidCrashSubstringToIndex:(NSUInteger)to {
NSString *subString = nil;
@try {
subString = [self avoidCrashSubstringToIndex:to];
}
@catch (NSException *exception) {
NSString *defaultToDo = AvoidCrashDefaultReturnNil;
[AvoidCrash noteErrorWithException:exception defaultToDo:defaultToDo];
subString = nil;
}
@finally {
return subString;
}
}
//=================================================================
// substringWithRange:
//=================================================================
#pragma mark - substringWithRange:
- (NSString *)avoidCrashSubstringWithRange:(NSRange)range {
NSString *subString = nil;
@try {
subString = [self avoidCrashSubstringWithRange:range];
}
@catch (NSException *exception) {
NSString *defaultToDo = AvoidCrashDefaultReturnNil;
[AvoidCrash noteErrorWithException:exception defaultToDo:defaultToDo];
subString = nil;
}
@finally {
return subString;
}
}
//=================================================================
// stringByReplacingOccurrencesOfString:
//=================================================================
#pragma mark - stringByReplacingOccurrencesOfString:
- (NSString *)avoidCrashStringByReplacingOccurrencesOfString:(NSString *)target withString:(NSString *)replacement {
NSString *newStr = nil;
@try {
newStr = [self avoidCrashStringByReplacingOccurrencesOfString:target withString:replacement];
}
@catch (NSException *exception) {
NSString *defaultToDo = AvoidCrashDefaultReturnNil;
[AvoidCrash noteErrorWithException:exception defaultToDo:defaultToDo];
newStr = nil;
}
@finally {
return newStr;
}
}
//=================================================================
// stringByReplacingOccurrencesOfString:withString:options:range:
//=================================================================
#pragma mark - stringByReplacingOccurrencesOfString:withString:options:range:
- (NSString *)avoidCrashStringByReplacingOccurrencesOfString:(NSString *)target withString:(NSString *)replacement options:(NSStringCompareOptions)options range:(NSRange)searchRange {
NSString *newStr = nil;
@try {
newStr = [self avoidCrashStringByReplacingOccurrencesOfString:target withString:replacement options:options range:searchRange];
}
@catch (NSException *exception) {
NSString *defaultToDo = AvoidCrashDefaultReturnNil;
[AvoidCrash noteErrorWithException:exception defaultToDo:defaultToDo];
newStr = nil;
}
@finally {
return newStr;
}
}
//=================================================================
// stringByReplacingCharactersInRange:withString:
//=================================================================
#pragma mark - stringByReplacingCharactersInRange:withString:
- (NSString *)avoidCrashStringByReplacingCharactersInRange:(NSRange)range withString:(NSString *)replacement {
NSString *newStr = nil;
@try {
newStr = [self avoidCrashStringByReplacingCharactersInRange:range withString:replacement];
}
@catch (NSException *exception) {
NSString *defaultToDo = AvoidCrashDefaultReturnNil;
[AvoidCrash noteErrorWithException:exception defaultToDo:defaultToDo];
newStr = nil;
}
@finally {
return newStr;
}
}
@end