onmyway133 / notes

:notebook_with_decorative_cover: Issues and solutions I found during development, mostly iOS
https://onmyway133.com/
MIT License
62 stars 4 forks source link

Swift wrapper around NSUserDefaults #153

Open onmyway133 opened 8 years ago

onmyway133 commented 8 years ago
public extension NSUserDefaults {

  public func get<T>(key: String) -> T? {
    switch T.self {
    case is Bool.Type:
      return boolForKey(key) as? T
    case is Int.Type:
      return integerForKey(key) as? T
    case is Double.Type:
      return doubleForKey(key) as? T
    case is Float.Type:
      return floatForKey(key) as? T
    case is String.Type:
      return stringForKey(key) as? T
    case is NSURL.Type:
      return URLForKey(key) as? T
    case is NSObject.Type:
      return valueForKey(key) as? T
    default:
      return nil
    }
  }

  public func set<T>(key: String, value: T) {
    switch value {
    case is Bool:
      setBool(value as! Bool, forKey: key)
    case is Int:
      setInteger(value as! Int, forKey: key)
    case is Double:
      setDouble(value as! Double, forKey: key)
    case is Float:
      setFloat(value as! Float, forKey: key)
    case is String:
      setObject(value as? String, forKey: key)
    case is NSURL:
      setURL(value as? NSURL, forKey: key)
    case is NSObject:
      setObject(value as? AnyObject, forKey: key)
    default:
      break
    }
  }
}
onmyway133 commented 8 years ago
func test() {
    let defaults = NSUserDefaults.standardUserDefaults()

    defaults.set("bool", value: true)
    XCTAssertEqual(defaults.get("bool"), true)

    defaults.set("int", value: 10)
    XCTAssertEqual(defaults.get("int"), 10)

    defaults.set("float", value: 15.0)
    XCTAssertEqual(defaults.get("float"), 15.0)

    defaults.set("double", value: 20.0)
    XCTAssertEqual(defaults.get("double"), 20.0)

    defaults.set("string", value: "hello")
    XCTAssertEqual(defaults.get("string"), "hello")

    defaults.set("array", value: [1, 2, 3])
    XCTAssertEqual(defaults.get("array"), [1, 2, 3])

    defaults.set("dictionary", value: ["one": 1, "two": 2])
    XCTAssertEqual(defaults.get("dictionary"), ["one": 1, "two": 2])

    defaults.set("url", value: NSURL(string: "http://www.google.com"))
    print(defaults.valueForKey("url"))
    XCTAssertEqual(defaults.get("url"), NSURL(string: "http://www.google.com"))

    defaults.set("date", value: NSDate(timeIntervalSince1970: 20))
    XCTAssertEqual(defaults.get("date"), NSDate(timeIntervalSince1970: 20))

    defaults.set("none", value: UIColor.redColor())
//    XCTAssertEqual(defaults.get("none"), nil as AnyObject)
  }
onmyway133 commented 8 years ago
public extension NSUserDefaults {

  func get<T: NSDataConvertible>(key: String) -> T? {
    guard let data = objectForKey(key) as? NSData else { return nil }

    return T.fromData(data) as? T
  }

  func set<T: NSDataConvertible>(key: String, value: T?) {
    guard let value = value else {
      removeObjectForKey(key)
      return
    }

    guard let data = value.toData else { return }

    setObject(data, forKey: key)
  }

  func exists(key: String) -> Bool {
    return valueForKey(key) != nil
  }
}
onmyway133 commented 8 years ago
public protocol NSDataConvertible {
  associatedtype T

  static func fromData(data: NSData) -> T?
  var toData: NSData? { get }
}

extension NSData: NSDataConvertible {

  public typealias T = NSData

  public static func fromData(data: NSData) -> T? {
    return data
  }

  public var toData: NSData? {
    return self
  }
}

extension Bool: NSDataConvertible {

  public typealias T = Bool

  public static func fromData(data: NSData) -> T? {
    return NSKeyedUnarchiver.unarchiveObjectWithData(data) as? Bool
  }

  public var toData: NSData? {
    return NSKeyedArchiver.archivedDataWithRootObject(self)
  }
}
onmyway133 commented 8 years ago
onmyway133 commented 8 years ago

subscript

public extension NSUserDefaults {

  subscript(key: String) -> String {
    return "string"
  }

  subscript(key: Int) -> Int {
    return 1
  }
}
onmyway133 commented 8 years ago

subscript with generic

public struct Key<T> {
  let value: T
}

public extension NSUserDefaults {

  subscript(key: Key<String>) -> String {
    return ""
  }

  subscript(key: Key<String>) -> Int {
    return 1
  }

  subscript(key: Key<Int>) -> String {
    return "int"
  }
}
onmyway133 commented 8 years ago

overload in objective C subclass, not work

public extension NSUserDefaults {

  func get(string: String) -> String {
    return ""
  }

  func get(int: String) -> Int {
    return 1
  }
}
onmyway133 commented 8 years ago

not derived from objective C, work

public class A {

  subscript(string: String) -> String {
    return ""
  }

  subscript(string: String) -> Int {
    return 1
  }
}

public class B {

  func get(string: String) -> String {
    return ""
  }

  func get(string: String) -> Int {
    return 1
  }
}
onmyway133 commented 8 years ago

Swift type signature