Sweeper Sweeper - 6 months ago 13
Swift Question

Why can't I pass an array to a vararg in Swift?

I have this function:

func doStuff(stuff: Int...) {
print(stuff)
}


and I call it like this:

let array = [1, 2, 3]
doStuff(array)


And it does not compile!

I mean, this makes no sense, right? The function is supposed to accept a list of things, and I am giving it a list of things. How come this doesn't work?

Here's some background info (you can skip it)




I have this
NSManagedObject
subclass:

class Entry: NSManagedObject {

override init(entity: NSEntityDescription, insertIntoManagedObjectContext context: NSManagedObjectContext?) {
// irrelevent
}

convenience init(entity: NSEntityDescription, insertIntoManagedObjectContext context: NSManagedObjectContext, title: String, content: String, date: NSDate) {
// irrelevent
}
}

extension Entry {

@NSManaged var content: String?
@NSManaged var date: NSDate?
@NSManaged var title: String?

}


In one of my view controllers, I fetch all the
Entry
s in
viewDidLoad
and I stored the fetched stuff in a variable called
anyObjs
which is of type
[AnyObject]


I want to turn this
[AnyObject]
to a
[NSDate: Entry]
, where the keys are the values'
date
property. I want it this way in order to easily access an
Entry
using an
NSDate
.

So I tried the following:

let literal = anyObjs!.map { (($0 as! Entry).date!, $0 as! Entry) }
entries = [NSDate: Entry](dictionaryLiteral: literal)


And I found out that I can't pass a
[(NSDate, Entry)]
to
(NSDate, Entry)...
!




"That's easy" you might say, "just pass all the elements in the array as varargs using the subscript!"

doStuff(array[0], array[1], array[2])


But this doesn't work if I don't know how many items there are.

Another workaround that doesn't work is to create a function that accepts an array:

func doStuff(array: [Int]) {
print(array)
}


This doesn't work either because if I don't know the exact implementation of the function, I cannot rewrite it in the new function.

What can I do?

Answer

You are right! There ought to be a method for getting a dictionary from an array of tuples.

extension Dictionary {
    init(tuples: [Element]) {
        self.init()

        for (key, value) in tuples {
            self.updateValue(value, forKey: key)
        }
    }
}

OK, now that's done, let's see.

let tuples = anyObjs!.map { (($0 as! Entry).date!, $0 as! Entry) }
let entries = [NSDate: Entry](tuples: tuples)

Or combine the two lines

let entries = [NSDate: Entry](tuples: anyObjs!.map { (($0 as! Entry).date!, $0 as! Entry) })