Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift: Extend Optional Array

I'd like to extend Optional, where Wrapped is an array (with elements of any type). In other words, I want to add a function to [Any]?. I'm just not sure how to declare that. I've tried:

1.

extension Optional where Wrapped: Array

results in:

error: reference to generic type 'Array' requires arguments in <...>

2.

extension Optional where Wrapped: Array<Any>

results in:

type 'Wrapped' constrained to non-protocol type 'Array<Any>'

and various other similar declarations. Help is appreciated.

like image 880
Connor Neville Avatar asked Nov 04 '16 16:11

Connor Neville


3 Answers

Yes the problem here is that in this line,

extension Optional where Wrapped: Array<Any>

the 'Array' should be a protocol, in a more general way :

extension Type where Element: Protocol 

The solution I got is ugly but works, consider this:

protocol ArrayOfAny {}
struct ArrayAny<Element: Any>: ArrayOfAny {
    let array: [Element]
    init(_ array: [Element]) {
        self.array = array
    }
}    

Because this:

extension Array: ArrayOfAny where Element: Any {}

is not supported...

then you can just do this:

extension Optional where Wrapped: ArrayOfAny

Hope it helps :)

like image 31
Stormsyders Avatar answered Nov 19 '22 17:11

Stormsyders


I am kinda late, but maybe I can help.

In swift 4, you can do this

extension Optional where Wrapped: Collection {

If you need to access the Element type of the array you can do:

Wrapped.Iterator.Element

like image 148
Tiago Almeida Avatar answered Nov 19 '22 15:11

Tiago Almeida


A bit late to the party but it still might help future readers. Using Wrapped RangeReplaceableCollection to support strings as well:


extension Optional where Wrapped: RangeReplaceableCollection {
    mutating func append(_ element: Wrapped.Element) {
        self = (self ?? .init()) + CollectionOfOne(element)
    }
    mutating func append<S: Sequence>(contentsOf sequence: S) where S.Element == Wrapped.Element {
        self = (self ?? .init()) + sequence
    }
}

var optionalString: String?
optionalString.append("a")
optionalString  //  "a"
optionalString.append(contentsOf: "bc")
optionalString  //  "abc"
optionalString.append(contentsOf: ["d", "e"])
optionalString  //  "abcde"
var optionalArray: [Int]?
optionalArray.append(1)
optionalArray  //  [1]
optionalArray.append(contentsOf: [2,3])
optionalArray  //  [2,3]
like image 34
Leo Dabus Avatar answered Nov 19 '22 16:11

Leo Dabus