Расширение типизированных массивов (таких примитивных типов, как Bool) в Swift 3?

Раньше в Swift 2.2 я мог:

extension _ArrayType where Generator.Element == Bool{
    var allTrue : Bool{
        return !self.contains(false)
    }
}

который продолжается [Bool] с помощью .allTrue. Например.

[true, true, false].allTrue == false

Но в Swift 3.0 я получаю эту ошибку:

необъявленный тип _ArrayType


Поэтому я попытался переключить его на Array и используя новое ключевое слово Iterator

extension Array where Iterator.Element == Bool
    var allTrue : Bool{
        return !self.contains(false)
    }
}

Но у меня другая ошибка, жалующаяся на то, что я заставляю элемент быть не общим

Требование к одному типу делает общий параметр "Элемент" не общим


Я также пробовал решения на этом 2-летнем посту, но безрезультатно.

Итак, как можно расширить массивы примитивных типов, таких как Bool в Swift 3?

Ответ 1

Просто добавьте коллекцию или последовательность

extension Collection where Iterator.Element == Bool { 
    var allTrue: Bool { return !contains(false) }
}

Тестирование игровой площадки:

[true, true,true, true,true, true].allTrue // true
[true, true,false, true,true, true].allTrue // false

Другой вариант - создать собственный протокол и расширить его:

protocol BoolConvertible {
    var bool: Bool { get }
}
extension Bool: BoolConvertible {
    var bool: Bool { return self }
}

extension Array where Element: BoolConvertible {
    var allTrue: Bool { return !contains{!$0.bool} }
}

Ответ 2

Apple заменила _ArrayType на _ArrayProtocol в Swift 3.0 (см. исходный код Apple Swift на GitHub), чтобы вы могли сделать то же самое вы сделали в Swift 2.2, выполнив следующие действия:

extension _ArrayProtocol where Iterator.Element == Bool {
    var allTrue : Bool { return !self.contains(false) }
}

Ответ 3

Начиная с Swift 3.1 (включенного в Xcode 8.3), теперь вы можете расширить тип с конкретным ограничением:

extension Array where Element == Bool {
    var allTrue: Bool {
        return !contains(false)
    }
}

Вы также можете расширить Collection вместо Array, но вам нужно ограничить Iterator.Element, а не только Element.

Ответ 4

Расширение _ArrayProtocol или Collection не работает для меня, но Sequence сделал.

public extension Sequence where Iterator.Element == String
{
    var allTrue: Bool { return !contains(false)
}