问题
By convention, each Cocoa and Core Foundation object listed in Table 2-1 is called a property-list object.
So, does this protocol (known as PropertyListObject
in the code below) exist, or do we need to make our own? If we do need to make our own, has someone made a definitive one?
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 { }
Use case:
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) }
}
}
More reading: https://github.com/apple/swift-evolution/blob/master/proposals/0139-bridge-nsnumber-and-nsvalue.md
来源:https://stackoverflow.com/questions/61333470/is-there-a-protocol-for-all-property-list-objects