Подтвердить что ты не робот

Swift 2.1. Сортировка ошибок на месте, только при выпуске

Я начал получать отчеты о сбоях для сортировки lamdba в приведенном ниже коде, третья строка в сером поле ниже:

private func fixOverlaps(inout blocks: [TimeBlock], maxOverlaps: Int? = nil) {
    blocks.sortInPlace { a,b in
        if a.startTime < b.startTime {
            return true
        } else if a.startTime == b.startTime && a.endTime < b.endTime {
            return true
        }
        return false
    }
...

Обратите внимание, что при сборе от XCode сбоя не возникает. Только архивы App Store и Ad Hoc будут разбиваться, и только когда длина списка блоков будет в сотнях.

Я изменил код на это, и проблема исчезла:

private func fixOverlaps(inout blocks: [TimeBlock], maxOverlaps: Int? = nil) {
    blocks = blocks.sort { a,b in
        if a.startTime < b.startTime {
            return true
        } else if a.startTime == b.startTime && a.endTime < b.endTime {
            return true
        }
        return false
    }
...

Есть ли что-то, что я пропустил о том, как использовать inout или sortInPlace? Я могу попытаться сделать это. Это на нескольких версиях iOS (8/9) и Swift 2.1.

ИЗМЕНИТЬ --------------------

Хорошо здесь минимальная версия, которая сбой. Оказывается, внутри входила красная селедка. Если вы запустите новый проект с одним представлением в XCode 7.1, вы можете заменить контроллер вида следующим:

class ViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    var blocks = [TimeBlock]()
    for var i in 0...20 { //Works if you put in a small number like 8
        let t = TimeBlock()
        t.start = Int(arc4random_uniform(1000)) //Get some random numbers so the sort has to do some work
        t.end = Int(arc4random_uniform(1000))
        blocks.append(t)
    }

    blocks.sortInPlace { a,b in
        if a.start > b.start {
            return true
        }
        return false
    }

    print("done") //Gets here on debug, not release
}

class TimeBlock {
    var start = 0
    var end = 0
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


}

Итак, запустите его в выпуске, и вы увидите, что он печатает "Готово", если вы закончите цикл около 17, но сработает с 20. Точное число может отличаться для вас.

4b9b3361

Ответ 1

Этот код выглядит правильно. Похоже, вы столкнулись с ошибкой в ​​компиляторе, что, как правило, имеет место, когда у вас есть авария в конфигурации выпуска, но не отладка. Возможно, вы можете убедиться в этом, включив оптимизации в сборку и тестирование отладки, чтобы определить, создает ли она проблему. Помимо вашего обходного пути, единственное, что вам нужно сделать, это записать ошибку.

Ответ 2

Работала над этим без потери функциональности, используя self.list = self.list.sort() вместо self.list.sortInPlace().

Ответ 3

Это ошибка в Xcode 7.1. Превращение быстрого уровня оптимизации компилятора из быстродействия, чтобы никто не исправил эту проблему для меня.

Ответ 4

Я зарегистрировал ошибку на bugs.swift.org об этом ранее сегодня и получил быстрый ответ от одного из разработчиков, что это действительно проблема с Xcode 7.1. Он отметил, что его резолюция изложена в Примечания к выпуску Xcode 7.2:

Исправлена ​​ошибка в оптимизаторе, которая приводила к сбою на месте сортировки по изменяемым коллекциям. (23081349)

Поэтому использование Xcode 7.2 для компиляции также должно устранить проблему.