2016-07-12 10 views
0

Ich habe ein Array von EKReminder, etwa so:Casting Array von Objekten Reihe von subclassed Objekte in Swift

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

ich dieses Array in ein Array von Subklassen von EKReminder werfen wollen. Lassen Sie uns sagen, dass dies die Unterklasse ist:

import Foundation 
import EventKit 

class NNReminder: EKReminder { 
    var additionalNotes: String? 
} 

Wie würde ich werfen currentReminders auf [NNReminder]? Ich habe es auf verschiedene Arten versucht, aber alle haben versagt.

+0

Wenn Sie versucht haben, was war die Fehlermeldung, die Sie erhalten haben? –

Antwort

2

Vorausgesetzt, Sie sicher sind, dass alle Mitglieder von currentReminders sind in der Tat, NNReminder s, können Sie sie alle wie diese werfen können:

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

Edit: Wenn nur einige der Erinnerungen sind vom Typ NNReminder oder sind Sie von dem Inhalt des Arrays nicht sicher, können Sie flatMap verwenden, um die Null-Werte zu entfernen:

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

Wenn Sie fragen, wie Sie ein paar obje zu verwandeln cts, die als EKReminder initialisiert wurden, sollten Sie eine benutzerdefinierte init in NNReminder schreiben, die eine EKReminder nimmt, und diese init in der obigen Kartenmethode verwenden.

+3

Beachten Sie, dass erzwungene Umwandlungen vermieden werden sollten, da sie dazu neigen, crashen – Cristik

+1

@Cristik yep zu erzeugen, weshalb ich erwähnte, dass er sicher sein sollte, dass die Besetzung gemacht werden kann (dh er initialisierte das Array selbst mit 'NNReminder's früher). In einer sichereren Operation obwohl redigiert. – Connor

+1

Danke Connor! Das hat geholfen. :) – mactunes

0

Ich war es leid, kryptische .map Klauseln über meinen Code so schrieb ich eine kleine Erweiterung Dinge ordentlich zu machen:

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

Beispiel:

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! 

HINWEIS :
Die Cast-Methode unterstützt auch Protokolle

+1

Sie können den Parameter auch auf die Cast-Funktion optional mit einem Standardwert von 'nil' setzen und er wird den richtigen Typ ableiten, so dass Sie 'B.self' nicht passieren müssen. – dan

+0

Macht es noch schöner! Netter Fang "dan". Funktioniert tadellos im Spielplatz, testete es sogar mit einem Protokoll, um sicher zu sein. Ich habe das Codebeispiel aktualisiert, um Ihrem Vorschlag zu entsprechen. – eonist

Verwandte Themen