What is array out of bounds

Array out of bounds, a lot of novice easy to catch the bug,

NSArray *ar = @[@ "123"@ (456), @"haha"];
nsstring *str = ar[3];// The array value is out of bounds
Copy the code

This seems very simple, but in the actual development application, all kinds of data variables are constantly changing in the process of running the program, which is easy to be ignored. If you are not careful, it will cross the boundary and lead to crash. Regardless of why we crossed the line, that’s another issue, at least the basic thing is to make sure that the program doesn’t crash.

The simplest solution is to limit the value of an index. For example:

NSArray *moduleTexts = @[@" Information System".@" Digital Resources".@" Seismic Case System".@" Encyclopedia system"];
int index = self.moduleCode.intValue- 1;//moduleCode is a server return value of type NSString
index = MAX(MIN(index, 3), 0);
lb_moduleType.text = moduleTexts[index];
Copy the code

Use the Runtime mechanism to swap methods in array classification

The basic idea is: return nil if the array is out of bounds, and return the original index if it is not out of bounds. This will prevent the program from crashing.

1. Create a Category Category for NSObject

The classification file is a single method that replaces the system method with the Runtime mechanism.

NSObject + ExchangeMethod. H file:

#import <Foundation/Foundation.h>
@interface NSObject (ExchangeMethod)

/** * Replace system methods (exchange instance methods) ** @param systemSelector Method to be replaced * @param changedSelector method actually used * @param error Error message during the replacement * * @return Whether the replacement succeeds */
+ (BOOL)exchangedSystemSelector:(SEL)systemSelector withSelector:(SEL)changedSelector error:(NSError *)error;

@end
Copy the code

Create.m file NSObject+ exchangemethod. m:

#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
Copy the code

Create a class for NSArray

NSArray + Overflow. H file:

#import <objc/runtime.h>
#import <Foundation/Foundation.h>

@interface NSArray (Overflow)

@end

Copy the code

NSArray + Overflow. M file:

#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)hd_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)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
Copy the code

Create NSMutabeArray class;

NSMutableArray + Overflow. H file:

#import <Foundation/Foundation.h>

@interface NSMutableArray (Overflow)

@end
Copy the code

NSMutableArray + Overflow. M file:

#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: array transgressed, 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: array transgressed, index = %ld, count = %ld", index, self.count); return nil; } } @endCopy the code

PCH = xxxx-prefix. PCH = xxxx-prefix. PCH = xxxx-prefix. PCH = xxxx-prefix. PCH = xxxx-prefix. PCH = xxxx-prefix. PCH = xxxx-prefix. PCH = xxxx-prefix. PCH

#ifdef __OBJC__
#define MAS_SHORTHAND

#import "NSArray+overflow.h"
#import "NSMutableArray+Overflow.h"

#endif
Copy the code