Swift AnyObject - приведение массива протоколов к [AnyObject]

Как вы понижаете массив экземпляров протокола в AnyObjects? Я попробовал некоторые из более разумных идей в примере кода ниже.

protocol Nameable : class {
    var name: String { get }
}

class Person: Nameable {
    var name: String

    init(name: String)
    {
        self.name = name
    }
}

class Example {

    func setArray(array: [AnyObject]?, forKey: String)
    {
        print("hello world")
    }
}

var personOne = Person(name: "Evan")
var personTwo = Person(name: "Brian")

var array: [ Nameable ] = [ personOne, personTwo ]

var anotherArray = array.map({ $0 as AnyObject })    // OMG gross!
var yetAnotherArray = array as [ AnyObject ]         // Nope.
var evenYetAnotherArray = array as? [ AnyObject ]    // Nope.
var omgThisIsAnArray = Array<AnyObject>(array)       // Ha ha, srsly. Nope.

var myExample = Example()
myExample.setArray(anotherArray, forKey: "Named")

Для чего это стоит, setArray(_ anArray: [AnyObject]?, forKey aKey: String) Метод подписи исходит от Apple NSUbiquitousKeyValueStore класс, так что я не могу по-настоящему изменить его, чтобы быть безопасным для типов.

2 ответа

Решение

Это менее чем идеально, но это работает, если протокол и класс оба @objc (и подклассы класса NSObject):

@objc protocol Nameable: class {
    var name: String { get }
}

@objc class Person: NSObject, Nameable {
    var name: String
    init(name: String) {
        self.name = name
    }
}

...

var array: [Nameable] = [personOne, personTwo]
let array2 = array as [AnyObject] // ✓

Это не дает прямого ответа на ваш вопрос, но я не думаю, что это сработает так, как вы ожидаете.

Из документов для NSUbiquitousKeyValueStore setArray:

Массив, содержимое которого может быть сохранено в формате списка свойств. Другими словами, объекты в массиве должны иметь типы NSNumber, NSString, NSDate, NSData, NSArray или NSDictionary. Общий размер (в байтах) массива и его содержимого не должен превышать ограничения на размер ключа.

Вы пытаетесь вставить данные, которых нет в любом из вышеперечисленных, и я предполагаю, что у вас возникнут проблемы.

Примерно так будет работать:

import UIKit // For String<->NSString bridging

protocol Nameable : class  {
    var name: String { get }
}

class Person: Nameable {
    var name: String

    init(name: String)
    {
        self.name = name
    }
}

class Example {

    func setArray(array: [AnyObject]?, forKey: String)
    {
        print("hello world")
    }
}

var personOne = Person(name: "Evan")
var personTwo = Person(name: "Brian")

var array: [ Nameable ] = [ personOne, personTwo ]

var nameArray = array.map({ $0.name }) // Now [String]

var myExample = Example()
myExample.setArray(nameArray, forKey: "Named")

Или вы можете сериализовать ваши объекты Swift другим способом, чтобы поместить их в один из поддерживаемых классов.

Другие вопросы по тегам