blob: a04421c2909100ec8ba8dfcd48757c882c2cffd1 [file] [log] [blame]
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
import CoreFoundation
public let NSGlobalDomain: String = "NSGlobalDomain"
public let NSArgumentDomain: String = "NSArgumentDomain"
public let NSRegistrationDomain: String = "NSRegistrationDomain"
private var registeredDefaults = [String: AnyObject]()
private var sharedDefaults = NSUserDefaults()
public class NSUserDefaults : NSObject {
private let suite: String?
public class func standardUserDefaults() -> NSUserDefaults {
return sharedDefaults
}
public class func resetStandardUserDefaults() {
//sharedDefaults.synchronize()
//sharedDefaults = NSUserDefaults()
}
public convenience override init() {
self.init(suiteName: nil)!
}
/// nil suite means use the default search list that +standardUserDefaults uses
public init?(suiteName suitename: String?) {
suite = suitename
}
public func objectForKey(defaultName: String) -> AnyObject? {
func getFromRegistered() -> AnyObject? {
return registeredDefaults[defaultName]
}
guard let anObj = CFPreferencesCopyAppValue(defaultName._cfObject, suite?._cfObject ?? kCFPreferencesCurrentApplication) else {
return getFromRegistered()
}
//Force the returned value to an NSObject
switch CFGetTypeID(anObj) {
case CFStringGetTypeID():
return (anObj as! CFString)._nsObject
case CFNumberGetTypeID():
return (anObj as! CFNumber)._nsObject
case CFURLGetTypeID():
return (anObj as! CFURL)._nsObject
case CFArrayGetTypeID():
return (anObj as! CFArray)._nsObject
case CFDictionaryGetTypeID():
return (anObj as! CFDictionary)._nsObject
case CFDataGetTypeID():
return (anObj as! CFData)._nsObject
default:
return getFromRegistered()
}
}
public func setObject(value: AnyObject?, forKey defaultName: String) {
guard let value = value else {
CFPreferencesSetAppValue(defaultName._cfObject, nil, suite?._cfObject ?? kCFPreferencesCurrentApplication)
return
}
var cfType: CFTypeRef? = nil
//FIXME: is this needed? Am I overcomplicating things?
//Foundation types
if let bType = value as? NSNumber {
cfType = bType._cfObject
} else if let bType = value as? NSString {
cfType = bType._cfObject
} else if let bType = value as? NSArray {
cfType = bType._cfObject
} else if let bType = value as? NSDictionary {
cfType = bType._cfObject
} else if let bType = value as? NSURL {
setURL(bType, forKey: defaultName)
return
} else if let bType = value as? NSData {
cfType = bType._cfObject
}
CFPreferencesSetAppValue(defaultName._cfObject, cfType, suite?._cfObject ?? kCFPreferencesCurrentApplication)
}
public func removeObjectForKey(defaultName: String) {
CFPreferencesSetAppValue(defaultName._cfObject, nil, suite?._cfObject ?? kCFPreferencesCurrentApplication)
}
public func stringForKey(defaultName: String) -> String? {
guard let aVal = objectForKey(defaultName), bVal = aVal as? NSString else {
return nil
}
return bVal._swiftObject
}
public func arrayForKey(defaultName: String) -> [AnyObject]? {
guard let aVal = objectForKey(defaultName), bVal = aVal as? NSArray else {
return nil
}
return bVal._swiftObject
}
public func dictionaryForKey(defaultName: String) -> [String : AnyObject]? {
guard let aVal = objectForKey(defaultName), bVal = aVal as? NSDictionary else {
return nil
}
//This got out of hand fast...
let cVal = bVal._swiftObject
enum convErr: ErrorProtocol {
case ConvErr
}
do {
let dVal = try cVal.map({ (key, val) -> (String, AnyObject) in
if let strKey = key as? NSString {
return (strKey._swiftObject, val)
} else {
throw convErr.ConvErr
}
})
var eVal = [String : AnyObject]()
for (key, value) in dVal {
eVal[key] = value
}
return eVal
} catch _ { }
return nil
}
public func dataForKey(defaultName: String) -> NSData? {
guard let aVal = objectForKey(defaultName), bVal = aVal as? NSData else {
return nil
}
return bVal
}
public func stringArrayForKey(defaultName: String) -> [String]? {
guard let aVal = objectForKey(defaultName), bVal = aVal as? NSArray else {
return nil
}
return _expensivePropertyListConversion(bVal) as? [String]
}
public func integerForKey(defaultName: String) -> Int {
guard let aVal = objectForKey(defaultName), bVal = aVal as? NSNumber else {
return 0
}
return bVal.integerValue
}
public func floatForKey(defaultName: String) -> Float {
guard let aVal = objectForKey(defaultName), bVal = aVal as? NSNumber else {
return 0
}
return bVal.floatValue
}
public func doubleForKey(defaultName: String) -> Double {
guard let aVal = objectForKey(defaultName), bVal = aVal as? NSNumber else {
return 0
}
return bVal.doubleValue
}
public func boolForKey(defaultName: String) -> Bool {
guard let aVal = objectForKey(defaultName), bVal = aVal as? NSNumber else {
return false
}
return bVal.boolValue
}
public func URLForKey(defaultName: String) -> NSURL? {
guard let aVal = objectForKey(defaultName) else {
return nil
}
if let bVal = aVal as? NSString {
let cVal = bVal.stringByExpandingTildeInPath
return NSURL(fileURLWithPath: cVal)
} else if let bVal = aVal as? NSData {
return NSKeyedUnarchiver.unarchiveObjectWithData(bVal) as? NSURL
}
return nil
}
public func setInteger(value: Int, forKey defaultName: String) {
setObject(NSNumber(integer: value), forKey: defaultName)
}
public func setFloat(value: Float, forKey defaultName: String) {
setObject(NSNumber(float: value), forKey: defaultName)
}
public func setDouble(value: Double, forKey defaultName: String) {
setObject(NSNumber(double: value), forKey: defaultName)
}
public func setBool(value: Bool, forKey defaultName: String) {
setObject(NSNumber(bool: value), forKey: defaultName)
}
public func setURL(url: NSURL?, forKey defaultName: String) {
if let url = url {
//FIXME: CFURLIsFileReferenceURL is limited to OS X/iOS
#if os(OSX) || os(iOS)
//FIXME: no SwiftFoundation version of CFURLIsFileReferenceURL at time of writing!
if !CFURLIsFileReferenceURL(url._cfObject) {
//FIXME: stringByAbbreviatingWithTildeInPath isn't implemented in SwiftFoundation
//TODO: use stringByAbbreviatingWithTildeInPath when it is
let urlPath = url.path!
setObject(urlPath._nsObject, forKey: defaultName)
return
}
#else
if let urlPath = url.path {
//FIXME: stringByAbbreviatingWithTildeInPath isn't implemented in SwiftFoundation
//TODO: use stringByAbbreviatingWithTildeInPath when it is
setObject(urlPath._nsObject, forKey: defaultName)
return
}
#endif
let data = NSKeyedArchiver.archivedDataWithRootObject(url)
setObject(data, forKey: defaultName)
} else {
setObject(nil, forKey: defaultName)
}
}
public func registerDefaults(registrationDictionary: [String : AnyObject]) {
for (key, value) in registrationDictionary {
registeredDefaults[key] = value
}
}
public func addSuiteNamed(suiteName: String) {
CFPreferencesAddSuitePreferencesToApp(kCFPreferencesCurrentApplication, suiteName._cfObject)
}
public func removeSuiteNamed(suiteName: String) {
CFPreferencesRemoveSuitePreferencesFromApp(kCFPreferencesCurrentApplication, suiteName._cfObject)
}
public func dictionaryRepresentation() -> [String : AnyObject] {
NSUnimplemented()
/*
Currently crashes the compiler.
guard let aPref = CFPreferencesCopyMultiple(nil, kCFPreferencesCurrentApplication, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost),
bPref = (aPref._swiftObject) as? [NSString: AnyObject] else {
return registeredDefaults
}
var allDefaults = registeredDefaults
for (key, value) in bPref {
allDefaults[key._swiftObject] = value
}
return allDefaults
*/
}
public var volatileDomainNames: [String] { NSUnimplemented() }
public func volatileDomainForName(domainName: String) -> [String : AnyObject] { NSUnimplemented() }
public func setVolatileDomain(domain: [String : AnyObject], forName domainName: String) { NSUnimplemented() }
public func removeVolatileDomainForName(domainName: String) { NSUnimplemented() }
public func persistentDomainForName(domainName: String) -> [String : AnyObject]? { NSUnimplemented() }
public func setPersistentDomain(domain: [String : AnyObject], forName domainName: String) { NSUnimplemented() }
public func removePersistentDomainForName(domainName: String) { NSUnimplemented() }
public func synchronize() -> Bool {
return CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication)
}
public func objectIsForcedForKey(key: String) -> Bool { NSUnimplemented() }
public func objectIsForcedForKey(key: String, inDomain domain: String) -> Bool { NSUnimplemented() }
}
public let NSUserDefaultsDidChangeNotification: String = "NSUserDefaultsDidChangeNotification"