2015-11-05 4 views
2

У меня есть несколько словарей, которые типы:Сделать Swift (2.1) перечисления соответствует AnyObject

public typealias RESTPostDictionary = [RESTPostDictionaryKey : AnyObject] 
public typealias RESTRequestDictionary = [RESTRequestDictionaryKey : AnyObject] 

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

public enum RESTPostDictionaryKey : String 
{ 
    case Requests = "requests" 
} 

И:

public enum RESTRequestDictionaryKey : String 
{ 
    case RequestURI = "request_uri" 
    case HTTPMethod = "http_method" 
    case DataDictionary = "data_dictionary" 
    case RequestIdentifier = "request_identifier" 
    case ResponseFormats = "response_formats" 
} 

Поскольку мое перечисление технически String типа, я бы-е должно было бы быть проблемой для компилятора, чтобы получить его базовое строковое значение (которое соответствует AnyObject) и использовать это. Но я получаю предупреждение:

Cannot assign value of type ‘Array<RESTRequestDictionary>’ aka … to type 'AnyObject?’

в следующей функции:

class public func postDictionaryWithRequestDictionaries(requestDictionaries: Array<RESTRequestDictionary>) -> RESTPostDictionary 
{ 
    var postDictionary = RESTPostDictionary() 

    postDictionary[.Requests] = requestDictionaries 

    return postDictionary 
} 

Есть ли способ сказать компилятору, чтобы получить его String посредством использования протокола или что-то другое, не имея полагаться на грязный и не-Swift-подобный .rawValue?

Или я делаю что-то неправильно?

+0

Почему вы ограничивающий словарь содержать только объекты? Если вам не нужны только объекты, вы можете просто изменить 'AnyObject' на' Any' – Kametrixom

+0

Я не знал о 'Any', но когда я использую' Any', я тогда не могу использовать словарь в качестве словаря, например, я использую метод 'NSJSONSerialization.dataWithJSONObject (postDictionary, options: [])' и получает ошибку, которая '' RESTPostDictionary 'не соответствует ожидаемому типу' AnyObject'' –

+0

О, да, в этом случае вам нужно использовать объекты, Obj-C ничего не может обработать – Kametrixom

ответ

3

Это не правильно:

public typealias RESTPostDictionary = [RESTPostDictionaryKey : AnyObject] 

Что вы имеете в виду это:

public typealias RESTPostDictionary = [String : AnyObject] 

Перечисление не строка. Но это строка, которую вы намереваетесь использовать в качестве ключа.

При использовании случай перечисления в качестве ключа, возьмите его rawValue:

postDictionary[RESTRequestDictionaryKey.Requests.rawValue] = requestDictionaries 

Так, например, это законно:

enum Keys : String { 
    case Key1 = "hey" 
    case Key2 = "ho" 
    case Key3 = "hey nonny no" 
} 

var d = [String:AnyObject]() 
d[Keys.Key1.rawValue] = 1 
d[Keys.Key2.rawValue] = 2 
+0

Я понимаю вашу точку зрения, но я бы хотел, чтобы мой 'RESTPostDictionary' использовал только ключи, которые находятся в переписке' RESTPostDictionaryKey'. Я уверен, что это должно работать, поскольку перечисление технически является строковым типом, который соответствует «AnyObject»? –

+0

Вы не понимаете мою точку зрения, потому что моя точка зрения заключается в том, что перечисление не является технически строкой. Это технически переименование, которое является совсем другим животным. – matt

+0

Хорошо, так что нет способа сообщить компилятору, кроме свойства 'rawValue'? –

0

почему бы не просто использовать перечисление в качестве ключа?

import Foundation 

enum E:String, CustomStringConvertible { 
    var description: String { return self.rawValue } 
    case A = "text A" 
    case B = "B text" 
    case C = "neither A nor B but C" 
} 

var dict: Dictionary<E, Any> = [:] 
dict[E.A] = "alfa" 
dict[E.B] = 1 
dict[E.C] = NSDate() 

dump(dict) 

/* 
▿ 3 key/value pairs 
▿ [0]: (2 elements) 
- .0: E.C 
- .1: Nov 8, 2015, 11:01 AM 
▿ [1]: (2 elements) 
- .0: E.A 
- .1: alfa 
▿ [2]: (2 elements) 
- .0: E.B 
- .1: 1 
*/ 

print(dict) 
// [neither A nor B but C: 2015-11-08 10:02:47 +0000, text A: "alfa", B text: 1] 

Объект, который может быть преобразован в формат JSON должен обладать следующими свойствами :

Объект верхнего уровня является NSArray или NSDictionary.

Все объекты являются экземплярами NSString, NSNumber, NSArray, NSDictionary, или NSNull.

Все словарные ключи являются экземплярами NSString.

Номера не NaN или бесконечность.

import Foundation 

enum E:String, CustomStringConvertible { 
    var description: String { return self.rawValue } 
    case A = "key A" 
    case B = "key B" 
    case C = "key C" 
} 

var dict: Dictionary<NSString, AnyObject> = [:] 

dict[E.A.description] = "alfa" 
dict[E.B.description] = [1,2,3] 
dict[E.C.description] = NSDate() 

dict is AnyObject // false 
let nsdict = dict as NSDictionary 
nsdict is AnyObject // true 
print(nsdict) 

/* 

{ 
    "key A" = alfa; 
    "key B" =  (
     1, 
     2, 
     3 
    ); 
    "key C" = "2015-11-09 23:13:31 +0000"; 
} 
*/ 
+0

Спасибо за идею, но компилятор мне сказал, что этот тип не соответствует 'AnyObject' при использовании его с классом' NSJSONSerialization' –

+0

. способ записи расширения, чтобы мой пользовательский тип '[StringBasedEnum: AnyObject]' соответствовал типу Swift 'AnyObject'? –

+0

теперь я вижу ответ Маттов. поэтому вы все знаете ... enum - это перечисление, а не строка. хотя ключ в NSDictionary является NSString, вы можете сравнить его с вашими перечислениями. enum со связанным строковым значением работает как ограниченный набор строковых значений. Я использую значения enum, соответствующие Streamable, как мой персонал JSON. сериализация в JSON проста и быстра, я использую свой собственный синтаксический анализатор с прямым отображением на мои совместимые с Json перечисления. все зависит от ваших потребностей, в Интернете много примеров – user3441734

0
class Box<T> { 
    let value: T 
    init(value: T) { 
    self.value = value 
    } 
} 
NSNotificationCenter.defaultCenter().postNotificationName("foo", object: Box(value: YourOwnStruct())) // OK 

Вы можете отдать свой STRUCT/каталог перечислимую, если реализовать AnyObjectConvertible в этом типе.

extension YourOwnStruct: AnyObjectConvertible {} 

NSNotificationCenter.defaultCenter().postNotificationName("foo", object: YourOwnStruct()) // OK let value = notification.object as? YourOwnStruct 

Посмотреть полный ответ/источник загрузки из here