How iOS completely avoids array out of bounds

Source: Internet
Author: User

Label:

Let's take a look at the possible array of crash where arrays are out of bounds;

?
1234567 -( void ) TableView: (UITableView *) TableView Didselectrowatindexpath: (Nsindexpath *) Indexpath {      welfareitem *item = [_datasourcearray objectAtIndex:indexPath.row]; //may be out of bounds, you will use [_datasourcearray removeallobjects] When the dropdown is refreshed, and then you click on a cell to crash Code class= "Java Plain" >}  -(UITableViewCell *) TableView: (UITableView *) TableView Cellforrowatindexpath: (Nsindexpath *) Indexpath {       welfareitem *item = _datasourcearray[indexpath.row]; //may be out of bounds, two places with [TableView Reloaddata]; the latter one has [_datasourcearray removeallobjects] The previous one has not finished executing, it will crash


The above code is likely to cross the line, the occurrence of crash is not good to reproduce, sent to the app always receive a few crash; the solution to this problem is also simple code as follows:

?
12345678910111213 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {    WelfareItem *item = nil;    if (indexPath.row < [_datasourceArray count]) {//无论你武功有多高,有时也会忘记加        item = [_datasourceArray objectAtIndex:indexPath.row];    }}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {    WelfareItem *item = nil;    if (indexPath.row < [_datasourceArray count]) {        item = [_datasourceArray objectAtIndex:indexPath.row];    }}


The problem comes again, no matter how high your martial arts, sometimes forget to add; so we have to think of a way of making enemies; I thought of using runtime to replace the Objectatindex method; The code is as follows:

?
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465 666768697071727374757677 /*! @category  @abstract NSObject的Category */@interface NSObject (Util)/*!@method swizzleMethod:withMethod:error:@abstract 对实例方法进行替换@param oldSelector 想要替换的方法@param newSelector 实际替换为的方法@param error 替换过程中出现的错误,如果没有错误为nil*/+ (BOOL)swizzleMethod:(SEL)originalSelector withMethod:(SEL)swizzledSelector error:(NSError **)error;@end#import "NSObject+Util.h"#import <objc runtime.h="">@implementation NSObject (Util)+ (BOOL)swizzleMethod:(SEL)originalSelector withMethod:(SEL)swizzledSelector error:(NSError **)error{    Method originalMethod = class_getInstanceMethod(self, originalSelector);    if (!originalMethod) {        NSString *string = [NSString stringWithFormat:@" %@ 类没有找到 %@ 方法",NSStringFromClass([self class]),NSStringFromSelector(originalSelector)];        *error = [NSError errorWithDomain:@"NSCocoaErrorDomain" code:-1 userInfo:[NSDictionary dictionaryWithObject:string forKey:NSLocalizedDescriptionKey]];        return NO;    }        Method swizzledMethod = class_getInstanceMethod(self, swizzledSelector);    if (!swizzledMethod) {        NSString *string = [NSString stringWithFormat:@" %@ 类没有找到 %@ 方法",NSStringFromClass([self class]),NSStringFromSelector(swizzledSelector)];        *error = [NSError errorWithDomain:@"NSCocoaErrorDomain" code:-1 userInfo:[NSDictionary dictionaryWithObject:string forKey:NSLocalizedDescriptionKey]];        return NO;    }        if (class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))) {        class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));    }    else {        method_exchangeImplementations(originalMethod, swizzledMethod);    }        return YES;}@end@implementation NSArray (ErrerManager)+ (void)load{    static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{        @autoreleasepool        {            [objc_getClass("__NSArrayI") swizzleMethod:@selector(objectAtIndex:) withMethod:@selector(swizzleObjectAtIndex:) error:nil];            [objc_getClass("__NSArrayM") swizzleMethod:@selector(objectAtIndex:) withMethod:@selector(swizzleObjectAtIndex:) error:nil];        };    });}- (id)swizzleObjectAtIndex:(NSUInteger)index{    if (index < self.count)    {        return [self swizzleObjectAtIndex:index];    }    NSLog(@"%@ 越界",self);    return nil;//越界返回为nil}@end</objc>


With the above code we use [_datasourcearray ObjectAtIndex:indexPath.row] will not occur in the cross-border crash;
will return nil; it seems to be a better solution; send out the app, and we crash several times higher than before (crash out of bounds, out of the new crash); crash as follows

?
12345678910111213 1 tbreader 0x002b93e9 tbreader + 20981532 libsystem_platform.dylib 0x33a66873 _sigtramp + 343 libsystem_blocks.dylib 0x33941ae1 _Block_release + 2164 libobjc.A.dylib 0x333c11a9 + 4045 CoreFoundation 0x25ba23a9 _CFAutoreleasePoolPop + 166 UIKit 0x2912317f + 427 CoreFoundation 0x25c565cd + 208 CoreFoundation 0x25c53c8b + 2789 CoreFoundation 0x25c54093 + 91410 CoreFoundation 0x25ba2621 CFRunLoopRunSpecific + 47611 CoreFoundation 0x25ba2433 CFRunLoopRunInMode + 10612 GraphicsServices 0x2cf0a0a9 GSEventRunModal + 13613 UIKit 0x2918c809 UIApplicationMain + 1440

Are this crash, appear in iOS7 above (including iOS7), the key has no user feedback has a problem, crash high several times no user feedback This situation is still rare, we can not reproduce the test; The test has finally reproduced the same crash; Replaced the Objectatindex method has the input of the place out of the soft keyboard press the home button on the phone crash; This method is not only, but also to find his strategy. Then we'll add the extension method code to the array as follows

?
123456789101112131415161718192021222324252627282930 @interface NSArray (SHYUtil)/*! @method objectAtIndexCheck: @abstract 检查是否越界和NSNull如果是返回nil @result 返回对象 */- (id)objectAtIndexCheck:(NSUInteger)index;@end#import "NSArray+SHYUtil.h" @implementation NSArray (SHYUtil)- (id)objectAtIndexCheck:(NSUInteger)index{    if (index >= [self count]) {        return nil;    }        id value = [self objectAtIndex:index];    if (value == [NSNull null]) {        return nil;    }    return value;}@end

Change the previous code welfareitem *item = [_datasourcearray ObjectAtIndex:indexPath.row] to Welfareitem *item = [_datasourcearray Object AtIndexCheck:indexPath.row] It's OK. This allows the array to be completely out of bounds-[__nsarrayi Objectatindex:]: Index beyond bounds [0.. 1] ' wrong

How iOS completely avoids array out of bounds

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

Tags Index: