数组越界,不少新手容易中招的bug,数组
NSArray *ar = @[@"123", @(456), @"haha"];
nsstring *str = ar[3];//数组取值越界了
复制代码
这个看起来很简单,可是实际开发应用中,各类数据变量在程序运行过程当中,是常常不断变化的,很容易被忽视,一不当心就越界致使crash。咱们先不论为何越界,这是另外一个议题,至少最基本的咱们要先保证程序不会奔溃是吧。服务器
NSArray *moduleTexts = @[@"资讯系统", @"数字资源", @"震例系统", @"百科系统"];
int index = self.moduleCode.intValue-1;//moduleCode是服务器返回值,NSString类型
index = MAX(MIN(index, 3), 0);
lb_moduleType.text = moduleTexts[index];
复制代码
基本思路是:当数组越界时返回nil,没有越界时返回本来的index.这样就能达到防止程序崩溃的问题.ui
此分类文件就一个方法,该方法用runtime的机制来替换系统方法。spa
NSObject+ExchangeMethod.h文件:code
#import <Foundation/Foundation.h>
@interface NSObject (ExchangeMethod)
/** * 对系统方法进行替换(交换实例方法) * * @param systemSelector 被替换的方法 * @param changedSelector 实际使用的方法 * @param error 替换过程当中出现的错误消息 * * @return 是否替换成功 */
+ (BOOL)exchangedSystemSelector:(SEL)systemSelector withSelector:(SEL)changedSelector error:(NSError *)error;
@end
复制代码
建立.m文件NSObject+ExchangeMethod.m:ip
#import "NSObject+ExchangeMethod.h"
#import <objc/runtime.h>
@implementation NSObject (ExchangeMethod)
+ (BOOL)exchangedSystemSelector:(SEL)systemSelector withSelector:(SEL)changedSelector error:(NSError *)error{
Method systemMethod = class_getInstanceMethod(self, systemSelector);
if (!systemMethod) {
return NO;
}
Method changedMethod = class_getInstanceMethod(self, changedSelector);
if (!changedMethod) {
return NO;
}
if (class_addMethod([self class], systemSelector, method_getImplementation(changedMethod), method_getTypeEncoding(changedMethod))) {
class_replaceMethod([self class], changedSelector, method_getImplementation(systemMethod), method_getTypeEncoding(systemMethod));
}else{
method_exchangeImplementations(systemMethod, changedMethod);
}
return YES;
}
@end
复制代码
NSArray+Overflow.h文件:资源
#import <objc/runtime.h>
#import <Foundation/Foundation.h>
@interface NSArray (Overflow)
@end
复制代码
NSArray+Overflow.m文件:开发
#import "NSArray+Overflow.h"
#import "NSObject+ExchangeMethod.h"
#import <objc/runtime.h>
@implementation NSArray (Overflow)
+(void)load{
[super load];
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[objc_getClass("__NSArrayI") exchangedSystemSelector:@selector(objectAtIndex:) withSelector:@selector(hd_objectAtIndex:) error:nil];
[objc_getClass("__NSArrayI") exchangedSystemSelector:@selector(objectAtIndexedSubscript:) withSelector:@selector(hd_objectAtIndexedSubscript:) error:nil];
});
}
- (id)sxy_objectAtIndexedSubscript:(NSUInteger)index{
if (index < self.count) {
return [self hd_objectAtIndexedSubscript:index];
}else{
NSLog(@"Error:数组越界了,index = %ld, count = %ld", index, self.count);
return nil;
}
}
- (id)sxy_objectAtIndex:(NSUInteger)index{
if (index < self.count) {
return [self hd_objectAtIndex:index];
}else{
NSLog(@"Error:数组越界了,index = %ld, count = %ld", index, self.count);
return nil;
}
}
@end
复制代码
NSMutableArray+Overflow.h文件:get
#import <Foundation/Foundation.h>
@interface NSMutableArray (Overflow)
@end
复制代码
NSMutableArray+Overflow.m文件:string
#import "NSMutableArray+Overflow.h"
#import "NSObject+ExchangeMethod.h"
@implementation NSMutableArray (Overflow)
+(void)load{
[super load];
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[objc_getClass("__NSArrayM") exchangedSystemSelector:@selector(objectAtIndex:) withSelector:@selector(hd_objectAtIndex:) error:nil];
[objc_getClass("__NSArrayM") exchangedSystemSelector:@selector(objectAtIndexedSubscript:) withSelector:@selector(hd_objectAtIndexedSubscript:) error:nil];
});
}
- (id)hd_objectAtIndexedSubscript:(NSUInteger)idx{
if (idx < self.count) {
return [self hd_objectAtIndexedSubscript:idx];
}else{
NSLog(@"Error:数组越界了,index = %ld, count = %ld", idx, self.count);
return nil;
}
}
- (id)hd_objectAtIndex:(NSUInteger)index{
if (index < self.count) {
return [self hd_objectAtIndex:index];
}else{
NSLog(@"Error:数组越界了,index = %ld, count = %ld", index, self.count);
return nil;
}
}
@end
复制代码
#ifdef __OBJC__
#define MAS_SHORTHAND
#import "NSArray+overflow.h"
#import "NSMutableArray+Overflow.h"
#endif
复制代码