└── ST_SafeTool ├── NSArray+Safe.h ├── NSDictionary+Safe.h ├── NSMutableArray+Safe.h ├── NSMutableDictionary+Safe.h ├── NSObject+ImpChangeTool.h ├── NSObject+ImpChangeTool.m ├── NSDictionary+Safe.m ├── NSMutableDictionary+Safe.m ├── NSArray+Safe.m └── NSMutableArray+Safe.m /ST_SafeTool/NSArray+Safe.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSArray+Safe.h 3 | // KVOTest 4 | // 5 | // Created by StriEver on 16/7/29. 6 | // Copyright © 2016年 StriEver. All rights reserved. 7 | // 8 | 9 | #import 10 | @interface NSArray (Safe) 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /ST_SafeTool/NSDictionary+Safe.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+Safe.h 3 | // KVOTest 4 | // 5 | // Created by StriEver on 16/8/1. 6 | // Copyright © 2016年 StriEver. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSDictionary (Safe) 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ST_SafeTool/NSMutableArray+Safe.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableArray+Safe.h 3 | // KVOTest 4 | // 5 | // Created by StriEver on 16/8/1. 6 | // Copyright © 2016年 StriEver. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSMutableArray (Safe) 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ST_SafeTool/NSMutableDictionary+Safe.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableDictionary+Safe.h 3 | // KVOTest 4 | // 5 | // Created by StriEver on 16/8/5. 6 | // Copyright © 2016年 StriEver. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSMutableDictionary (Safe) 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ST_SafeTool/NSObject+ImpChangeTool.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+ImpChangeTool.h 3 | // KVOTest 4 | // 5 | // Created by StriEver on 16/8/1. 6 | // Copyright © 2016年 StriEver. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSObject (ImpChangeTool) 12 | /** 13 | * 交换两个函数实现指针 参数均为NSString类型 14 | * 15 | * @param systemMethodString 系统方法名string 16 | * @param systemClassString 系统实现方法类名string 17 | * @param safeMethodString 自定义hook方法名string 18 | * @param targetClassString 目标实现类名string 19 | */ 20 | + (void)SwizzlingMethod:(NSString *)systemMethodString systemClassString:(NSString *)systemClassString toSafeMethodString:(NSString *)safeMethodString targetClassString:(NSString *)targetClassString; 21 | @end 22 | -------------------------------------------------------------------------------- /ST_SafeTool/NSObject+ImpChangeTool.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+ImpChangeTool.m 3 | // KVOTest 4 | // 5 | // Created by StriEver on 16/8/1. 6 | // Copyright © 2016年 StriEver. All rights reserved. 7 | // 8 | 9 | #import "NSObject+ImpChangeTool.h" 10 | #import 11 | @implementation NSObject (ImpChangeTool) 12 | + (void)SwizzlingMethod:(NSString *)systemMethodString systemClassString:(NSString *)systemClassString toSafeMethodString:(NSString *)safeMethodString targetClassString:(NSString *)targetClassString{ 13 | //获取系统方法IMP 14 | Method sysMethod = class_getInstanceMethod(NSClassFromString(systemClassString), NSSelectorFromString(systemMethodString)); 15 | //自定义方法的IMP 16 | Method safeMethod = class_getInstanceMethod(NSClassFromString(targetClassString), NSSelectorFromString(safeMethodString)); 17 | //IMP相互交换,方法的实现也就互相交换了 18 | method_exchangeImplementations(safeMethod,sysMethod); 19 | } 20 | @end 21 | -------------------------------------------------------------------------------- /ST_SafeTool/NSDictionary+Safe.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+Safe.m 3 | // KVOTest 4 | // 5 | // Created by StriEver on 16/8/1. 6 | // Copyright © 2016年 StriEver. All rights reserved. 7 | // 8 | 9 | #import "NSDictionary+Safe.h" 10 | #import 11 | #import "NSObject+ImpChangeTool.h" 12 | 13 | @implementation NSDictionary (Safe) 14 | + (void)load{ 15 | [self SwizzlingMethod:@"initWithObjects:forKeys:count:" systemClassString:@"__NSPlaceholderDictionary" toSafeMethodString:@"initWithObjects_st:forKeys:count:" targetClassString:@"NSDictionary"]; 16 | } 17 | -(instancetype)initWithObjects_st:(id *)objects forKeys:(id *)keys count:(NSUInteger)count { 18 | NSUInteger rightCount = 0; 19 | for (NSUInteger i = 0; i < count; i++) { 20 | if (!(keys[i] && objects[i])) { 21 | break; 22 | }else{ 23 | rightCount++; 24 | } 25 | } 26 | self = [self initWithObjects_st:objects forKeys:keys count:rightCount]; 27 | return self; 28 | } 29 | @end 30 | -------------------------------------------------------------------------------- /ST_SafeTool/NSMutableDictionary+Safe.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableDictionary+Safe.m 3 | // KVOTest 4 | // 5 | // Created by StriEver on 16/8/5. 6 | // Copyright © 2016年 StriEver. All rights reserved. 7 | // 8 | 9 | #import "NSMutableDictionary+Safe.h" 10 | #import 11 | #import "NSObject+ImpChangeTool.h" 12 | @implementation NSMutableDictionary (Safe) 13 | + (void)load{ 14 | static dispatch_once_t onceToken; 15 | dispatch_once(&onceToken, ^{ 16 | [self SwizzlingMethod:@"st_removeObjectForKey:" systemClassString:@"NSMutableDictionary" toSafeMethodString:@"removeObjectForKey:" targetClassString:@"__NSDictionaryM"]; 17 | [self SwizzlingMethod:@"st_setObject:forKey:" systemClassString:@"NSMutableDictionary" toSafeMethodString:@"setObject:forKey:" targetClassString:@"__NSDictionaryM"]; 18 | }); 19 | } 20 | - (void)st_removeObjectForKey:(id)key { 21 | if (!key) { 22 | return; 23 | } 24 | [self st_removeObjectForKey:key]; 25 | } 26 | - (void)st_setObject:(id)obj forKey:(id )key { 27 | if (!obj) { 28 | return; 29 | } 30 | if (!key) { 31 | return; 32 | } 33 | [self st_setObject:obj forKey:key]; 34 | } 35 | @end 36 | -------------------------------------------------------------------------------- /ST_SafeTool/NSArray+Safe.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSArray+Safe.m 3 | // KVOTest 4 | // 5 | // Created by StriEver on 16/7/29. 6 | // Copyright © 2016年 StriEver. All rights reserved. 7 | // 8 | 9 | #import "NSArray+Safe.h" 10 | #import 11 | #import "NSObject+ImpChangeTool.h" 12 | @implementation NSArray (Safe) 13 | + (void)load{ 14 | static dispatch_once_t onceDispatch; 15 | dispatch_once(&onceDispatch, ^{ 16 | [self SwizzlingMethod:@"objectAtIndex:" systemClassString:@"__NSArrayI" toSafeMethodString:@"st_objectAtIndex:" targetClassString:@"NSArray"]; 17 | 18 | [self SwizzlingMethod:@"initWithObjects:count:" systemClassString:@"__NSPlaceholderArray" toSafeMethodString:@"initWithObjects_st:count:" targetClassString:@"NSArray"]; 19 | // 20 | [self SwizzlingMethod:@"arrayByAddingObject:" systemClassString:@"__NSArrayI" toSafeMethodString:@"arrayByAddingObject_st:" targetClassString:@"NSArray"]; 21 | }); 22 | } 23 | - (id)st_objectAtIndex:(NSUInteger)index{ 24 | //判断数组是否越界 25 | if (index >= [self count]) { 26 | return nil; 27 | } 28 | return [self st_objectAtIndex:index]; 29 | } 30 | - (NSArray *)arrayByAddingObject_st:(id)anObject { 31 | if (!anObject) { 32 | return self; 33 | } 34 | return [self arrayByAddingObject_st:anObject]; 35 | } 36 | - (instancetype)initWithObjects_st:(id *)objects count:(NSUInteger)count { 37 | NSUInteger newCount = 0; 38 | for (NSUInteger i = 0; i < count; i++) { 39 | if (!objects[i]) { 40 | break; 41 | } 42 | newCount++; 43 | } 44 | self = [self initWithObjects_st:objects count:newCount]; 45 | return self; 46 | } 47 | 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /ST_SafeTool/NSMutableArray+Safe.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableArray+Safe.m 3 | // KVOTest 4 | // 5 | // Created by StriEver on 16/8/1. 6 | // Copyright © 2016年 StriEver. All rights reserved. 7 | // 8 | 9 | #import "NSMutableArray+Safe.h" 10 | #import 11 | #import "NSObject+ImpChangeTool.h" 12 | @implementation NSMutableArray (Safe) 13 | + (void)load{ 14 | static dispatch_once_t onceToken; 15 | dispatch_once(&onceToken, ^{ 16 | [self SwizzlingMethod:@"addObject:" systemClassString:@"__NSArrayM" toSafeMethodString:@"st_addObject:" targetClassString:@"NSMutableArray"]; 17 | 18 | [self SwizzlingMethod:@"insertObject:atIndex:" systemClassString:@"__NSArrayM" toSafeMethodString:@"st_insertObject:atIndex:" targetClassString:@"NSMutableArray"]; 19 | 20 | [self SwizzlingMethod:@"removeObjectAtIndex:" systemClassString:@"__NSArrayM" toSafeMethodString:@"st_removeObjectAtIndex:" targetClassString:@"NSMutableArray"]; 21 | 22 | [self SwizzlingMethod:@"replaceObjectAtIndex:withObject:" systemClassString:@"__NSArrayM" toSafeMethodString:@"st_safe_replaceObjectAtIndex:withObject:" targetClassString:@"NSMutableArray"]; 23 | 24 | [self SwizzlingMethod:@"removeObjectsAtIndexes:" systemClassString:@"NSMutableArray" toSafeMethodString:@"st_removeObjectsAtIndexes:" targetClassString:@"NSMutableArray"]; 25 | 26 | [self SwizzlingMethod:@"removeObjectsInRange:" systemClassString:@"NSMutableArray" toSafeMethodString:@"st_removeObjectsInRange:" targetClassString:@"NSMutableArray"]; 27 | 28 | [self SwizzlingMethod:@"objectAtIndex:" systemClassString:@"__NSArrayM" toSafeMethodString:@"st_objectAtIndex:" targetClassString:@"NSMutableArray"]; 29 | 30 | 31 | }); 32 | } 33 | - (void)st_addObject:(id)anObject{ 34 | if (!anObject) { 35 | return; 36 | } 37 | [self st_addObject:anObject]; 38 | } 39 | - (void)st_insertObject:(id)anObject atIndex:(NSUInteger)index { 40 | if (index > [self count]) { 41 | return; 42 | } 43 | if (!anObject) { 44 | return; 45 | } 46 | [self st_insertObject:anObject atIndex:index]; 47 | } 48 | - (void)st_removeObjectAtIndex:(NSUInteger)index { 49 | if (index >= [self count]) { 50 | return; 51 | } 52 | 53 | return [self st_removeObjectAtIndex:index]; 54 | } 55 | - (void)safe_replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject { 56 | if (index >= [self count]) { 57 | return; 58 | } 59 | if (!anObject) { 60 | return; 61 | } 62 | [self safe_replaceObjectAtIndex:index withObject:anObject]; 63 | } 64 | - (void)st_removeObjectsAtIndexes:(NSIndexSet *)indexes{ 65 | NSMutableIndexSet * mutableSet = [NSMutableIndexSet indexSet]; 66 | [indexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop) { 67 | if (idx < [self count ]) { 68 | [mutableSet addIndex:idx]; 69 | } 70 | }]; 71 | [self st_removeObjectsAtIndexes:mutableSet]; 72 | } 73 | - (void)st_removeObjectsInRange:(NSRange)range{ 74 | //获取最大索引 75 | if (range.location + range.length - 1 < [self count]) { 76 | [self st_removeObjectsInRange:range]; 77 | return; 78 | } 79 | if (range.location >= [self count]) { 80 | return; 81 | } 82 | NSInteger tempInteger = range.location + range.length - 1; 83 | while (tempInteger >= [self count]) { 84 | tempInteger -= 1; 85 | } 86 | NSRange tempRange = NSMakeRange(range.location, tempInteger + 1 -range.location); 87 | [self st_removeObjectsInRange:tempRange]; 88 | } 89 | - (id)st_objectAtIndex:(NSUInteger)index{ 90 | //判断数组是否越界 91 | if (index >= [self count]) { 92 | return nil; 93 | } 94 | return [self st_objectAtIndex:index]; 95 | } 96 | @end 97 | --------------------------------------------------------------------------------