美文网首页
iOS崩溃处理机制:Container类型crash防护

iOS崩溃处理机制:Container类型crash防护

作者: 光之盐汽水 | 来源:发表于2020-10-18 21:33 被阅读0次

    Container类型的crash 指的是容器类的crash,常见的有NSArray/NSMutableArray/NSDictionary/NSMutableDictionary/NSCache的crash。 一些常见的越界,插入nil,等错误操作均会导致此类crash发生。

    解决方案:
    对于容易造成crash的方法,自定义方法进行交换,并在自定义的方法中加入一些条件限制和判断。

    具体方式:
    1、NSArray crash:

    #import <Foundation/Foundation.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface NSArray (XZCrash)
    
    + (void)xz_enableArrayProtector;
    
    @end
    
    NS_ASSUME_NONNULL_END
    
    /**
     
     iOS 8:下都是__NSArrayI
     iOS11: 之后分 __NSArrayI、  __NSArray0、__NSSingleObjectArrayI
     
     iOS11之前:arr@[]  调用的是[__NSArrayI objectAtIndexed]
     iOS11之后:arr@[]  调用的是[__NSArrayI objectAtIndexedSubscript]
     
     arr为空数组
     *** -[__NSArray0 objectAtIndex:]: index 12 beyond bounds for empty NSArray
     
     arr只有一个元素
     *** -[__NSSingleObjectArrayI objectAtIndex:]: index 12 beyond bounds [0 .. 0]
     
     */
    
    #import "NSArray+XZCrash.h"
    #import "NSObject+XZSwizzle.h"
    #import <objc/runtime.h>
    
    @implementation NSArray (XZCrash)
    
    + (void)xz_enableArrayProtector {
        
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            
            /**
             __NSArray0 仅仅初始化后不含有元素的数组          ( NSArray *arr2 =  [[NSArray alloc]init]; )
             __NSSingleObjectArrayI 只有一个元素的数组      ( NSArray *arr3 =  [[NSArray alloc]initWithObjects: @"1",nil]; )
             __NSPlaceholderArray 占位数组                ( NSArray *arr4 =  [NSArray alloc]; )
             __NSArrayI 初始化后的不可变数组                ( NSArray *arr1 =  @[@"1",@"2"]; )
             */
            Class __NSArray = objc_getClass("NSArray");
            Class __NSArrayI = objc_getClass("__NSArrayI");
            Class __NSSingleObjectArrayI = objc_getClass("__NSSingleObjectArrayI");
            Class __NSArray0 = objc_getClass("__NSArray0");
            
            
            [self xz_classSwizzleMethodWithClass:__NSArray orginalMethod:@selector(arrayWithObjects:count:) replaceMethod:@selector(xz_arrayWithObjects:count:)];
            
            
            // [arr objectAtIndex:];
            [self xz_instanceSwizzleMethodWithClass:__NSArrayI orginalMethod:@selector(objectAtIndex:) replaceMethod:@selector(xz_objectAtIndex:)];
            
            // arr[];
            [self xz_instanceSwizzleMethodWithClass:__NSArrayI orginalMethod:@selector(objectAtIndexedSubscript:) replaceMethod:@selector(xz_objectAtIndexedSubscript:)];
            
            // 数组为空
            [self xz_instanceSwizzleMethodWithClass:__NSArray0 orginalMethod:@selector(objectAtIndex:) replaceMethod:@selector(xz_objectAtIndexedNullarray:)];
            
            // 数组count == 1
            [self xz_instanceSwizzleMethodWithClass:__NSSingleObjectArrayI orginalMethod:@selector(objectAtIndex:) replaceMethod:@selector(xz_objectAtIndexedArrayCountOnlyOne:)];
            
            // objectsAtIndexes:
            [self xz_instanceSwizzleMethodWithClass:__NSArray orginalMethod:@selector(objectsAtIndexes:) replaceMethod:@selector(xz_objectsAtIndexes:)];
            
            // 以下方法调用频繁,替换可能会影响性能
            // getObjects:range:
            [self xz_instanceSwizzleMethodWithClass:__NSArray orginalMethod:@selector(getObjects:range:) replaceMethod:@selector(xz_getObjectsNSArray:range:)];
            [self xz_instanceSwizzleMethodWithClass:__NSSingleObjectArrayI orginalMethod:@selector(getObjects:range:) replaceMethod:@selector(xz_getObjectsNSSingleObjectArrayI:range:)];
            [self xz_instanceSwizzleMethodWithClass:__NSArrayI orginalMethod:@selector(getObjects:range:) replaceMethod:@selector(xz_getObjectsNSArrayI:range:)];
        });
    }
    
    
    // 创建类
    + (instancetype)xz_arrayWithObjects:(const id  _Nonnull __unsafe_unretained *)objects count:(NSUInteger)cnt {
        id instance = nil;
        
        @try {
            instance = [self xz_arrayWithObjects:objects count:cnt];
            
        } @catch (NSException *exception) {
            
            // 去掉nil的数据,用新数据重新初始化数组
            NSInteger newObjectsIndex = 0;
            id _Nonnull __unsafe_unretained newObjects[cnt];
            
            for (int i = 0; i < cnt; i ++) {
                if (objects[i] != nil) {
                    newObjects[newObjectsIndex] = objects[i];
                    newObjectsIndex ++;
                }
            }
            instance = [self xz_arrayWithObjects:newObjects count:newObjectsIndex];
            
        } @finally {
            return instance;
        }
    }
    
    
    - (id)xz_objectAtIndex:(NSUInteger)index {
        
        id object = nil;
        
        @try {
            object = [self xz_objectAtIndex:index];
            
        } @catch (NSException *exception) {
            
        } @finally {
            return object;
        }
    }
    
    - (id)xz_objectAtIndexedSubscript:(NSUInteger)index {
        
        id object = nil;
        
        @try {
            object = [self xz_objectAtIndexedSubscript:index];
            
        } @catch (NSException *exception) {
            
        } @finally {
            return object;
        }
    }
    
    - (id)xz_objectAtIndexedNullarray:(NSUInteger)index {
        
        id object = nil;
        
        @try {
            object = [self xz_objectAtIndexedNullarray:index];
            
        } @catch (NSException *exception) {
            
        } @finally {
            return object;
        }
    }
    
    - (id)xz_objectAtIndexedArrayCountOnlyOne:(NSUInteger)index {
        
        id object = nil;
        
        @try {
            object = [self xz_objectAtIndexedArrayCountOnlyOne:index];
            
        } @catch (NSException *exception) {
            
        } @finally {
            return object;
        }
    }
    
    - (NSArray *)xz_objectsAtIndexes:(NSIndexSet *)indexes {
        
        NSArray *returnArray = nil;
        
        @try {
            returnArray = [self xz_objectsAtIndexes:indexes];
            
        } @catch (NSException *exception) {
            
        } @finally {
            return returnArray;
        }
    }
    
    
    #pragma mark getObjects:range:
    - (void)xz_getObjectsNSArray:(__unsafe_unretained id  _Nonnull *)objects range:(NSRange)range {
        @try {
            [self xz_getObjectsNSArray:objects range:range];
        } @catch (NSException *exception) {
        } @finally {
        }
    }
    
    - (void)xz_getObjectsNSSingleObjectArrayI:(__unsafe_unretained id  _Nonnull *)objects range:(NSRange)range {
        @try {
            [self xz_getObjectsNSSingleObjectArrayI:objects range:range];
        } @catch (NSException *exception) {
        } @finally {
        }
    }
    
    - (void)xz_getObjectsNSArrayI:(__unsafe_unretained id  _Nonnull *)objects range:(NSRange)range {
        @try {
            [self xz_getObjectsNSArrayI:objects range:range];
        } @catch (NSException *exception) {
        } @finally {
        }
    }
    
    @end
    

    2、NSMutableArray Crash:

    #import <Foundation/Foundation.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface NSMutableArray (XZCrash)
    
    + (void)xz_enableMutableArrayProtector;
    
    @end
    
    NS_ASSUME_NONNULL_END
    
    #import "NSMutableArray+XZCrash.h"
    #import "NSObject+XZSwizzle.h"
    
    @implementation NSMutableArray (XZCrash)
    
    
    + (void)xz_enableMutableArrayProtector {
        
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            
            Class __NSArrayM = NSClassFromString(@"__NSArrayM");
            
            // objectAtIndex:
            [self xz_instanceSwizzleMethodWithClass:__NSArrayM orginalMethod:@selector(objectAtIndex:) replaceMethod:@selector(xz_objectAtIndex:)];
            
            [self xz_instanceSwizzleMethodWithClass:__NSArrayM orginalMethod:@selector(objectAtIndexedSubscript:) replaceMethod:@selector(xz_objectAtIndexedSubscript:)];
    
            //insertObject:atIndex:
            [self xz_instanceSwizzleMethodWithClass:__NSArrayM orginalMethod:@selector(insertObject:atIndex:) replaceMethod:@selector(xz_insertObject:atIndex:)];
    
            //removeObjectAtIndex:
            [self xz_instanceSwizzleMethodWithClass:__NSArrayM orginalMethod:@selector(removeObjectAtIndex:) replaceMethod:@selector(xz_removeObjectAtIndex:)];
    
            //setObject:atIndexedSubscript:
            [self xz_instanceSwizzleMethodWithClass:__NSArrayM orginalMethod:@selector(setObject:atIndexedSubscript:) replaceMethod:@selector(xz_setObject:atIndexedSubscript:)];
    
            [self xz_instanceSwizzleMethodWithClass:__NSArrayM orginalMethod:@selector(getObjects:range:) replaceMethod:@selector(xz_getObjects:range:)];
        });
    }
    
    
    - (id)xz_objectAtIndex:(NSUInteger)index {
        id object = nil;
        @try {
            object = [self xz_objectAtIndex:index];
        }
        @catch (NSException *exception) {
        }
        @finally {
            return object;
        }
    }
    
    - (id)xz_objectAtIndexedSubscript:(NSUInteger)index {
        id object = nil;
        @try {
            object = [self xz_objectAtIndex:index];
        }
        @catch (NSException *exception) {
        }
        @finally {
            return object;
        }
    }
    
    - (void)xz_insertObject:(id)anObject atIndex:(NSUInteger)index {
        @try {
            [self xz_insertObject:anObject atIndex:index];
        }
        @catch (NSException *exception) {
        }
        @finally {
        }
    }
    
    - (void)xz_removeObjectAtIndex:(NSUInteger)index {
        @try {
            [self xz_removeObjectAtIndex:index];
        }
        @catch (NSException *exception) {
        }
        @finally {
        }
    }
    
    - (void)xz_setObject:(id)obj atIndexedSubscript:(NSUInteger)idx {
        @try {
            [self xz_setObject:obj atIndexedSubscript:idx];
        }
        @catch (NSException *exception) {
        }
        @finally {
        }
    }
    
    - (void)xz_getObjects:(__unsafe_unretained id  _Nonnull *)objects range:(NSRange)range {
        @try {
            [self xz_getObjects:objects range:range];
        } @catch (NSException *exception) {
        } @finally {
        }
    }
    
    @end
    

    3、NSString Crash:

    #import <Foundation/Foundation.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface NSString (XZCrash)
    
    + (void)xz_enableStringProtector;
    
    @end
    
    NS_ASSUME_NONNULL_END
    
    #import "NSString+XZCrash.h"
    #import "NSObject+XZSwizzle.h"
    
    @implementation NSString (XZCrash)
    
    
    + (void)xz_enableStringProtector {
        
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            
            Class __NSCFConstantString = NSClassFromString(@"__NSCFConstantString");
            
            //substringFromIndex
            [self xz_instanceSwizzleMethodWithClass:__NSCFConstantString orginalMethod:@selector(substringFromIndex:) replaceMethod:@selector(xz_substringFromIndex:)];
            
            //substringToIndex
            [self xz_instanceSwizzleMethodWithClass:__NSCFConstantString orginalMethod:@selector(substringToIndex:) replaceMethod:@selector(xz_substringToIndex:)];
            
            //substringWithRange:
            [self xz_instanceSwizzleMethodWithClass:__NSCFConstantString orginalMethod:@selector(substringWithRange:) replaceMethod:@selector(xz_substringWithRange:)];
            
            //characterAtIndex
            [self xz_instanceSwizzleMethodWithClass:__NSCFConstantString orginalMethod:@selector(characterAtIndex:) replaceMethod:@selector(xz_characterAtIndex:)];
            
            /* 注意swizzling先后顺序 👇: */
            //stringByReplacingOccurrencesOfString:withString:options:range:
            [self xz_instanceSwizzleMethodWithClass:__NSCFConstantString orginalMethod:@selector(stringByReplacingOccurrencesOfString:withString:options:range:) replaceMethod:@selector(xz_stringByReplacingOccurrencesOfString:withString:options:range:)];
    
            //stringByReplacingCharactersInRange:withString:
            [self xz_instanceSwizzleMethodWithClass:__NSCFConstantString orginalMethod:@selector(stringByReplacingCharactersInRange:withString:) replaceMethod:@selector(xz_stringByReplacingCharactersInRange:withString:)];
        });
    }
    
    
    #pragma mark - characterAtIndex:
    
    - (unichar)xz_characterAtIndex:(NSUInteger)index {
        
        unichar characteristic;
        @try {
            characteristic = [self xz_characterAtIndex:index];
        }
        @catch (NSException *exception) {
        }
        @finally {
            return characteristic;
        }
    }
    
    #pragma mark - substringFromIndex:
    
    - (NSString *)xz_substringFromIndex:(NSUInteger)from {
        
        NSString *subString = nil;
        
        @try {
            subString = [self xz_substringFromIndex:from];
        }
        @catch (NSException *exception) {
            subString = nil;
        }
        @finally {
            return subString;
        }
    }
    
    #pragma mark - substringToIndex
    - (NSString *)xz_substringToIndex:(NSUInteger)index {
        
        NSString *subString = nil;
        
        @try {
            subString = [self xz_substringToIndex:index];
        }
        @catch (NSException *exception) {
            subString = nil;
        }
        @finally {
            return subString;
        }
    }
    
    #pragma mark - stringByReplacingCharactersInRange:withString:
    
    - (NSString *)xz_stringByReplacingCharactersInRange:(NSRange)range withString:(NSString *)replacement {
        
        NSString *newStr = nil;
        
        @try {
            newStr = [self xz_stringByReplacingCharactersInRange:range withString:replacement];
        }
        @catch (NSException *exception) {
            newStr = nil;
        }
        @finally {
            return newStr;
        }
    }
    
    - (NSString *)xz_stringByReplacingOccurrencesOfString:(NSRange)range withString:(NSString *)replacement {
        
        NSString *newStr = nil;
        
        @try {
            newStr = [self xz_stringByReplacingOccurrencesOfString:range withString:replacement];
        }
        @catch (NSException *exception) {
            newStr = nil;
        }
        @finally {
            return newStr;
        }
    }
    
    #pragma mark - stringByReplacingOccurrencesOfString:withString:options:range:
    
    - (NSString *)xz_stringByReplacingOccurrencesOfString:(NSString *)target withString:(NSString *)replacement options:(NSStringCompareOptions)options range:(NSRange)searchRange {
        
        NSString *newStr = nil;
        
        @try {
            newStr = [self xz_stringByReplacingOccurrencesOfString:target withString:replacement options:options range:searchRange];
        }
        @catch (NSException *exception) {
            newStr = nil;
        }
        @finally {
            return newStr;
        }
    }
    
    #pragma mark - substringWithRange:
    - (NSString *)xz_substringWithRange:(NSRange)range {
        
        NSString *subString = nil;
        
        @try {
            subString = [self xz_substringWithRange:range];
        }
        @catch (NSException *exception) {
            subString = nil;
        }
        @finally {
            return subString;
        }
    }
    
    @end
    

    4、NSMutableString Crash:

    #import <Foundation/Foundation.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface NSMutableString (XZCrash)
    
    + (void)xz_enableMutableStringProtector;
    
    @end
    
    NS_ASSUME_NONNULL_END
    
    #import "NSMutableString+XZCrash.h"
    #import "NSObject+XZSwizzle.h"
    
    @implementation NSMutableString (XZCrash)
    
    
    + (void)xz_enableMutableStringProtector {
        
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            
            Class __NSCFString = NSClassFromString(@"__NSCFString");
            
            //substringFromIndex
            [self xz_instanceSwizzleMethodWithClass:__NSCFString orginalMethod:@selector(substringFromIndex:) replaceMethod:@selector(xz_substringFromIndex:)];
            
            //substringToIndex
            [self xz_instanceSwizzleMethodWithClass:__NSCFString orginalMethod:@selector(substringToIndex:) replaceMethod:@selector(xz_substringToIndex:)];
            
            //substringWithRange:
            [self xz_instanceSwizzleMethodWithClass:__NSCFString orginalMethod:@selector(substringWithRange:) replaceMethod:@selector(xz_substringWithRange:)];
            
            //characterAtIndex
            [self xz_instanceSwizzleMethodWithClass:__NSCFString orginalMethod:@selector(characterAtIndex:) replaceMethod:@selector(xz_characterAtIndex:)];
            
            //replaceCharactersInRange
            [self xz_instanceSwizzleMethodWithClass:__NSCFString orginalMethod:@selector(replaceCharactersInRange:withString:) replaceMethod:@selector(xz_replaceCharactersInRange:withString:)];
            
            //insertString:atIndex:
            [self xz_instanceSwizzleMethodWithClass:__NSCFString orginalMethod:@selector(insertString:atIndex:) replaceMethod:@selector(xz_insertString:atIndex:)];
    
            //deleteCharactersInRange
            [self xz_instanceSwizzleMethodWithClass:__NSCFString orginalMethod:@selector(deleteCharactersInRange:) replaceMethod:@selector(xz_deleteCharactersInRange:)];
        });
    }
    
    #pragma mark - characterAtIndex:
    
    - (unichar)xz_characterAtIndex:(NSUInteger)index {
        
        unichar characteristic;
        @try {
            characteristic = [self xz_characterAtIndex:index];
        }
        @catch (NSException *exception) {
        }
        @finally {
            return characteristic;
        }
    }
    
    #pragma mark - substringFromIndex:
    
    - (NSString *)xz_substringFromIndex:(NSUInteger)from {
        
        NSString *subString = nil;
        
        @try {
            subString = [self xz_substringFromIndex:from];
        }
        @catch (NSException *exception) {
            subString = nil;
        }
        @finally {
            return subString;
        }
    }
    
    #pragma mark - substringToIndex
    - (NSString *)xz_substringToIndex:(NSUInteger)index {
        
        NSString *subString = nil;
        
        @try {
            subString = [self xz_substringToIndex:index];
        }
        @catch (NSException *exception) {
            subString = nil;
        }
        @finally {
            return subString;
        }
    }
    
    #pragma mark - substringWithRange:
    - (NSString *)xz_substringWithRange:(NSRange)range {
        
        NSString *subString = nil;
        
        @try {
            subString = [self xz_substringWithRange:range];
        }
        @catch (NSException *exception) {
            subString = nil;
        }
        @finally {
            return subString;
        }
    }
    
    
    #pragma mark - replaceCharactersInRange
    - (void)xz_replaceCharactersInRange:(NSRange)range withString:(NSString *)aString {
        @try {
            [self xz_replaceCharactersInRange:range withString:aString];
        }
        @catch (NSException *exception) {
        }
        @finally {
        }
    }
    
    #pragma mark - insertString:atIndex:
    - (void)xz_insertString:(NSString *)aString atIndex:(NSUInteger)loc {
        
        @try {
            [self xz_insertString:aString atIndex:loc];
        }
        @catch (NSException *exception) {
        }
        @finally {
        }
    }
    
    #pragma mark - deleteCharactersInRange
    
    - (void)xz_deleteCharactersInRange:(NSRange)range {
        
        @try {
            [self xz_deleteCharactersInRange:range];
        }
        @catch (NSException *exception) {
        }
        @finally {
        }
    }
    
    @end
    

    5、NSDictionary Crash:

    #import <Foundation/Foundation.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface NSDictionary (XZCrash)
    
    + (void)xz_enableDictionaryProtector;
    
    @end
    
    NS_ASSUME_NONNULL_END
    
    #import "NSDictionary+XZCrash.h"
    #import "NSObject+XZSwizzle.h"
    
    @implementation NSDictionary (XZCrash)
    
    
    + (void)xz_enableDictionaryProtector {
        
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            
            // __NSPlaceholderDictionary
            [self xz_classSwizzleMethodWithClass:self orginalMethod:@selector(dictionaryWithObjects:forKeys:count:) replaceMethod:@selector(xz_dictionaryWithObjects:forKeys:count:)];
        });
    }
    
    + (instancetype)xz_dictionaryWithObjects:(const id  _Nonnull __unsafe_unretained *)objects forKeys:(const id<NSCopying>  _Nonnull __unsafe_unretained *)keys count:(NSUInteger)cnt {
        
        id instance = nil;
        @try {
            instance = [self xz_dictionaryWithObjects:objects forKeys:keys count:cnt];
        }
        @catch (NSException *exception) {
            
            //处理错误的数据,然后重新初始化一个字典
            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 xz_dictionaryWithObjects:newObjects forKeys:newkeys count:index];
        }
        @finally {
            return instance;
        }
    }
    
    @end
    

    6、NSMutableDictionary Crash:

    #import <Foundation/Foundation.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface NSMutableDictionary (XZCrash)
    
    + (void)xz_enableMutableDictionaryProtector;
    
    @end
    
    NS_ASSUME_NONNULL_END
    
    #import "NSMutableDictionary+XZCrash.h"
    #import "NSObject+XZSwizzle.h"
    
    @implementation NSMutableDictionary (XZCrash)
    
    
    + (void)xz_enableMutableDictionaryProtector {
        
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            
            Class dictionaryM = NSClassFromString(@"__NSDictionaryM");
            
            //setObject:forKey:
            [self  xz_instanceSwizzleMethodWithClass:dictionaryM orginalMethod:@selector(setObject:forKey:) replaceMethod:@selector(xz_setObject:forKey:)];
            
            // iOS11
            [self xz_instanceSwizzleMethodWithClass:dictionaryM orginalMethod:@selector(setObject:forKeyedSubscript:) replaceMethod:@selector(xz_setObject:forKeyedSubscript:)];
    
            
            //removeObjectForKey:
            [self xz_instanceSwizzleMethodWithClass:dictionaryM orginalMethod:@selector(removeObjectForKey:) replaceMethod:@selector(xz_removeObjectForKey:)];
        });
    }
    
    - (void)xz_setObject:(id)anObject forKey:(id<NSCopying>)aKey {
        
        @try {
            [self xz_setObject:anObject forKey:aKey];
        }
        @catch (NSException *exception) {
        }
        @finally {
        }
    }
    
    - (void)xz_setObject:(id)anObject forKeyedSubscript:(id<NSCopying>)aKey {
        
        @try {
            [self xz_setObject:anObject forKey:aKey];
        }
        @catch (NSException *exception) {
        }
        @finally {
        }
    }
    
    - (void)xz_removeObjectForKey:(id)aKey {
        
        @try {
            [self xz_removeObjectForKey:aKey];
        }
        @catch (NSException *exception) {
        }
        @finally {
        }
    }
    
    @end
    

    7、NSAttributedString Crash:

    #import <Foundation/Foundation.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface NSAttributedString (XZCrash)
    
    + (void)xz_enableAttributedStringProtector;
    
    @end
    
    NS_ASSUME_NONNULL_END
    
    #import "NSAttributedString+XZCrash.h"
    #import "NSObject+XZSwizzle.h"
    
    @implementation NSAttributedString (XZCrash)
    
    
    + (void)xz_enableAttributedStringProtector {
        
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            
            Class NSConcreteAttributedString = NSClassFromString(@"NSConcreteAttributedString");
            
            //initWithString:
            [self xz_instanceSwizzleMethodWithClass:NSConcreteAttributedString orginalMethod:@selector(initWithString:) replaceMethod:@selector(xz_initWithString:)];
            //initWithAttributedString
            [self xz_instanceSwizzleMethodWithClass:NSConcreteAttributedString orginalMethod:@selector(initWithAttributedString:) replaceMethod:@selector(xz_initWithAttributedString:)];
    
            //initWithString:attributes:
            [self xz_instanceSwizzleMethodWithClass:NSConcreteAttributedString orginalMethod:@selector(initWithString:attributes:) replaceMethod:@selector(xz_initWithString:attributes:)];
        });
    }
    
    
    - (instancetype)xz_initWithString:(NSString *)str {
        id object = nil;
        
        @try {
            object = [self xz_initWithString:str];
        }
        @catch (NSException *exception) {
        }
        @finally {
            return object;
        }
    }
    
    #pragma mark - initWithAttributedString
    - (instancetype)xz_initWithAttributedString:(NSAttributedString *)attrStr {
        id object = nil;
        
        @try {
            object = [self xz_initWithAttributedString:attrStr];
        }
        @catch (NSException *exception) {
        }
        @finally {
            return object;
        }
    }
    
    #pragma mark - initWithString:attributes:
    
    - (instancetype)xz_initWithString:(NSString *)str attributes:(NSDictionary<NSString *,id> *)attrs {
        id object = nil;
        
        @try {
            object = [self xz_initWithString:str attributes:attrs];
        }
        @catch (NSException *exception) {
        }
        @finally {
            return object;
        }
    }
    
    @end
    

    8、NSMutableAttributedString Crash:

    #import <Foundation/Foundation.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface NSMutableAttributedString (XZCrash)
    
    + (void)xz_enableMutableAttributedStringProtector;
    
    @end
    
    NS_ASSUME_NONNULL_END
    
    #import "NSMutableAttributedString+XZCrash.h"
    #import "NSObject+XZSwizzle.h"
    
    @implementation NSMutableAttributedString (XZCrash)
    
    
    + (void)xz_enableMutableAttributedStringProtector {
        
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            
            Class NSConcreteMutableAttributedString = NSClassFromString(@"NSConcreteMutableAttributedString");
            
            //initWithString:
            [self xz_instanceSwizzleMethodWithClass:NSConcreteMutableAttributedString orginalMethod:@selector(initWithString:) replaceMethod:@selector(xz_initWithString:)];
    
            //initWithString:attributes:
            [self xz_instanceSwizzleMethodWithClass:NSConcreteMutableAttributedString orginalMethod:@selector(initWithString:attributes:) replaceMethod:@selector(xz_initWithString:attributes:)];
        });
    }
    
    
    - (instancetype)xz_initWithString:(NSString *)str {
        id object = nil;
        
        @try {
            object = [self xz_initWithString:str];
        }
        @catch (NSException *exception) {
        }
        @finally {
            return object;
        }
    }
    
    - (instancetype)xz_initWithString:(NSString *)str attributes:(NSDictionary<NSString *,id> *)attrs {
        id object = nil;
        
        @try {
            object = [self xz_initWithString:str attributes:attrs];
        }
        @catch (NSException *exception) {
        }
        @finally {
            return object;
        }
    }
    
    @end
    

    相关文章

      网友评论

          本文标题:iOS崩溃处理机制:Container类型crash防护

          本文链接:https://www.haomeiwen.com/subject/hywzpktx.html