1

I have an array of EKReminder, like so:

var currentReminders: [EKReminder]? = ....

I want to cast this array to an array of subclasses of EKReminder. Let's say this is the subclass:

import Foundation
import EventKit

class NNReminder: EKReminder {
    var additionalNotes: String?
}

How would I cast currentReminders to [NNReminder]? I tried several ways but they all failed.

1
  • When you tried, what was the error message you received ? Commented Jul 12, 2016 at 18:08

2 Answers 2

3

Provided you are sure that all members of currentReminders are, in fact, NNReminders, you can cast them all like this:

currentReminders = currentReminders.map { $0 as! NNReminder }

Edit: if only some of the reminders are of type NNReminder, or you're not sure of the array's contents, you can use flatMap to remove the nil values:

currentReminders = currentReminders.flatMap { $0 as? NNReminder }

If you are asking how to transform a bunch of objects that were initialized as EKReminder, you should write a custom init in NNReminder that takes an EKReminder, and use this init in the above map method.

Sign up to request clarification or add additional context in comments.

4 Comments

Note that forced casts should be avoided as they tend to generate crashe
@Cristik yep, which is why I mentioned he should be sure the cast can be done (ie. he initialized the array himself with NNReminders earlier). Edited in a safer operation though.
Thanks Connor! That helped. :)
This is for down-cast Array's. If you want to up-cast then you can just use as! [ClassTypeHere]
0

I was tired of having cryptic .map clauses all over my code so i wrote a small extension to make things neat:

extension Array{
    func cast<T>(type:T.Type? = nil) -> [T]{
        return self.map { $0 as! T }
    }
}

Example:

class A:B{
    var value:String = "default"
    init(_ value:String){
        self.value = value
    }
}
class B{
    var someNum:CGFloat = 1
    init(){

    }
}
var arr1:Array<A> = [A("a"),A("b"),A("c")]
let arr2:Array<B> = arr1.cast(B.self)//neat!
let arr3:Array<B> = arr1.cast()//epic!

NOTE:
the cast method supports protocols as well

2 Comments

You can also make the parameter to the cast function optional with a default value of nil and it will infer the correct type so you don't have to pass B.self
Makes it even nicer! Nice catch "dan". Works flawlessly in playground, even tested it with a protocol just to be sure. I updated the code-example to reflect your suggestion.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.