简体   繁体   中英

Extending typed Arrays (of primitive types like Bool) in Swift 3?

Previously in Swift 2.2 I'm able to do:

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

which extends [Bool] with .allTrue . Eg

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

But in Swift 3.0 I'm getting this error:

undeclared type _ArrayType


So I tried switching it to Array and using the new keyword Iterator

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

But I got a different error complaining that I'm forcing element to be non-generic

Same-type requirement makes generic parameter 'Element' non-generic


I've also tried the solutions in this 2 years old post but to no avail.

So how does one extend arrays of primitive types like Bool in Swift 3?

Just extend the Collection or the Sequence

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

edit/update:

Xcode 10 • Swift 4 or later

You can use Swift 4 or later collection method allSatisfy

let alltrue = [true, true,true, true,true, true].allSatisfy{$0}  // true

let allfalse = [false, false,false, false,false, false].allSatisfy{!$0} // true

extension Collection where Element == Bool {
    var allTrue: Bool { return allSatisfy{ $0 } }
    var allFalse: Bool { return allSatisfy{ !$0 } }
}

Testing Playground:

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

Apple replaced _ArrayType with _ArrayProtocol in Swift 3.0 ( see Apple's Swift source code on GitHub ) so you can do the same thing you did in Swift 2.2 by doing the following:

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

As of Swift 3.1 (included in Xcode 8.3), you can now extend a type with a concrete constraint :

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

You can also extend Collection instead of Array , but you'll need to constrain Iterator.Element , not just Element .

Extending _ArrayProtocol or Collection didn't work for me but Sequence did.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM