【问题标题】:Make a Swift (2.1) enum conform to AnyObject使 Swift (2.1) 枚举符合 AnyObject
【发布时间】:2016-02-06 14:48:01
【问题描述】:

我有一些类型的字典:

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?

还是我做错了什么?

【问题讨论】:

  • 为什么限制字典只包含对象?如果你不只需要对象,你可以把AnyObject改成Any
  • 我不知道Any,但是当我使用Any时,我不能将字典用作字典,例如我使用方法NSJSONSerialization.dataWithJSONObject(postDictionary, options: [])并得到错误那’RESTPostDictionary’ does not conform to expected type ‘AnyObject’
  • 哦是的,在那种情况下你必须使用对象,Obj-C 不能处理其他任何东西

标签: swift enums swift2.1


【解决方案1】:

这是不正确的:

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

【讨论】:

  • 我理解你的意思,但我希望我的RESTPostDictionary 只使用RESTPostDictionaryKey 枚举中的键。我的观点是肯定这应该有效,因为枚举在技术上是一个 String 类型,它确实符合 AnyObject?
  • 实际上你不明白我的意思,因为我的意思是枚举在技术上是不是字符串。从技术上讲,它是一个枚举,是一种非常不同的动物。
  • 好吧,除了rawValue属性,没有办法告诉编译器了吗?
  • 我已将我的枚举改回为每个键都有静态常量的结构。不过感谢您的帮助
  • 我没有在任何地方尝试过你,我很感谢你的帮助,但我的想法没有奏效让我很失望。
【解决方案2】:
class Box<T> {
  let value: T
  init(value: T) {
    self.value = value
  }
}
NSNotificationCenter.defaultCenter().postNotificationName("foo", object: Box(value: YourOwnStruct())) // OK

如果以该类型实现 AnyObjectConvertible,您可以转换您的 struct/enum 目录。

extension YourOwnStruct: AnyObjectConvertible {}

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

here查看完整的答案/下载源

【讨论】:

    【解决方案3】:

    为什么不简单地使用枚举作为键?

    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";
    }
    */
    

    【讨论】:

    • 感谢您的想法,但编译器告诉我,在将其与 NSJSONSerialization 类一起使用时,此类型不符合 AnyObject
    • 有没有办法写一个扩展来让我的自定义类型[StringBasedEnum : AnyObject]符合AnyObject的Swift类型?
    • 现在我看到了 Matts 的回答。所以,你什么都知道……枚举是枚举,而不是字符串。即使 NSDictionary 中的键是 NSString,您也可以将它与您的枚举进行比较。具有关联字符串值的枚举就像一组有限的字符串值。我使用符合 Streamable 的枚举值作为我的 JSON 'staff'。序列化为 JSON 既简单又快速,我使用自己的解析器直接映射到我的 Json 兼容枚举。一切都取决于您的需求,网络上有很多示例
    猜你喜欢
    • 1970-01-01
    • 2014-07-23
    • 2015-06-29
    • 1970-01-01
    • 2020-10-19
    • 2014-08-25
    • 1970-01-01
    • 2015-04-12
    相关资源
    最近更新 更多