iOS 開發(fā)之避坑指南 (不定期更新)<Fatal error: Index out of range>

最近在用 Swift 寫自己的新項目 Fontzar, 擼了個遍歷時移除不符合條件的值的碼然后 build and run, 崩了!沒錯是崩了!報了個Fatal error: Index out of range

var arr = ["a","c","a"]

for (idx, value) in arr.enumerated() {
    if value == "a" {
        arr.remove(at: idx)
    }
}

print(arr)

同樣代碼用 OC 寫不會蹦???!

NSMutableArray *arr = @[@"a",@"c",@"a"].mutableCopy;

[arr enumerateObjectsUsingBlock:^(NSString* str, NSUInteger idx, BOOL * _Nonnull stop) {
    if ([str isEqualToString:@"a"]) {
        [arr removeObjectAtIndex:idx];
    }
}];

NSLog(@"%@", tempMArr);

我覺得在 Swift 中崩潰是因為 Swift 是安全的,讓我們提前發(fā)現(xiàn)了問題。

Swift的特點: 快速 現(xiàn)代 安全 互動

注意: 遍歷中不能直接操控原數(shù)組,因為這會改變數(shù)組長度導(dǎo)然后導(dǎo)致隱藏 Bug,你檢查錯誤都不知哪出問題了(請看下面的代碼)。

NSMutableArray *tempMArr = @[@"a",@"x",@"d",@"c",@"a",@"j",@"a",@"c",@"a",@"k",@"f"].mutableCopy;
NSArray *tempArr = @[@"a",@"b",@"c"];

[tempMArr enumerateObjectsUsingBlock:^(NSString* str, NSUInteger idx, BOOL * _Nonnull stop) {
    
    BOOL isExisted = NO;
    
    for (NSString *str2 in tempArr) {
        if ([str isEqualToString:str2]) {
            isExisted = YES;
            break;
        }
    }
    
    if (!isExisted) {
        [tempMArr removeObjectAtIndex:idx];
    }
}];
    
NSLog(@"tempMArr:%@", tempMArr);

控制臺打印出的結(jié)果:

tempMArr:(
    a,
    d,
    c,
    a,
    a,
    c,
    a,
    f
)

從打印出來的結(jié)果我們發(fā)現(xiàn)數(shù)組中多了 fd,這結(jié)果是不符合我們預(yù)期。從而證明了遍歷中不能操作原數(shù)組的真理!

正確姿勢:

  • 遍歷中把符合條件的值保存在新的數(shù)組里
  • 遍歷拷貝的數(shù)組,操作原數(shù)組
  • 倒序遍歷數(shù)組
  • 使用 Filter 函數(shù)filter(_:) Or filteredArrayUsingPredicate:

PS: 如果你用 Swift 開發(fā)時遇到了這個問題,可能是因為你用 OC 時這么玩過,或者是你曾經(jīng)所看過的《iOS 中如何遍歷數(shù)組?》系列的 Blog 本身就有問題,誤導(dǎo)你了或沒提醒你。提醒一下 除了 OC 以外的編程語言中就算允許你遍歷中操作原數(shù)組(不崩潰)也全力避免這種騷操作。最后記得審一下你的 OC 代碼 ??

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容