Skip to content

Instantly share code, notes, and snippets.

Last active December 22, 2023 11:06
Show Gist options
  • Save shivammaggu/451e06aafc8b25ba8ca9479a8f9ab175 to your computer and use it in GitHub Desktop.
Save shivammaggu/451e06aafc8b25ba8ca9479a8f9ab175 to your computer and use it in GitHub Desktop.
Using UserDefaults with Property Wrapper
import UIKit
// Protocol to check for Nil
protocol AnyOptional {
var isNil: Bool { get }
// Conforming nil check protocol to optional
extension Optional: AnyOptional {
var isNil: Bool {
return self == nil
// Helper Class for UserDefaults with Property Wrapper
class UserDefaultsHelper<T> {
private let defaultValue: T // Stores an initial default value
private let key: String // The key representing the value
private let store: UserDefaults // Used for defaults initialisation (Eg. .standard or .init(suiteName:))
// Initialiser
init(defaultValue: T, key: String, store: UserDefaults) {
self.defaultValue = defaultValue
self.key = key = store
print("\(self.key) initialised with default value \(self.defaultValue)\n")
// Getter Setter fot the wrapped property value
var wrappedValue: T {
set {
self.setValue(newValue: newValue)
get {
return self.getValue()
// Sets a value to Defaults or Removes it if nil
private func setValue(newValue: T) {
guard let newValue = newValue as? AnyOptional, newValue.isNil == true else {, forKey: self.key)
print("\(self.key) initialised with new value \(newValue)\n")
} self.key)
print("\(self.key) is removed\n")
// Fetches a value against a key from Defaults
private func getValue() -> T {
let value = self.key) as? T ?? defaultValue
print("Value for \(self.key) is \(value)\n")
return value
// Initialiser with nil default value
extension UserDefaultsHelper where T: ExpressibleByNilLiteral {
convenience init(key: String, store: UserDefaults) {
self.init(defaultValue: nil, key: key, store: store)
extension UserDefaults {
// Defaults object
private static var store: UserDefaults {
return UserDefaults.standard
// Defaults object shared with app groups
private static var groupStore: UserDefaults {
return UserDefaults.init(suiteName: "")!
// User Default Keys
enum Keys {
static let firstname: String = "firstname"
static let lastname: String = "lastname"
static let grade: String = "grade"
static let dateModified: String = "dateModified"
static let subjects: String = "subjects"
static let subjectTeacher: String = "subjectTeacher"
static let isActive: String = "isActive"
static let profileImage: String = "profileImage"
static let coverImage: String = "coverImage"
static var allCases: [String] = [firstname,
// Using property wrapper to set key values stored in user defaults
@UserDefaultsHelper(defaultValue: "Shivam", key: Keys.firstname, store: .groupStore)
static var firstname: String
@UserDefaultsHelper(defaultValue: "Maggu", key: Keys.lastname, store: .groupStore)
static var lastname: String
@UserDefaultsHelper(defaultValue: 5, key: Keys.grade, store: .store)
static var grade: Int?
@UserDefaultsHelper(defaultValue: Date(), key: Keys.dateModified, store: .store)
static var dateModified: Date
@UserDefaultsHelper(defaultValue: ["English", "Maths", "Science"], key: Keys.subjects, store: .store)
static var subjects: Array<String>
@UserDefaultsHelper(defaultValue: ["English": "Mrs. Jaggi", "Maths": "Mr. Karim", "Science": "Mrs. Rita"],
key: Keys.subjectTeacher,
store: .store)
static var subjectTeacher: [String: String]
@UserDefaultsHelper(defaultValue: true, key: Keys.isActive, store: .store)
static var isActive: Bool
@UserDefaultsHelper(defaultValue: Data(), key: Keys.profileImage, store: .store)
static var profileImage: Data
@UserDefaultsHelper(key: Keys.coverImage, store: .store)
static var coverImage: Data?
// Sets all the key-value pairs to their default values
static func clearAll() {
Keys.allCases.forEach { key in key)
self.groupStore.removeObject(forKey: key)
// Usage of UserDefaults
UserDefaults.isActive = false
UserDefaults.grade = 5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment