數組越界,不少新手容易中招的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
複製代碼