Add to Podfile:
use_frameworks!
pod 'UserDefaultPropertyWrapper', :git => 'https://github.com/AntonBelousov/UserDefaultPropertyWrapper'
Call
pod install
-
You can use wrapper with base types:
Bool,Int,Double,Float,String,Date,Data. You can useArrayof any mentioned type (array of arrays as well), andDictionary, whereKey == StringandValue == any mentioned type -
Type may be optional
-
You can use custom types, just make your type conform to the
UserDefaultsConvertibleprotocol. -
Some types has predefined default values:
falsetoBool,0forInt,Float,Double,nilforOptional, empty collection forArrayandDictionary. You can specify default values for other types (seeUserDefaultsConvertibleWithDefaultValue)
- Add model version update handling
import UserDefaultPropertyWrapper
class Settings {
static let shared = Settings()
@UserDefault("boolValue")
var boolValue: Bool
@UserDefault("boolValueWithDefaultValue", defaultValue: true)
var boolValueWithDefaultValue: Bool
@UserDefault("intValue")
var intValue: Int
@UserDefault("intValueWithDefaultValue", defaultValue: 451)
var intValueWithDefaultValue: Int
@UserDefault("doubleValue")
var doubleValue: Double
@UserDefault("floatValue")
var floatValue: Float
@UserDefault("stringValue", defaultValue: "")
var stringValue: String
@UserDefault("optionalStringValue")
var optionalStringValue: String?
@UserDefault("dateValue", defaultValue: .distantFuture)
var dateValue: Date
@UserDefault("optionalDataValue")
var optionalDataValue: Data?
@UserDefault("array", defaultValue: [1,9,6,1])
var array: [Int]
@UserDefault("arrayOfArray")
var arrayOfArray: [[Int]]
@UserDefault("dict")
var dict: [String: Int]
}
// Than use these properties as usual
Settings.shared.optionalStringValue = "Some value"
print(String.shared.optionalStringValue)
Settings.shared.optionalStringValue = nil
print(String.shared.optionalStringValue)
You can make any type conform to the UserDefaultsConvertible protocol
enum Activity: UserDefaultsConvertible {
var userDefaultsValue: Any {
switch self {
case .reading(let book):
return "r\(book)"
case .watching(let movie):
return "w\(movie)"
}
}
static func create(from userDefaultsValue: Any) -> Activity {
var value = userDefaultsValue as! String
if value.hasPrefix("r") {
value.removeFirst()
return .reading(book: value)
} else if value.hasPrefix("w") {
value.removeFirst()
return .watching(movie: value)
}
fatalError()
}
case watching(movie: String)
case reading(book: String)
}
class ActivityStorage {
@UserDefault("activity", defaultValue: nil)
var activity: Activity?
}
ActivityStorage().activity = .reading(book: "Hearts of Three")
print(ActivityStorage().activity ?? "nil")
If your type conforms to the Codable protocol, you can easily make if conform UserDefaultsConvertible. Just add UserDefaultsConvertible after type name and it will became convertible automatically:
struct User: Codable, UserDefaultsConvertible {
var firstname: String
var lastname: String
var birthdate: Date
var address: String
}
Note. You can use UserDefauls to share data between your application and app extension see
struct User: Codable, UserDefaultsConvertible {
var firstname: String
var lastname: String
var birthdate: Date
var address: String
}
class UsersSource {
static let defaults = UserDefaults(suiteName: "app.group.id")!
@UserDefault("users", defaultValue:[], defaults: UsersSource.defaults)
var users: [User]
}
func someMethodInApp() {
let user = User(
firstname: "Artur",
lastname: "Fleck",
birthdate: Date(timeIntervalSince1970: -729345600),
address: "Arkham Asylum, Gotham County, New Jersey, United States of America")
var source = UsersSource()
source.users.append(user)
}
func someMethodInExtension() {
source = UsersSource()
print(source.users)
}