2016-07-12 2 views
0

У меня есть массив EKReminder, например, так:Кастинг массив объектов в массив подклассы объектов в Swift

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

Я хочу, чтобы бросить этот массив в массив подклассов EKReminder. Скажем, это подкласс:

import Foundation 
import EventKit 

class NNReminder: EKReminder { 
    var additionalNotes: String? 
} 

Как бы я бросил currentReminders на [NNReminder]? Я попробовал несколько способов, но все они потерпели неудачу.

+0

Когда вы попытались, какое сообщение об ошибке вы получили? –

ответ

2

При условии, вы уверены, что все члены currentReminders, на самом деле, NNReminder s, вы можете бросить их все так:

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

Edit: если только некоторые из напоминаний имеют тип NNReminder или вы не уверены содержимого массива, вы можете использовать flatMap удалить нулевые значения:

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

Если вы спрашиваете, как превратить кучу OBJE cts, которые были инициализированы как EKReminder, вы должны написать обычай init в NNReminder, который принимает EKReminder и использует этот init в приведенном выше методе карты.

+3

Обратите внимание, что принудительных следов следует избегать, поскольку они имеют тенденцию генерировать crashe – Cristik

+1

@Cristik yep, поэтому я упомянул, что он должен быть уверен, что приведение может быть выполнено (т. Е. Он инициализировал массив самостоятельно с помощью 'NNReminder' раньше). Тем не менее, отредактировано в более безопасной операции. – Connor

+1

Спасибо, Коннор! Это помогло. :) – mactunes

0

Я устал от того, загадочные .map положения во всем моем коде, так что я написал небольшое расширение, чтобы сделать вещи аккуратные:

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

Пример:

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! 

ПРИМЕЧАНИЕ :
метод литья также поддерживает протоколы

+1

Вы также можете сделать параметр для функции трансляции опциональным со значением по умолчанию 'nil', и он выведет правильный тип, чтобы вам не пришлось пропускать' B.self' – dan

+0

Делает его еще приятнее! Хороший улов «дан». Работает безупречно на детской площадке, даже проверял ее с протоколом, чтобы быть уверенным. Я обновил код-пример, чтобы отразить ваше предложение. – eonist

Смежные вопросы