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 +
2098153
2 libsystem_platform.dylib
0x33a66873 _sigtramp +
34
3 libsystem_blocks.dylib
0x33941ae1 _Block_release +
216
4 libobjc.A.dylib
0x333c11a9 +
404
5 CoreFoundation
0x25ba23a9 _CFAutoreleasePoolPop +
16
6 UIKit
0x2912317f +
42
7 CoreFoundation
0x25c565cd +
20
8 CoreFoundation
0x25c53c8b +
278
9 CoreFoundation
0x25c54093 +
914
10 CoreFoundation
0x25ba2621 CFRunLoopRunSpecific +
476
11 CoreFoundation
0x25ba2433 CFRunLoopRunInMode +
106
12 GraphicsServices
0x2cf0a0a9 GSEventRunModal +
136
13 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