Skip to content

Instantly share code, notes, and snippets.

@shaundon
Last active February 3, 2024 15:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shaundon/652d1c2cce52adfa1a502603380ec4c6 to your computer and use it in GitHub Desktop.
Save shaundon/652d1c2cce52adfa1a502603380ec4c6 to your computer and use it in GitHub Desktop.
UserDefaults group proof of concept

Very simple proof of concept of using App Groups for UserDefaults. I use this in all my apps to share data between a main app and its widgets.

It consists of:

  • UserPreferences: Struct that interacts with UserDefaults
  • PreferencesModel: Observable wrapper for UserPreferences, which is used in view-related code
  • ContentView: Very simple view to display something from preferences
  • MyApp: Entry point for the app, initialises preferences and adds it to the environment

Note that it uses the Observable protocol which requires iOS 17, but it works fine using ObservableObject too, which is supported in all previous versions of SwiftUI.

In app extensions (like widgets) I access these the same way, either by getting it directly from UserPreferences or PreferencesModel.

Ensure that all targets (i.e. both your app and your widget) are members of the same app group in Signing & Capabilities > App Groups.

import SwiftUI
struct ContentView: View {
@Environment(PreferencesModel.self) var preferences
var body: some View {
Text("Salary: \(preferences.salary)")
}
}
#Preview {
ContentView()
}
import SwiftUI
@main
struct MyApp: App {
@State private var preferences = PreferencesModel()
var body: some Scene {
WindowGroup {
ContentView()
.environment(preferences)
}
}
}
import SwiftUI
@Observable
class PreferencesModel {
var salary = UserPreferences.salary {
didSet { UserPreferences.salary = self.salary }
}
}
import UIKit
extension UserDefaults {
static let group = UserDefaults(suiteName: "group.com.codakuma.moneyplease")
}
import Foundation
struct UserPreferences {
enum Keys: String {
case salary
}
static var salary: Int {
get {
guard let group = UserDefaults.group else { return 0 }
return group.integer(forKey: Keys.salary.rawValue)
}
set { UserDefaults.group?.set(newValue, forKey: Keys.salary.rawValue) }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment