Objective-c 非圆弧对象

Objective-c Non Arc Object

我正在管理一个仍在使用 Non Arc 的旧 Objective-c 项目,我在 Fabric Crashlytics 中注意到 EXC_BAD_ACCESS KERN_INVALID_ADDRESS 应用程序崩溃。

这是崩溃的痕迹,我有这个代码行:

[view.label setText:[historyArray getStringForVideoArray]];

即调用此函数:

-(NSString*)getStringForVideoArray {
    NSString *str = nil;

    int seconds = 0;

    for (NSObject *video in self) {
        if (!video) {
            continue;
        }
        if ([video isKindOfClass:[VideoItem class]]) {
            VideoItem *tmp = (VideoItem*)video;
            seconds += tmp.seconds;
        }
    }

    if (seconds != 0) {
        int minutes = seconds / 60;
        if (minutes == 0 || minutes == 1) {
            minutes = 1;
            str = [NSString stringWithFormat:@"%d Min.",minutes];
        } else {
            str = [NSString stringWithFormat:@"%d Mins.",minutes];
        }
    } else {
        str = [NSString stringWithFormat:@""];
    }

    return str;
}

根据我从 Fabric Crashlytics 中注意到的情况,崩溃发生在这一行:

if ([video isKindOfClass:[VideoItem class]]) {

我认为唯一会导致崩溃的是 historyArray 在这个方法中创建:

historyArray = [[NSMutableArray alloc] initWithArray:historyRep.historyArray];

这是class中数组的定义:

@interface HistoryViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> {
    NSMutableArray *historyArray;
}

知道是什么导致了这次崩溃吗?无法将项目更改为 ARC 代码,找不到这个崩溃问题,我真的很沮丧。

编辑

这是我向数组插入项的三种方式:

1) 交换数组中某一项的位置时:

id object = [[[self.historyArray objectAtIndex:firstIndex] retain] autorelease];
[self.historyArray removeObjectAtIndex:firstIndex];
[self.historyArray insertObject:object atIndex:secondIndex];

2) 从另一个 class 插入项目: [self.historyArray insertObject:video atIndex:0]; 创建自:

if (self.videoItem)
    [self.videoItem release];
self.videoItem = [[VideoItem alloc] initWithVideoItem:item];

3) 第一次初始化数组:

NSArray *myRepository = [[NSUserDefaults standardUserDefaults] arrayForKey:@"kHistory"];
if(myRepository) { 
    for(NSData *data in myRepository) {
        VideoItem *video = (VideoItem*)[NSKeyedUnarchiver unarchiveObjectWithData:data];
        [self.historyArray addObject:video];
    }
}

有什么建议可以解决问题吗?

由于这是一个可变数组,它可以在迭代过程中被清除,导致恰好在报告的行发生崩溃(因为之前的条件只是为真,所以即使悬空指针也可以通过,而且它是无意义的)。

这是可能的解决方案

-(NSString*)getStringForVideoArray {
    NSString *str = nil;

    int seconds = 0;

    NSArray *tmp = [NSArray arrayWithArray:self]; // shallow copy - fast
    for (NSObject *video in tmp) {
        if ([video isKindOfClass:[VideoItem class]]) {
            VideoItem *tmp = (VideoItem*)video;
            seconds += tmp.seconds;
        }
    }

    ... // all below with no changes
}