是否有针对所有属性列表对象的协议?

时间:2020-04-20 23:03:00

标签: ios swift nsuserdefaults

按照惯例,Table 2-1中列出的每个Cocoa和Core Foundation对象都称为属性列表对象。

那么,这个协议(在下面的代码中称为PropertyListObject)是否存在,还是我们需要自己制定?如果我们确实需要自己做,那么有人确定了吗?

public protocol UserDefaults_Value_WrappedValue {
  associatedtype PropertyListObject: HM.PropertyListObject
  init?(propertyListObject: Any)
  var convertertedToPropertyListObject: PropertyListObject { get }
}

public protocol PropertyListObject: UserDefaults_Value_WrappedValue
where PropertyListObject == Self { }

public extension PropertyListObject {
  init?(propertyListObject: Any) {
    guard let object = propertyListObject as? Self
    else { return nil }

    self = object
  }

  var convertertedToPropertyListObject: Self { self }
}

extension Bool: PropertyListObject { }
extension Data: PropertyListObject { }
extension Date: PropertyListObject { }
extension String: PropertyListObject { }
extension URL: PropertyListObject { }

extension Int: PropertyListObject { }
extension Int8: PropertyListObject { }
extension Int16: PropertyListObject { }
extension Int32: PropertyListObject { }
extension Int64: PropertyListObject { }
extension UInt: PropertyListObject { }
extension UInt8: PropertyListObject { }
extension UInt16: PropertyListObject { }
extension UInt32: PropertyListObject { }
extension UInt64: PropertyListObject { }
extension Float: PropertyListObject { }
extension Double: PropertyListObject { }

extension Array: PropertyListObject & UserDefaults_Value_WrappedValue
where Element: HM.PropertyListObject {
  public typealias PropertyListObject = Self
}

extension Dictionary: UserDefaults_Value_WrappedValue
where Key: LosslessStringConvertible, Value: HM.PropertyListObject {
  public typealias PropertyListObject = PropertyListDictionary<Value>

  public init?(propertyListObject: Any) {
    guard let dictionary = propertyListObject as? PropertyListObject
    else { return nil }

    self.init(dictionary)
  }

  public var convertertedToPropertyListObject: PropertyListObject {
    .init(self)
  }
}

extension Dictionary: PropertyListObject
where Key == String, Value: HM.PropertyListObject { }

public typealias PropertyListDictionary<Value: PropertyListObject> = [String: Value]

import CoreGraphics
extension CGPoint: PropertyListObject { }
extension CGVector: PropertyListObject { }
extension CGSize: PropertyListObject { }
extension CGRect: PropertyListObject { }
extension CGAffineTransform: PropertyListObject { }

用例:

The value parameter can be only property list objects: NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary. For NSArray and NSDictionary objects, their contents must be property list objects.

final class UserDefaultsTestCase: XCTestCase {
  func test_subscript() {
    let key = "?"

    UserDefaults[key] = true
    XCTAssert(UserDefaults[key] == true)

    UserDefaults[key] = 9
    XCTAssertEqual(UserDefaults[key], 9)
  }

  func test_Dictionary() {
    let key = "?"

    UserDefaults[key] = Day.ta
    XCTAssertEqual(UserDefaults["?"], Day.ta)

    UserDefaults[key] = [1: "?", 2: "?"]
    XCTAssertEqual(UserDefaults["?"], Day.ta)

    UserDefaults.standard[key] = ["1": "?", "2": "?"]
    XCTAssertEqual(UserDefaults["?"], Day.ta)
  }

  func test_propertyWrapper() {
    struct Type {
      @UserDefaults.Value(key: "?") var dayta = Day.ta
    }

    var instance = Type()
    XCTAssertEqual(instance.dayta, Day.ta)
    instance.dayta = nil
    XCTAssertNil(instance.dayta)
  }
}

private enum Day: Int, LosslessStringConvertible {
  case sunday = 1, monday

  static let ta = [Day.sunday: "?", .monday: "?"]
}
public extension UserDefaults {
  @propertyWrapper struct Value<WrappedValue: UserDefaults_Value_WrappedValue> {
    public init(
      wrappedValue: WrappedValue?,
      key: String,
      defaults: UserDefaults = .standard
    ) {
      self.key = key
      self.defaults = defaults
      self.wrappedValue = wrappedValue
    }

    public var wrappedValue: WrappedValue? {
      get { defaults[key] }
      set { defaults[key] = newValue }
    }

    public let key: String
    private let defaults: UserDefaults
  }

  static subscript<Object: UserDefaults_Value_WrappedValue>(key: String) -> Object? {
    get { standard[key] }
    set { standard[key] = newValue }
  }

  subscript<Object: UserDefaults_Value_WrappedValue>(key: String) -> Object? {
    get { object(forKey: key).flatMap(Object.init)  }
    set { set(newValue?.convertertedToPropertyListObject, forKey: key) }
  }
}

更多阅读内容:https://github.com/apple/swift-evolution/blob/master/proposals/0139-bridge-nsnumber-and-nsvalue.md

0 个答案:

没有答案
相关问题