Prephirences 是一个 Swift 库,它提供有用的协议和便捷方法来管理应用程序偏好设置、配置和应用状态。
@Preference(key: "enabled")
var enabled: Bool?
@UserDefaultsPreference(key: "my.string.pref")
var pref: String?
@MutablePreference(preferences: UserDefaults.standard, key: "enabled")
var enabled: Bool?
let userDefaults = UserDefaults.standard
if let enabled = userDefaults["enabled"] as? Bool {..}
userDefaults["mycolorkey", archive] = UIColor.blue
Preferences 不仅仅是 UserDefaults
,还可以是:
Bundle
的应用程序信息NSUbiquitousKeyValueStore
即:任何实现简单协议 PreferencesType 的对象,该协议定义了键值存储方法。
您还可以组合多个偏好设置并以透明的方式使用它们(请参阅 组合)
PreferencesType 最简单的实现是 DictionaryPreferences
// From Dictionary
var fromDico = DictionaryPreferences(myDictionary)
// or literal
var fromDicoLiteral: DictionaryPreferences = ["myKey": "myValue", "bool": true]
// From filepath
if let fromFile = DictionaryPreferences(filePath: "/my/file/path") {..}
// ...in main bundle ##
if let fromFile = DictionaryPreferences(filename: "prefs", ofType: "plist") {..}
您可以使用 PreferencesType 协议中定义的所有方法进行访问
if let myValue = fromDicoLiteral.object(forKey: "myKey") {..}
if let myValue = fromDicoLiteral["bool"] as? Bool {..}
var hasKey = fromDicoLiteral.hasObject(forKey: "myKey")
var myValue = fromDicoLiteral.bool(forKey: "myKey")
..
如果您想使用 RawRepresentable
enum
进行访问。
enum MyKey: PreferenceKey/*String*/ {
case Key1, Key2, ...
}
if let myValue = fromDicoLiteral.object(forKey: MyKey.Key1) {..}
var myValue = fromDicoLiteral.bool(forKey: MyKey.Key2)
可修改的偏好设置实现了协议 MutablePreferencesTypes
最简单的实现是 MutableDictionaryPreferences
var mutableFromDico: MutableDictionaryPreferences = ["myKey": "myValue"]
mutableFromDico["newKey"] = "newValue"
mutableFromDico.set("myValue", forKey: "newKey")
mutableFromDico.set(true, forKey: "newKey")
...
您可以使用运算符附加字典或其他 PreferencesType
mutableFromDico += ["newKey": "newValue", "otherKey": true]
您也可以删除一个偏好设置
mutableFromDico -= "myKey"
您可以从任何 MutablePreferencesTypes
中提取一个 MutablePreference
,并根据其值类型应用运算符
var intPref: MutablePreference<Int> = aPrefs.preference(forKey: "intKey")
var intPref: MutablePreference<Int> = aPrefs <| "intKey"
intPref++
intPref--
intPref += 30
intPref -= 30
intPref *= 20
intPref %= 7
intPref /= 3
switch(intPref) {
case 1: println("one")
case 2...10: println("not one or zero but...")
default: println("unkwown")
}
var boolPref: MutablePreference<Bool> = aPrefs <| "boolKey")
boolPref &= false
boolPref |= true
boolPref != true
您还可以使用一些方法来更改值
var stringPref: MutablePreference<String> = userDefaults <| "stringKey"
stringPref.apply { value in
return value?.uppercaseString
}
或者使用闭包转换值类型
let intFromBoolPref : MutablePreference<Int> = boolPref.transform { value in
return (value ?? false) ? 1:0
}
在存储或访问值之前,可以应用符合协议 PreferenceTransformation
的转换。
这允许归档、更改类型、如果为 nil 则返回默认值等等。
您可以使用 subscript
获取和设置值
userDefaults["aKey", myTransformation] = myObject
if let object = userDefaults["aKey", myTransformation] {...}
如果您提取一个偏好设置,请使用 transformation
属性来设置转换
var aPref: MutablePreference<MyObject> = userDefaults <| "aKey"
aPref.transformation = myTransformation
或者,您可以使用一些实用函数来指定存储值满足条件时的默认值
public var intValueMin10: MutablePreference<Int> {
get {
return userDefaults.preference(forKey: "intKey")
.whenNil(use: 100)
.ensure(when: lessThan100, use: 100)
}
set {..}
}
归档对于 NSUserDefaults
特别有用,因为 NSUserDefaults
无法存储所有类型的对象。以下函数可以通过将值转换为另一种类型来提供帮助
您可以使用这两种方法归档为 Data
userDefaults.set(objectToArchive: UIColor.blueColor(), forKey: "colorKey")
userDefaults["colorKey", .Archive] = UIColor.blueColor()
并使用以下方法解档
if let color = userDefaults.unarchiveObject(forKey: "colorKey") as? UIColor {..}
if let color = userDefaults["colorKey", .Archive] as? UIColor {..}
如果您提取一个偏好设置,请使用 transformation
属性来设置归档模式
var colorPref: MutablePreference<UIColor> = userDefaults <| "colorKey"
colorPref.transformation = TransformationKey.Archive
colorPref.value = UIColor.redColor()
if let color = colorPref.value as? UIColor {..}
您还可以对所有对象类型应用 NSValueTransformer
,例如转换为 JSON
userDefaults["colorKey", myValueTransformerToJson] = myComplexObject
if let object = userDefaults["colorKey", myValueTransformerToJson] {...}
allowsReverseTransformation
必须返回 true
对于像 enum
这样的 RawRepresentable
对象,您可以将计算属性 preferenceTransformation
用作 transformation
enum PrefEnum: String {
case One, Two, Three
}
var pref: MutablePreference<PrefEnum> = preferences <| "enumKey"
pref.transformation = PrefEnum.preferenceTransformation
pref.value = PrefEnum.Two
UserDefaults
实现了 PreferencesType
并且可以使用相同的方法进行访问
let userDefaults = UserDefaults.standard
if let myValue = userDefaults["mykey"] as? Bool {..}
NSUserDefaults 也实现了 MutablePreferencesType
并且可以使用相同的方法进行修改
userDefaults["mykey"] = "myvalue"
// with type to archive
userDefaults["mykey", .Archive] = UIColor.blueColor()
所有 Bundle
都实现了 PreferencesType
,允许访问 Info.plist 文件。
例如,Bundle.main
包含许多关于您的应用程序的有用信息。
Prephirences 框架附带一些预定义的枚举,这些枚举在 苹果文档 中描述,并在 PropertyListKeys.swift
中定义。
let bundle = Bundle.main
let applicationName = bundle[.CFBundleName] as? String
要在 iCloud 中存储,NSUbiquitousKeyValueStore
也实现了 PreferencesType
请参阅组合章节,将 iCloud 偏好设置与其他偏好设置合并和同步。
您可以将响应隐式协议 NSKeyValueCoding 的对象包装在 KVCPreferences
或 MutableKVCPreferences
中
let kvcPref = MutableKVCPreferences(myObject)
请务必影响正确的对象类型
使用 ReflectingPreferences
,您可以轻松访问 struct 或 swift 类。只需添加扩展。
struct PreferenceStruct {
var color: String = "red"
var age: Int
let enabled: Bool = true
}
extension PreferenceStruct: ReflectingPreferences {}
然后您可以使用来自 PreferencesType
的所有函数
var pref = PreferenceStruct(color: "red", age: 33)
if pref["color"] as? String { .. }
您可以将 NSManageObject
包装在 ManageObjectPreferences
或 MutableManageObjectPreferences
中
let managedPref = ManageObjectPreferences(myManagedObject)
有很多方法可以处理 plist 文件
Plist
(带有有用的 write
方法)DictionaryPreferences
或 MutableDictionaryPreferences
set(dictionary:
要存储到钥匙串中,请使用 KeychainPreferences
的一个实例
KeychainPreferences.sharedInstance // default instance with main bundle id
var keychain = KeychainPreferences(service: "com.github.example")
然后存储 String
或 Data
keychain["anUserName"] = "password-encoded"
if let pass = keychain.stringForKey("anUserName") {..}
辅助功能
keychain.accessibility = .AccessibleAfterFirstUnlock
共享钥匙串项目
keychain.accessGroup = "AKEY.shared"
部分支持 NSCoder
(dictionary
不可用)
当您实现 NSCoding 时,您可以执行以下操作
init?(coder decoder: NSCoder) {
self.init()
self.intVar = decoder["intVarKey"] as? Int ?? 0
// or self.intVar = decoder.integer(forKey: "intVar")
self.stringVar = decoder["stringVarKey"] as? String ?? ""
}
func encodeWithCoder(coder: NSCoder) {
coder["intVarKey"] = self.intVar
coder["stringVarKey"] = self.stringVar
}
创建一个符合 PreferencesType
的自定义对象非常容易。
extension MyCustomPreferences: PreferencesType {
func object(forKey: String) -> Any? {
// return an object according to key
}
func dictionary() -> [String : Any] {
// return a full dictionary of key value
}
}
只有两个函数是强制性的,其他函数会自动映射,但可以为了性能或可读性而覆盖。
set
和 removeObject(forKey:
方法实现 MutablePreferencesType
。PreferencesAdapter
并实现 func keys() -> [String]
。CollectionPreferencesAdapter
或查看 NSHTTPCookieStorage
实现。您可以不使用 string
或 string
常量,而是使用 enum
来定义键列表
首先使用 String
原始值创建您的 enum
enum MyEnum: String {
case MyFirstKey
case MySecondKey
}
然后为您的键添加下标
extension PreferencesType {
subscript(key: MyEnum) -> Any? {
return self[key.rawValue]
}
}
最后访问您的信息
if let firstValue = bundle[.MyFirstKey] {..}
您可以对 MutablePreferencesType
执行相同的操作
您可以像这样定义一个带有您自己的字符串前缀的偏好设置子类别
let myAppPrefs = MutableProxyPreferences(preferences: userDefaults, key: "myAppKey.")
// We have :
userDefaults["myAppKey.myKey"] == myAppPrefs["myKey"] // is true
这允许使用相同的键为所有偏好设置(用户默认设置)添加前缀
组合允许将多个 PreferencesType 对象聚合为一个 PreferencesType
let myPreferences = CompositePreferences([fromDico, fromFile, userDefaults])
// With array literal
let myPreferences: CompositePreferences = [fromDico, fromFile, userDefaults]
// Mutable, only first mutable will be affected
let myPreferences: MutableCompositePreferences = [fromDico, fromFile, userDefaults]
您可以像任何 PreferencesType
一样访问或修改此复合偏好设置。
MutableCompositePreferences
属性 affectOnlyFirstMutable
设置为 false
以影响所有可变偏好设置,从而允许您例如复制 iCloud 中的偏好设置主要目标是为您的应用程序定义只读偏好设置(在代码或文件中)和一些可变偏好设置(例如 UserDefaults
、NSUbiquitousKeyValueStore
)。然后您可以访问一个偏好设置值,而无需关心来源。
如果您想在框架中使用 Prephirences,或者想在不添加类之间依赖关系的情况下获取 Preferences
,您可以将任何 PreferencesType
注册到 Prephirences
中
作为共享实例
Prephirences.sharedInstance = myPreferences
或者通过提供一个 Hashable
键
Prephirences.register(preferences: myPreferences, forKey: "myKey")
Prephirences.instances()["myKey"] = myPreferences
Prephirences.instances()[NSStringFromClass(self.dynamicType)] = currentClassPreferences
然后您可以在任何地方访问它
if let pref = Prephirences.instance(forKey: "myKey") {..}
if let pref = Prephirences.instances()["myKey"] {..}
通过使用远程偏好设置,您可以远程控制应用程序的行为。
如果您使用 Alamofire,Alamofire-Prephirences 将帮助您从远程 JSON 或 Plist 加载偏好设置
您可以使用框架 CryptoPrephirences 使用来自 CryptoSwift 的密码加密/解密您的偏好设置
CocoaPods 是 Objective-C 和 Swift 的集中式依赖项管理器。 请转到 这里 了解更多信息。
将项目添加到您的 Podfile。
use_frameworks!
pod 'Prephirences'
运行 pod install
并打开 .xcworkspace
文件以启动 Xcode。
添加 pod 'Prephirences/CoreData'
添加 pod 'Prephirences/RawRepresentableKey'
添加 pod 'Prephirences/Keys'
Carthage 是 Objective-C 和 Swift 的去中心化依赖项管理器。
将项目添加到您的 Cartfile。
github "phimage/Prephirences"
运行 carthage update
并按照 附加步骤 将 Prephirences 添加到您的项目。
由 kodlian 提供