Skip to content

Commit

Permalink
docs: [vision-os-sample-app][2/n] App State Storage (#618)
Browse files Browse the repository at this point in the history
Co-authored-by: Ahmed Ali <[email protected]>
  • Loading branch information
Ahmed-CIO and Ahmed-Ali authored Mar 12, 2024
1 parent 63eebf5 commit e45e69f
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 1 deletion.
22 changes: 21 additions & 1 deletion Apps/VisionOS/VisionOS.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
60F967472B91264B00A4E95E /* Splash in Frameworks */ = {isa = PBXBuildFile; productRef = 60F967462B91264B00A4E95E /* Splash */; };
60F9674A2B91265B00A4E95E /* MarkdownUI in Frameworks */ = {isa = PBXBuildFile; productRef = 60F967492B91265B00A4E95E /* MarkdownUI */; };
60F9674E2B91269D00A4E95E /* Tracking in Frameworks */ = {isa = PBXBuildFile; productRef = 60F9674D2B91269D00A4E95E /* Tracking */; };
60F967532B91288400A4E95E /* AppState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60F967502B91288400A4E95E /* AppState.swift */; };
60F967542B91288400A4E95E /* Payloads.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60F967512B91288400A4E95E /* Payloads.swift */; };
60F967552B91288400A4E95E /* UserDefaultsCodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60F967522B91288400A4E95E /* UserDefaultsCodable.swift */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
Expand All @@ -21,7 +24,10 @@
60F967362B9125D000A4E95E /* MainScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainScreen.swift; sourceTree = "<group>"; };
60F967382B9125D100A4E95E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
60F9673D2B9125D100A4E95E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
60F9674B2B91267200A4E95E /* customerio-ios */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = "customerio-ios"; path = ../../..; sourceTree = "<group>"; };
60F9674B2B91267200A4E95E /* cio-ios-spl */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = "customerio-ios"; path = ../../..; sourceTree = "<group>"; };
60F967502B91288400A4E95E /* AppState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppState.swift; sourceTree = "<group>"; };
60F967512B91288400A4E95E /* Payloads.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Payloads.swift; sourceTree = "<group>"; };
60F967522B91288400A4E95E /* UserDefaultsCodable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserDefaultsCodable.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -59,6 +65,7 @@
60F9672F2B9125D000A4E95E /* VisionOS */ = {
isa = PBXGroup;
children = (
60F9674F2B91288400A4E95E /* Storage */,
60F967342B9125D000A4E95E /* VisionOSApp.swift */,
60F967362B9125D000A4E95E /* MainScreen.swift */,
60F967382B9125D100A4E95E /* Assets.xcassets */,
Expand All @@ -82,6 +89,16 @@
name = Frameworks;
sourceTree = "<group>";
};
60F9674F2B91288400A4E95E /* Storage */ = {
isa = PBXGroup;
children = (
60F967502B91288400A4E95E /* AppState.swift */,
60F967512B91288400A4E95E /* Payloads.swift */,
60F967522B91288400A4E95E /* UserDefaultsCodable.swift */,
);
path = Storage;
sourceTree = "<group>";
};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
Expand Down Expand Up @@ -160,8 +177,11 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
60F967542B91288400A4E95E /* Payloads.swift in Sources */,
60F967372B9125D000A4E95E /* MainScreen.swift in Sources */,
60F967352B9125D000A4E95E /* VisionOSApp.swift in Sources */,
60F967532B91288400A4E95E /* AppState.swift in Sources */,
60F967552B91288400A4E95E /* UserDefaultsCodable.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
23 changes: 23 additions & 0 deletions Apps/VisionOS/VisionOS/Storage/AppState.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import Foundation

class AppState: ObservableObject {
static let shared = AppState()

@Published var profile: Profile = .loadFromStorage() {
didSet {
UserDefaults.standard.setValue(
profile.toJson(),
forKey: Profile.storageKey()
)
}
}

@Published var workspaceSettings: WorkspaceSettings = .loadFromStorage() {
didSet {
UserDefaults.standard.setValue(
workspaceSettings.toJson(),
forKey: WorkspaceSettings.storageKey()
)
}
}
}
66 changes: 66 additions & 0 deletions Apps/VisionOS/VisionOS/Storage/Payloads.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import CioTracking
import Foundation

extension Region: CaseIterable, Codable {
public static var allCases: [Region] = [.EU, .US]
}

struct WorkspaceSettings: UserDefaultsCodable {
var siteId: String
var apiKey: String
var region: Region = .EU

static func storageKey() -> String {
"UserDefaultsCodable"
}

static func empty() -> Self {
WorkspaceSettings(siteId: "", apiKey: "")
}

func isSet() -> Bool {
!siteId.isEmpty && !apiKey.isEmpty
}
}

struct Profile: UserDefaultsCodable {
var id: String
var properties: [Property]
var loggedIn: Bool

static func empty() -> Profile {
Profile(id: UUID().uuidString, properties: [], loggedIn: false)
}

static func storageKey() -> String {
"Profile"
}
}

struct Property: Codable, Identifiable, Comparable, Equatable {
static func < (lhs: Property, rhs: Property) -> Bool {
lhs.name == rhs.name
}

let id: String
var name: String
var value: String

init(name: String, value: String) {
self.id = UUID().uuidString
self.name = name
self.value = value
}
}

extension [Property] {
func toDictionary() -> [String: String] {
var res: [String: String] = [:]
forEach { p in
if !p.name.isEmpty {
res[p.name] = p.value
}
}
return res
}
}
34 changes: 34 additions & 0 deletions Apps/VisionOS/VisionOS/Storage/UserDefaultsCodable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import Foundation

protocol UserDefaultsCodable: Codable {
static func storageKey() -> String
static func empty() -> Self
}

extension UserDefaultsCodable {
func toJson() -> Data {
let encoder = JSONEncoder()
return try! encoder.encode(self)
}

static func from(_ data: Data) -> Self? {
let decoder = JSONDecoder()
return try? decoder.decode(Self.self, from: data)
}

static func loadFromStorage() -> Self {
if let data =
UserDefaults.standard.object(forKey: storageKey()) as? Data,
let storedInstance = from(data) {
return storedInstance
}

let content = Self.empty()
UserDefaults.standard.setValue(
content.toJson(),
forKey: Self.storageKey()
)

return content
}
}

0 comments on commit e45e69f

Please sign in to comment.