美文网首页
Runtime 四之交换方法防止整个项目数组越界

Runtime 四之交换方法防止整个项目数组越界

作者: joymake | 来源:发表于2017-05-26 14:09 被阅读120次

数组取数据组越界的问题我想每个程序🐒都遇到过无数次,我们这章不谈如何解决bug,不谈这样做
是否正确, 只谈如何通过runtime交换objectatidex方法导致crash的问题用于对runtime的
理解扩展(!!!注意,此方法并不会解决我们代码所产生的bug,仅仅会防止整个项目中数组的
越界crash问题,所以不要以为这样做了就可以不管bug了)

同上一章,我们需要建一个pch文件加到prefix headder中,在pch中我们包含这个category

众所周知try catch方法可以让编译器在遇到crash情况时抛出异常而不至于crash,那我们就通过
替换经常crash的objectatindex方法替换为try catch的lxzObjectAtIndex来实现

[demo传送门]https://github.com/joy-make/nsarrayBounds.git

category具体实现如下

#import "NSArray+LXZArray.h"
@implementation NSArray (LXZArray)
+(void)load{
[super load];
//定义方法a
  Method fromMethod = class_getInstanceMethod(objc_getClass("__NSArrayI"), @selector(objectAtIndex:));
//定义方法b
  Method toMethod = class_getInstanceMethod(objc_getClass("__NSArrayI"), @selector(lxzObjectAtIndex:));
//交换方法a和b
  method_exchangeImplementations(fromMethod, toMethod);
}
- (id)lxzObjectAtIndex:(NSInteger)index{
if (self.count-1<index) {
  @try 
  {
    [self lxzObjectAtIndex:index];
  }
@catch (NSException *exception)
 {
  NSLog(@"---------- %s Crash Because Method %s  ----------\n",   class_getName(self.class), __func__);
  NSLog(@"ERROR:%@",[exception callStackSymbols]);
}@finally {//xxx}
  return nil;
  }
else{ return [self lxzObjectAtIndex:index];}
}
runtime 交换方法还有好多其他的用处,就不一一举例了
@end

测试一下

@interface ViewController (){
    NSTimer *_timer;
}

@property (weak, nonatomic) IBOutlet UILabel *displayLabel;
@property (nonatomic,strong)NSArray *listArray;
@end

@implementation ViewController
static int repeats = 0;

- (void)viewDidLoad {
    
    [super viewDidLoad];
    
    __weak __typeof(&*self)weakSelf = self;
    _timer = [NSTimer scheduledTimerWithTimeInterval:0.4 repeats:10 block:^(NSTimer * _Nonnull timer) {
        weakSelf.displayLabel.text = repeats>=weakSelf.listArray.count-1?[NSString stringWithFormat:@"第%d个元素应该crash但没有crash",repeats++]:weakSelf.listArray[repeats++];
    }];
    _timer.fireDate = [NSDate distantFuture];

}
-(NSArray *)listArray{
    return _listArray =_listArray?:@[@"0",@"1",@"2"];
}
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}
- (IBAction)testListCrash:(id)sender {
    repeats = 0;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    _timer.fireDate = [NSDate distantPast];
    });
}

相关文章

网友评论

      本文标题:Runtime 四之交换方法防止整个项目数组越界

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