Compare commits
10 Commits
f2219e9df8
...
3c04ad18b7
| Author | SHA1 | Date | |
|---|---|---|---|
| 3c04ad18b7 | |||
| c71b9f5fb0 | |||
| 40e086c591 | |||
| 8bd5a47c42 | |||
| cb30e67bbe | |||
| be65f4610c | |||
| e88a1fca56 | |||
| 35dd86e81c | |||
| 53b3f7ed3a | |||
| 1a71670f9d |
31
README.md
31
README.md
@ -1,4 +1,4 @@
|
|||||||
# SecureStorgageSample
|
# SecureStorageSample
|
||||||
|
|
||||||
A sample iOS app demonstrating the LocalData package capabilities for secure, typed storage across multiple domains.
|
A sample iOS app demonstrating the LocalData package capabilities for secure, typed storage across multiple domains.
|
||||||
|
|
||||||
@ -24,10 +24,10 @@ The project also includes a watchOS companion app target for watch-specific demo
|
|||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
1. Open `SecureStorgageSample.xcodeproj`
|
1. Open `SecureStorageSample.xcodeproj`
|
||||||
2. Select an iOS simulator or device
|
2. Select an iOS simulator or device
|
||||||
3. Build and run (⌘R)
|
3. Build and run (⌘R)
|
||||||
4. To use App Group demos, set your App Group identifier in `SecureStorgageSample/SecureStorgageSample/Models/AppGroupConfiguration.swift` and enable the entitlement for each target that should share data.
|
4. To use App Group demos, enable the App Group entitlement for each target that should share data. The identifier is derived from the bundle ID via SharedKit constants.
|
||||||
|
|
||||||
## Project Structure
|
## Project Structure
|
||||||
|
|
||||||
@ -37,10 +37,11 @@ SharedPackage/
|
|||||||
└── Sources/
|
└── Sources/
|
||||||
└── SharedKit/
|
└── SharedKit/
|
||||||
├── Constants/
|
├── Constants/
|
||||||
│ └── StorageKeyNames.swift
|
│ ├── StorageKeyNames.swift
|
||||||
|
│ └── StorageServiceIdentifiers.swift
|
||||||
└── Models/
|
└── Models/
|
||||||
└── UserProfile.swift
|
└── UserProfile.swift
|
||||||
SecureStorgageSample/
|
SecureStorageSample/
|
||||||
├── ContentView.swift # Tabbed navigation
|
├── ContentView.swift # Tabbed navigation
|
||||||
├── Models/
|
├── Models/
|
||||||
│ ├── Credential.swift
|
│ ├── Credential.swift
|
||||||
@ -89,9 +90,9 @@ The app demonstrates various storage configurations:
|
|||||||
- 6 access control options (biometry, passcode, etc.)
|
- 6 access control options (biometry, passcode, etc.)
|
||||||
|
|
||||||
### File System
|
### File System
|
||||||
- Documents directory (persisted, backed up)
|
- **Documents**: Permanent storage, backed up to iCloud. Use for critical user data.
|
||||||
- Caches directory (can be purged)
|
- **Caches**: Purgeable storage (iOS may delete when low on space), not backed up. Use for temporary data.
|
||||||
- JSON and PropertyList serializers
|
- JSON and PropertyList serializers supported.
|
||||||
|
|
||||||
### App Group Storage
|
### App Group Storage
|
||||||
- Shared UserDefaults via App Group identifier
|
- Shared UserDefaults via App Group identifier
|
||||||
@ -103,10 +104,23 @@ The app demonstrates various storage configurations:
|
|||||||
- PBKDF2 or HKDF key derivation
|
- PBKDF2 or HKDF key derivation
|
||||||
- Complete file protection
|
- Complete file protection
|
||||||
- External key material example via `KeyMaterialProviding`
|
- External key material example via `KeyMaterialProviding`
|
||||||
|
- Global encryption configuration (Keychain service/account) in app `init`
|
||||||
|
|
||||||
### Platform & Sync
|
### Platform & Sync
|
||||||
- Platform availability (phoneOnly, watchOnly, all)
|
- Platform availability (phoneOnly, watchOnly, all)
|
||||||
- Sync policies (never, manual, automaticSmall)
|
- Sync policies (never, manual, automaticSmall)
|
||||||
|
- Global sync configuration (max file size) in app `init`
|
||||||
|
|
||||||
|
## Global Configuration
|
||||||
|
|
||||||
|
The app demonstrates how to configure the `LocalData` library globally during startup in `SecureStorageSampleApp.swift`:
|
||||||
|
|
||||||
|
- **Encryption**: Customized Keychain service (`SecureStorageSample`) and account (`AppMasterKey`) names to isolate the library's master encryption key from other apps.
|
||||||
|
- **Sync**: Set a custom `maxAutoSyncSize` of 50KB to control which data is automatically synchronized to the Apple Watch, overriding the library's 100KB default.
|
||||||
|
- **File Storage**: Scoping all library files into a `SecureStorage` sub-directory. This ensures that the library's data (whether in the main sandbox or a shared App Group container) is kept neat and isolated within its own folder, rather than cluttering the root directories.
|
||||||
|
- **Storage Defaults**: Pre-configuring the default Keychain service and App Group identifier. This allows common keys in the app to omit these identifiers, reducing boilerplate and making the code more maintainable.
|
||||||
|
|
||||||
|
This approach centralizes infrastructure settings and avoids hardcoding environment-specific values within individual storage keys.
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
@ -117,6 +131,7 @@ The app demonstrates various storage configurations:
|
|||||||
|
|
||||||
- Storage keys are now split into one file per key and grouped by domain; platform-focused keys live in `StorageKeys/Platform` with comments calling out availability/sync focus.
|
- Storage keys are now split into one file per key and grouped by domain; platform-focused keys live in `StorageKeys/Platform` with comments calling out availability/sync focus.
|
||||||
- The shared model/constants live in `SharedPackage` (`SharedKit`) to keep the watch/iOS data contract centralized.
|
- The shared model/constants live in `SharedPackage` (`SharedKit`) to keep the watch/iOS data contract centralized.
|
||||||
|
- Keychain service IDs and App Group identifiers are centralized in `SharedKit/Constants/StorageServiceIdentifiers.swift` to avoid hardcoded strings in keys.
|
||||||
- The watch app uses a handler-based WatchConnectivity layer so new payload types can be added in `Services/Handlers` without bloating the main service.
|
- The watch app uses a handler-based WatchConnectivity layer so new payload types can be added in `Services/Handlers` without bloating the main service.
|
||||||
- A `StorageKeyCatalog` sample is included to generate a security audit report of all storage keys.
|
- A `StorageKeyCatalog` sample is included to generate a security audit report of all storage keys.
|
||||||
- Each `StorageKey` includes a `description` used in audit reports.
|
- Each `StorageKey` includes a `description` used in audit reports.
|
||||||
|
|||||||
58
SecureStorageSample Watch App/README.md
Normal file
58
SecureStorageSample Watch App/README.md
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
# SecureStorageSample Watch App
|
||||||
|
|
||||||
|
A watchOS companion app demonstrating data synchronization with the iOS app using WatchConnectivity.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This watch app receives `UserProfile` data synced from the paired iPhone via `WCSession.updateApplicationContext`. It does **not** use LocalData directly for storage—instead, it displays synced data in memory.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
SecureStorageSample Watch App/
|
||||||
|
├── ContentView.swift # Displays synced profile data
|
||||||
|
├── SecureStorageSampleApp.swift
|
||||||
|
├── Protocols/
|
||||||
|
│ └── WatchDataHandling.swift # Protocol for payload handlers
|
||||||
|
├── State/
|
||||||
|
│ └── WatchProfileStore.swift # Holds synced profile in memory
|
||||||
|
└── Services/
|
||||||
|
├── WatchConnectivityService.swift
|
||||||
|
└── Handlers/
|
||||||
|
└── UserProfileWatchHandler.swift
|
||||||
|
```
|
||||||
|
|
||||||
|
## Data Flow
|
||||||
|
|
||||||
|
1. **iOS app** calls `SyncHelper` when storing data with `syncPolicy: .automaticSmall` or `.manual`
|
||||||
|
2. `SyncHelper` sends data via `WCSession.updateApplicationContext`
|
||||||
|
3. **Watch app** receives context in `WatchConnectivityService`
|
||||||
|
4. The service dispatches each payload key to its registered `WatchDataHandling` handler
|
||||||
|
5. `UserProfileWatchHandler` decodes the profile and updates `WatchProfileStore`
|
||||||
|
|
||||||
|
## Adding New Sync Payloads
|
||||||
|
|
||||||
|
1. Create a new handler conforming to `WatchDataHandling`:
|
||||||
|
|
||||||
|
```swift
|
||||||
|
struct MyDataWatchHandler: WatchDataHandling {
|
||||||
|
let key = "myData"
|
||||||
|
|
||||||
|
func handle(data: Data) {
|
||||||
|
// Decode and update state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Register it in `WatchConnectivityService.registerDefaultHandlers()`
|
||||||
|
|
||||||
|
## Limitations
|
||||||
|
|
||||||
|
- **No persistent storage on watch**: Data is held in memory only
|
||||||
|
- **One-way sync**: Watch receives data from iPhone; it does not send data back
|
||||||
|
- **Simulator limitations**: WatchConnectivity may not work reliably in the simulator
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- watchOS 10.0+
|
||||||
|
- Paired with iOS app via WatchConnectivity
|
||||||
@ -8,10 +8,14 @@ final class UserProfileWatchHandler: WatchDataHandling {
|
|||||||
private let store: WatchProfileStore
|
private let store: WatchProfileStore
|
||||||
private let decoder = JSONDecoder()
|
private let decoder = JSONDecoder()
|
||||||
|
|
||||||
init(store: WatchProfileStore = .shared) {
|
init(store: WatchProfileStore) {
|
||||||
self.store = store
|
self.store = store
|
||||||
}
|
}
|
||||||
|
|
||||||
|
convenience init() {
|
||||||
|
self.init(store: .shared)
|
||||||
|
}
|
||||||
|
|
||||||
func handle(data: Data) {
|
func handle(data: Data) {
|
||||||
do {
|
do {
|
||||||
let profile = try decoder.decode(UserProfile.self, from: data)
|
let profile = try decoder.decode(UserProfile.self, from: data)
|
||||||
|
|||||||
@ -20,14 +20,14 @@
|
|||||||
containerPortal = EA179CF92F1722BB00B1D54A /* Project object */;
|
containerPortal = EA179CF92F1722BB00B1D54A /* Project object */;
|
||||||
proxyType = 1;
|
proxyType = 1;
|
||||||
remoteGlobalIDString = EA179D002F1722BB00B1D54A;
|
remoteGlobalIDString = EA179D002F1722BB00B1D54A;
|
||||||
remoteInfo = SecureStorgageSample;
|
remoteInfo = SecureStorageSample;
|
||||||
};
|
};
|
||||||
EA179D192F1722BC00B1D54A /* PBXContainerItemProxy */ = {
|
EA179D192F1722BC00B1D54A /* PBXContainerItemProxy */ = {
|
||||||
isa = PBXContainerItemProxy;
|
isa = PBXContainerItemProxy;
|
||||||
containerPortal = EA179CF92F1722BB00B1D54A /* Project object */;
|
containerPortal = EA179CF92F1722BB00B1D54A /* Project object */;
|
||||||
proxyType = 1;
|
proxyType = 1;
|
||||||
remoteGlobalIDString = EA179D002F1722BB00B1D54A;
|
remoteGlobalIDString = EA179D002F1722BB00B1D54A;
|
||||||
remoteInfo = SecureStorgageSample;
|
remoteInfo = SecureStorageSample;
|
||||||
};
|
};
|
||||||
EA65D6F22F17DD6800C48466 /* PBXContainerItemProxy */ = {
|
EA65D6F22F17DD6800C48466 /* PBXContainerItemProxy */ = {
|
||||||
isa = PBXContainerItemProxy;
|
isa = PBXContainerItemProxy;
|
||||||
@ -67,28 +67,28 @@
|
|||||||
/* End PBXCopyFilesBuildPhase section */
|
/* End PBXCopyFilesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
EA179D012F1722BB00B1D54A /* SecureStorgageSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SecureStorgageSample.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
EA179D012F1722BB00B1D54A /* SecureStorageSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SecureStorageSample.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
EA179D0E2F1722BC00B1D54A /* SecureStorgageSampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SecureStorgageSampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
EA179D0E2F1722BC00B1D54A /* SecureStorageSampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SecureStorageSampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
EA179D182F1722BC00B1D54A /* SecureStorgageSampleUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SecureStorgageSampleUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
EA179D182F1722BC00B1D54A /* SecureStorageSampleUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SecureStorageSampleUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
EA65D6E52F17DD6700C48466 /* SecureStorageSample Watch App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "SecureStorageSample Watch App.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
EA65D6E52F17DD6700C48466 /* SecureStorageSample Watch App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "SecureStorageSample Watch App.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
EA65D6F12F17DD6800C48466 /* SecureStorageSample Watch AppTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SecureStorageSample Watch AppTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
|
EA65D6F12F17DD6800C48466 /* SecureStorageSample Watch AppTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SecureStorageSample Watch AppTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
EA65D6FB2F17DD6800C48466 /* SecureStorageSample Watch AppUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SecureStorageSample Watch AppUITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
|
EA65D6FB2F17DD6800C48466 /* SecureStorageSample Watch AppUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SecureStorageSample Watch AppUITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
||||||
EA179D032F1722BB00B1D54A /* SecureStorgageSample */ = {
|
EA179D032F1722BB00B1D54A /* SecureStorageSample */ = {
|
||||||
isa = PBXFileSystemSynchronizedRootGroup;
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
path = SecureStorgageSample;
|
path = SecureStorageSample;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
EA179D112F1722BC00B1D54A /* SecureStorgageSampleTests */ = {
|
EA179D112F1722BC00B1D54A /* SecureStorageSampleTests */ = {
|
||||||
isa = PBXFileSystemSynchronizedRootGroup;
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
path = SecureStorgageSampleTests;
|
path = SecureStorageSampleTests;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
EA179D1B2F1722BC00B1D54A /* SecureStorgageSampleUITests */ = {
|
EA179D1B2F1722BC00B1D54A /* SecureStorageSampleUITests */ = {
|
||||||
isa = PBXFileSystemSynchronizedRootGroup;
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
path = SecureStorgageSampleUITests;
|
path = SecureStorageSampleUITests;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
EA65D6E62F17DD6700C48466 /* SecureStorageSample Watch App */ = {
|
EA65D6E62F17DD6700C48466 /* SecureStorageSample Watch App */ = {
|
||||||
@ -161,9 +161,9 @@
|
|||||||
EA179CF82F1722BB00B1D54A = {
|
EA179CF82F1722BB00B1D54A = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
EA179D032F1722BB00B1D54A /* SecureStorgageSample */,
|
EA179D032F1722BB00B1D54A /* SecureStorageSample */,
|
||||||
EA179D112F1722BC00B1D54A /* SecureStorgageSampleTests */,
|
EA179D112F1722BC00B1D54A /* SecureStorageSampleTests */,
|
||||||
EA179D1B2F1722BC00B1D54A /* SecureStorgageSampleUITests */,
|
EA179D1B2F1722BC00B1D54A /* SecureStorageSampleUITests */,
|
||||||
EA65D6E62F17DD6700C48466 /* SecureStorageSample Watch App */,
|
EA65D6E62F17DD6700C48466 /* SecureStorageSample Watch App */,
|
||||||
EA65D6F42F17DD6800C48466 /* SecureStorageSample Watch AppTests */,
|
EA65D6F42F17DD6800C48466 /* SecureStorageSample Watch AppTests */,
|
||||||
EA65D6FE2F17DD6800C48466 /* SecureStorageSample Watch AppUITests */,
|
EA65D6FE2F17DD6800C48466 /* SecureStorageSample Watch AppUITests */,
|
||||||
@ -175,9 +175,9 @@
|
|||||||
EA179D022F1722BB00B1D54A /* Products */ = {
|
EA179D022F1722BB00B1D54A /* Products */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
EA179D012F1722BB00B1D54A /* SecureStorgageSample.app */,
|
EA179D012F1722BB00B1D54A /* SecureStorageSample.app */,
|
||||||
EA179D0E2F1722BC00B1D54A /* SecureStorgageSampleTests.xctest */,
|
EA179D0E2F1722BC00B1D54A /* SecureStorageSampleTests.xctest */,
|
||||||
EA179D182F1722BC00B1D54A /* SecureStorgageSampleUITests.xctest */,
|
EA179D182F1722BC00B1D54A /* SecureStorageSampleUITests.xctest */,
|
||||||
EA65D6E52F17DD6700C48466 /* SecureStorageSample Watch App.app */,
|
EA65D6E52F17DD6700C48466 /* SecureStorageSample Watch App.app */,
|
||||||
EA65D6F12F17DD6800C48466 /* SecureStorageSample Watch AppTests.xctest */,
|
EA65D6F12F17DD6800C48466 /* SecureStorageSample Watch AppTests.xctest */,
|
||||||
EA65D6FB2F17DD6800C48466 /* SecureStorageSample Watch AppUITests.xctest */,
|
EA65D6FB2F17DD6800C48466 /* SecureStorageSample Watch AppUITests.xctest */,
|
||||||
@ -195,9 +195,9 @@
|
|||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
EA179D002F1722BB00B1D54A /* SecureStorgageSample */ = {
|
EA179D002F1722BB00B1D54A /* SecureStorageSample */ = {
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = EA179D222F1722BC00B1D54A /* Build configuration list for PBXNativeTarget "SecureStorgageSample" */;
|
buildConfigurationList = EA179D222F1722BC00B1D54A /* Build configuration list for PBXNativeTarget "SecureStorageSample" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
EA179CFD2F1722BB00B1D54A /* Sources */,
|
EA179CFD2F1722BB00B1D54A /* Sources */,
|
||||||
EA179CFE2F1722BB00B1D54A /* Frameworks */,
|
EA179CFE2F1722BB00B1D54A /* Frameworks */,
|
||||||
@ -210,20 +210,20 @@
|
|||||||
EA65D70F2F17DDEB00C48466 /* PBXTargetDependency */,
|
EA65D70F2F17DDEB00C48466 /* PBXTargetDependency */,
|
||||||
);
|
);
|
||||||
fileSystemSynchronizedGroups = (
|
fileSystemSynchronizedGroups = (
|
||||||
EA179D032F1722BB00B1D54A /* SecureStorgageSample */,
|
EA179D032F1722BB00B1D54A /* SecureStorageSample */,
|
||||||
);
|
);
|
||||||
name = SecureStorgageSample;
|
name = SecureStorageSample;
|
||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
EA179D552F17379800B1D54A /* LocalData */,
|
EA179D552F17379800B1D54A /* LocalData */,
|
||||||
EA65D7312F17DDEB00C48466 /* SharedKit */,
|
EA65D7312F17DDEB00C48466 /* SharedKit */,
|
||||||
);
|
);
|
||||||
productName = SecureStorgageSample;
|
productName = SecureStorageSample;
|
||||||
productReference = EA179D012F1722BB00B1D54A /* SecureStorgageSample.app */;
|
productReference = EA179D012F1722BB00B1D54A /* SecureStorageSample.app */;
|
||||||
productType = "com.apple.product-type.application";
|
productType = "com.apple.product-type.application";
|
||||||
};
|
};
|
||||||
EA179D0D2F1722BC00B1D54A /* SecureStorgageSampleTests */ = {
|
EA179D0D2F1722BC00B1D54A /* SecureStorageSampleTests */ = {
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = EA179D252F1722BC00B1D54A /* Build configuration list for PBXNativeTarget "SecureStorgageSampleTests" */;
|
buildConfigurationList = EA179D252F1722BC00B1D54A /* Build configuration list for PBXNativeTarget "SecureStorageSampleTests" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
EA179D0A2F1722BC00B1D54A /* Sources */,
|
EA179D0A2F1722BC00B1D54A /* Sources */,
|
||||||
EA179D0B2F1722BC00B1D54A /* Frameworks */,
|
EA179D0B2F1722BC00B1D54A /* Frameworks */,
|
||||||
@ -235,19 +235,19 @@
|
|||||||
EA179D102F1722BC00B1D54A /* PBXTargetDependency */,
|
EA179D102F1722BC00B1D54A /* PBXTargetDependency */,
|
||||||
);
|
);
|
||||||
fileSystemSynchronizedGroups = (
|
fileSystemSynchronizedGroups = (
|
||||||
EA179D112F1722BC00B1D54A /* SecureStorgageSampleTests */,
|
EA179D112F1722BC00B1D54A /* SecureStorageSampleTests */,
|
||||||
);
|
);
|
||||||
name = SecureStorgageSampleTests;
|
name = SecureStorageSampleTests;
|
||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
EA65D7312F17DDEB00C48466 /* SharedKit */,
|
EA65D7312F17DDEB00C48466 /* SharedKit */,
|
||||||
);
|
);
|
||||||
productName = SecureStorgageSampleTests;
|
productName = SecureStorageSampleTests;
|
||||||
productReference = EA179D0E2F1722BC00B1D54A /* SecureStorgageSampleTests.xctest */;
|
productReference = EA179D0E2F1722BC00B1D54A /* SecureStorageSampleTests.xctest */;
|
||||||
productType = "com.apple.product-type.bundle.unit-test";
|
productType = "com.apple.product-type.bundle.unit-test";
|
||||||
};
|
};
|
||||||
EA179D172F1722BC00B1D54A /* SecureStorgageSampleUITests */ = {
|
EA179D172F1722BC00B1D54A /* SecureStorageSampleUITests */ = {
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = EA179D282F1722BC00B1D54A /* Build configuration list for PBXNativeTarget "SecureStorgageSampleUITests" */;
|
buildConfigurationList = EA179D282F1722BC00B1D54A /* Build configuration list for PBXNativeTarget "SecureStorageSampleUITests" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
EA179D142F1722BC00B1D54A /* Sources */,
|
EA179D142F1722BC00B1D54A /* Sources */,
|
||||||
EA179D152F1722BC00B1D54A /* Frameworks */,
|
EA179D152F1722BC00B1D54A /* Frameworks */,
|
||||||
@ -259,13 +259,13 @@
|
|||||||
EA179D1A2F1722BC00B1D54A /* PBXTargetDependency */,
|
EA179D1A2F1722BC00B1D54A /* PBXTargetDependency */,
|
||||||
);
|
);
|
||||||
fileSystemSynchronizedGroups = (
|
fileSystemSynchronizedGroups = (
|
||||||
EA179D1B2F1722BC00B1D54A /* SecureStorgageSampleUITests */,
|
EA179D1B2F1722BC00B1D54A /* SecureStorageSampleUITests */,
|
||||||
);
|
);
|
||||||
name = SecureStorgageSampleUITests;
|
name = SecureStorageSampleUITests;
|
||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
);
|
);
|
||||||
productName = SecureStorgageSampleUITests;
|
productName = SecureStorageSampleUITests;
|
||||||
productReference = EA179D182F1722BC00B1D54A /* SecureStorgageSampleUITests.xctest */;
|
productReference = EA179D182F1722BC00B1D54A /* SecureStorageSampleUITests.xctest */;
|
||||||
productType = "com.apple.product-type.bundle.ui-testing";
|
productType = "com.apple.product-type.bundle.ui-testing";
|
||||||
};
|
};
|
||||||
EA65D6E42F17DD6700C48466 /* SecureStorageSample Watch App */ = {
|
EA65D6E42F17DD6700C48466 /* SecureStorageSample Watch App */ = {
|
||||||
@ -371,7 +371,7 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
buildConfigurationList = EA179CFC2F1722BB00B1D54A /* Build configuration list for PBXProject "SecureStorgageSample" */;
|
buildConfigurationList = EA179CFC2F1722BB00B1D54A /* Build configuration list for PBXProject "SecureStorageSample" */;
|
||||||
developmentRegion = en;
|
developmentRegion = en;
|
||||||
hasScannedForEncodings = 0;
|
hasScannedForEncodings = 0;
|
||||||
knownRegions = (
|
knownRegions = (
|
||||||
@ -389,9 +389,9 @@
|
|||||||
projectDirPath = "";
|
projectDirPath = "";
|
||||||
projectRoot = "";
|
projectRoot = "";
|
||||||
targets = (
|
targets = (
|
||||||
EA179D002F1722BB00B1D54A /* SecureStorgageSample */,
|
EA179D002F1722BB00B1D54A /* SecureStorageSample */,
|
||||||
EA179D0D2F1722BC00B1D54A /* SecureStorgageSampleTests */,
|
EA179D0D2F1722BC00B1D54A /* SecureStorageSampleTests */,
|
||||||
EA179D172F1722BC00B1D54A /* SecureStorgageSampleUITests */,
|
EA179D172F1722BC00B1D54A /* SecureStorageSampleUITests */,
|
||||||
EA65D6E42F17DD6700C48466 /* SecureStorageSample Watch App */,
|
EA65D6E42F17DD6700C48466 /* SecureStorageSample Watch App */,
|
||||||
EA65D6F02F17DD6800C48466 /* SecureStorageSample Watch AppTests */,
|
EA65D6F02F17DD6800C48466 /* SecureStorageSample Watch AppTests */,
|
||||||
EA65D6FA2F17DD6800C48466 /* SecureStorageSample Watch AppUITests */,
|
EA65D6FA2F17DD6800C48466 /* SecureStorageSample Watch AppUITests */,
|
||||||
@ -492,12 +492,12 @@
|
|||||||
/* Begin PBXTargetDependency section */
|
/* Begin PBXTargetDependency section */
|
||||||
EA179D102F1722BC00B1D54A /* PBXTargetDependency */ = {
|
EA179D102F1722BC00B1D54A /* PBXTargetDependency */ = {
|
||||||
isa = PBXTargetDependency;
|
isa = PBXTargetDependency;
|
||||||
target = EA179D002F1722BB00B1D54A /* SecureStorgageSample */;
|
target = EA179D002F1722BB00B1D54A /* SecureStorageSample */;
|
||||||
targetProxy = EA179D0F2F1722BC00B1D54A /* PBXContainerItemProxy */;
|
targetProxy = EA179D0F2F1722BC00B1D54A /* PBXContainerItemProxy */;
|
||||||
};
|
};
|
||||||
EA179D1A2F1722BC00B1D54A /* PBXTargetDependency */ = {
|
EA179D1A2F1722BC00B1D54A /* PBXTargetDependency */ = {
|
||||||
isa = PBXTargetDependency;
|
isa = PBXTargetDependency;
|
||||||
target = EA179D002F1722BB00B1D54A /* SecureStorgageSample */;
|
target = EA179D002F1722BB00B1D54A /* SecureStorageSample */;
|
||||||
targetProxy = EA179D192F1722BC00B1D54A /* PBXContainerItemProxy */;
|
targetProxy = EA179D192F1722BC00B1D54A /* PBXContainerItemProxy */;
|
||||||
};
|
};
|
||||||
EA65D6F32F17DD6800C48466 /* PBXTargetDependency */ = {
|
EA65D6F32F17DD6800C48466 /* PBXTargetDependency */ = {
|
||||||
@ -642,7 +642,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
CODE_SIGN_ENTITLEMENTS = SecureStorgageSample/SecureStorgageSample.entitlements;
|
CODE_SIGN_ENTITLEMENTS = SecureStorageSample/SecureStorageSample.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEVELOPMENT_TEAM = 6R7KLBPBLZ;
|
DEVELOPMENT_TEAM = 6R7KLBPBLZ;
|
||||||
@ -659,7 +659,7 @@
|
|||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.mbrucedogs.SecureStorgageSample;
|
PRODUCT_BUNDLE_IDENTIFIER = com.mbrucedogs.SecureStorageSample;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
||||||
@ -676,7 +676,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
CODE_SIGN_ENTITLEMENTS = SecureStorgageSample/SecureStorgageSample.entitlements;
|
CODE_SIGN_ENTITLEMENTS = SecureStorageSample/SecureStorageSample.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEVELOPMENT_TEAM = 6R7KLBPBLZ;
|
DEVELOPMENT_TEAM = 6R7KLBPBLZ;
|
||||||
@ -693,7 +693,7 @@
|
|||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.mbrucedogs.SecureStorgageSample;
|
PRODUCT_BUNDLE_IDENTIFIER = com.mbrucedogs.SecureStorageSample;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
||||||
@ -714,7 +714,7 @@
|
|||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 26.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 26.0;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.mbrucedogs.SecureStorgageSampleTests;
|
PRODUCT_BUNDLE_IDENTIFIER = com.mbrucedogs.SecureStorageSampleTests;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
STRING_CATALOG_GENERATE_SYMBOLS = NO;
|
STRING_CATALOG_GENERATE_SYMBOLS = NO;
|
||||||
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
||||||
@ -722,7 +722,7 @@
|
|||||||
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SecureStorgageSample.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/SecureStorgageSample";
|
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SecureStorageSample.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/SecureStorageSample";
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
};
|
};
|
||||||
@ -735,7 +735,7 @@
|
|||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 26.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 26.0;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.mbrucedogs.SecureStorgageSampleTests;
|
PRODUCT_BUNDLE_IDENTIFIER = com.mbrucedogs.SecureStorageSampleTests;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
STRING_CATALOG_GENERATE_SYMBOLS = NO;
|
STRING_CATALOG_GENERATE_SYMBOLS = NO;
|
||||||
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
||||||
@ -743,7 +743,7 @@
|
|||||||
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SecureStorgageSample.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/SecureStorgageSample";
|
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SecureStorageSample.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/SecureStorageSample";
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
};
|
};
|
||||||
@ -754,7 +754,7 @@
|
|||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.mbrucedogs.SecureStorgageSampleUITests;
|
PRODUCT_BUNDLE_IDENTIFIER = com.mbrucedogs.SecureStorageSampleUITests;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
STRING_CATALOG_GENERATE_SYMBOLS = NO;
|
STRING_CATALOG_GENERATE_SYMBOLS = NO;
|
||||||
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
||||||
@ -762,7 +762,7 @@
|
|||||||
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
TEST_TARGET_NAME = SecureStorgageSample;
|
TEST_TARGET_NAME = SecureStorageSample;
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
};
|
};
|
||||||
@ -773,7 +773,7 @@
|
|||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.mbrucedogs.SecureStorgageSampleUITests;
|
PRODUCT_BUNDLE_IDENTIFIER = com.mbrucedogs.SecureStorageSampleUITests;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
STRING_CATALOG_GENERATE_SYMBOLS = NO;
|
STRING_CATALOG_GENERATE_SYMBOLS = NO;
|
||||||
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
||||||
@ -781,7 +781,7 @@
|
|||||||
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
TEST_TARGET_NAME = SecureStorgageSample;
|
TEST_TARGET_NAME = SecureStorageSample;
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
};
|
};
|
||||||
@ -797,13 +797,13 @@
|
|||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = SecureStorageSample;
|
INFOPLIST_KEY_CFBundleDisplayName = SecureStorageSample;
|
||||||
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
|
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
|
||||||
INFOPLIST_KEY_WKCompanionAppBundleIdentifier = com.mbrucedogs.SecureStorgageSample;
|
INFOPLIST_KEY_WKCompanionAppBundleIdentifier = com.mbrucedogs.SecureStorageSample;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.mbrucedogs.SecureStorgageSample.watchkitapp;
|
PRODUCT_BUNDLE_IDENTIFIER = com.mbrucedogs.SecureStorageSample.watchkitapp;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SDKROOT = watchos;
|
SDKROOT = watchos;
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
@ -830,13 +830,13 @@
|
|||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = SecureStorageSample;
|
INFOPLIST_KEY_CFBundleDisplayName = SecureStorageSample;
|
||||||
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
|
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
|
||||||
INFOPLIST_KEY_WKCompanionAppBundleIdentifier = com.mbrucedogs.SecureStorgageSample;
|
INFOPLIST_KEY_WKCompanionAppBundleIdentifier = com.mbrucedogs.SecureStorageSample;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.mbrucedogs.SecureStorgageSample.watchkitapp;
|
PRODUCT_BUNDLE_IDENTIFIER = com.mbrucedogs.SecureStorageSample.watchkitapp;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SDKROOT = watchos;
|
SDKROOT = watchos;
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
@ -944,7 +944,7 @@
|
|||||||
/* End XCBuildConfiguration section */
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
/* Begin XCConfigurationList section */
|
/* Begin XCConfigurationList section */
|
||||||
EA179CFC2F1722BB00B1D54A /* Build configuration list for PBXProject "SecureStorgageSample" */ = {
|
EA179CFC2F1722BB00B1D54A /* Build configuration list for PBXProject "SecureStorageSample" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
EA179D202F1722BC00B1D54A /* Debug */,
|
EA179D202F1722BC00B1D54A /* Debug */,
|
||||||
@ -953,7 +953,7 @@
|
|||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Release;
|
||||||
};
|
};
|
||||||
EA179D222F1722BC00B1D54A /* Build configuration list for PBXNativeTarget "SecureStorgageSample" */ = {
|
EA179D222F1722BC00B1D54A /* Build configuration list for PBXNativeTarget "SecureStorageSample" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
EA179D232F1722BC00B1D54A /* Debug */,
|
EA179D232F1722BC00B1D54A /* Debug */,
|
||||||
@ -962,7 +962,7 @@
|
|||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Release;
|
||||||
};
|
};
|
||||||
EA179D252F1722BC00B1D54A /* Build configuration list for PBXNativeTarget "SecureStorgageSampleTests" */ = {
|
EA179D252F1722BC00B1D54A /* Build configuration list for PBXNativeTarget "SecureStorageSampleTests" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
EA179D262F1722BC00B1D54A /* Debug */,
|
EA179D262F1722BC00B1D54A /* Debug */,
|
||||||
@ -971,7 +971,7 @@
|
|||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Release;
|
||||||
};
|
};
|
||||||
EA179D282F1722BC00B1D54A /* Build configuration list for PBXNativeTarget "SecureStorgageSampleUITests" */ = {
|
EA179D282F1722BC00B1D54A /* Build configuration list for PBXNativeTarget "SecureStorageSampleUITests" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
EA179D292F1722BC00B1D54A /* Debug */,
|
EA179D292F1722BC00B1D54A /* Debug */,
|
||||||
@ -0,0 +1,116 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "2600"
|
||||||
|
version = "1.7">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES"
|
||||||
|
buildArchitectures = "Automatic">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "EA65D6E42F17DD6700C48466"
|
||||||
|
BuildableName = "SecureStorageSample Watch App.app"
|
||||||
|
BlueprintName = "SecureStorageSample Watch App"
|
||||||
|
ReferencedContainer = "container:SecureStorageSample.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "EA179D002F1722BB00B1D54A"
|
||||||
|
BuildableName = "SecureStorageSample.app"
|
||||||
|
BlueprintName = "SecureStorageSample"
|
||||||
|
ReferencedContainer = "container:SecureStorageSample.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
shouldAutocreateTestPlan = "YES">
|
||||||
|
<Testables>
|
||||||
|
<TestableReference
|
||||||
|
skipped = "NO"
|
||||||
|
parallelizable = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "EA65D6F02F17DD6800C48466"
|
||||||
|
BuildableName = "SecureStorageSample Watch AppTests.xctest"
|
||||||
|
BlueprintName = "SecureStorageSample Watch AppTests"
|
||||||
|
ReferencedContainer = "container:SecureStorageSample.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</TestableReference>
|
||||||
|
<TestableReference
|
||||||
|
skipped = "NO"
|
||||||
|
parallelizable = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "EA65D6FA2F17DD6800C48466"
|
||||||
|
BuildableName = "SecureStorageSample Watch AppUITests.xctest"
|
||||||
|
BlueprintName = "SecureStorageSample Watch AppUITests"
|
||||||
|
ReferencedContainer = "container:SecureStorageSample.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</TestableReference>
|
||||||
|
</Testables>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "EA65D6E42F17DD6700C48466"
|
||||||
|
BuildableName = "SecureStorageSample Watch App.app"
|
||||||
|
BlueprintName = "SecureStorageSample Watch App"
|
||||||
|
ReferencedContainer = "container:SecureStorageSample.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "EA65D6E42F17DD6700C48466"
|
||||||
|
BuildableName = "SecureStorageSample Watch App.app"
|
||||||
|
BlueprintName = "SecureStorageSample Watch App"
|
||||||
|
ReferencedContainer = "container:SecureStorageSample.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
||||||
@ -0,0 +1,78 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "2600"
|
||||||
|
version = "1.7">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES"
|
||||||
|
buildArchitectures = "Automatic">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "EA179D002F1722BB00B1D54A"
|
||||||
|
BuildableName = "SecureStorageSample.app"
|
||||||
|
BlueprintName = "SecureStorageSample"
|
||||||
|
ReferencedContainer = "container:SecureStorageSample.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
shouldAutocreateTestPlan = "YES">
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "EA179D002F1722BB00B1D54A"
|
||||||
|
BuildableName = "SecureStorageSample.app"
|
||||||
|
BlueprintName = "SecureStorageSample"
|
||||||
|
ReferencedContainer = "container:SecureStorageSample.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "EA179D002F1722BB00B1D54A"
|
||||||
|
BuildableName = "SecureStorageSample.app"
|
||||||
|
BlueprintName = "SecureStorageSample"
|
||||||
|
ReferencedContainer = "container:SecureStorageSample.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
||||||
@ -2,6 +2,6 @@
|
|||||||
<Workspace
|
<Workspace
|
||||||
version = "1.0">
|
version = "1.0">
|
||||||
<FileRef
|
<FileRef
|
||||||
location = "container:SecureStorgageSample.xcodeproj">
|
location = "container:SecureStorageSample.xcodeproj">
|
||||||
</FileRef>
|
</FileRef>
|
||||||
</Workspace>
|
</Workspace>
|
||||||
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// ContentView.swift
|
// ContentView.swift
|
||||||
// SecureStorgageSample
|
// SecureStorageSample
|
||||||
//
|
//
|
||||||
// Main navigation view with tabbed interface for all LocalData demos.
|
// Main navigation view with tabbed interface for all LocalData demos.
|
||||||
//
|
//
|
||||||
69
SecureStorageSample/SecureStorageSampleApp.swift
Normal file
69
SecureStorageSample/SecureStorageSampleApp.swift
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
//
|
||||||
|
// SecureStorageSampleApp.swift
|
||||||
|
// SecureStorageSample
|
||||||
|
//
|
||||||
|
// Created by Matt Bruce on 1/13/26.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
import LocalData
|
||||||
|
|
||||||
|
@main
|
||||||
|
struct SecureStorageSampleApp: App {
|
||||||
|
init() {
|
||||||
|
_ = WatchConnectivityService.shared
|
||||||
|
Task {
|
||||||
|
// 1. Global Encryption Configuration
|
||||||
|
// We isolate our library's master key in the Keychain by providing a specific service
|
||||||
|
// and account name. This prevents conflicts with other apps using the same library.
|
||||||
|
// We also set PBKDF2 iterations for consistent security across the app.
|
||||||
|
let config = EncryptionConfiguration(
|
||||||
|
masterKeyService: "SecureStorageSample",
|
||||||
|
masterKeyAccount: "AppMasterKey",
|
||||||
|
pbkdf2Iterations: 20_000
|
||||||
|
)
|
||||||
|
await StorageRouter.shared.updateEncryptionConfiguration(config)
|
||||||
|
|
||||||
|
// 2. Global Sync Configuration
|
||||||
|
// Overriding the default 100KB limit for automatic Watch sync to 50KB.
|
||||||
|
// This demonstrates how to tune performance for low-bandwidth scenarios.
|
||||||
|
let syncConfig = SyncConfiguration(maxAutoSyncSize: 50_000)
|
||||||
|
await StorageRouter.shared.updateSyncConfiguration(syncConfig)
|
||||||
|
|
||||||
|
// 3. Global File Storage Configuration
|
||||||
|
// We scope all our library files into a "SecureStorage" sub-directory
|
||||||
|
// underneath the standard Documents/Caches folders.
|
||||||
|
let fileConfig = FileStorageConfiguration(subDirectory: "SecureStorage")
|
||||||
|
await StorageRouter.shared.updateFileStorageConfiguration(fileConfig)
|
||||||
|
|
||||||
|
// 4. Global Storage Defaults
|
||||||
|
// Setting default identifiers for Keychain and App Groups.
|
||||||
|
// This allows keys to be defined more concisely without repeating these IDs.
|
||||||
|
let storageConfig = StorageConfiguration(
|
||||||
|
defaultKeychainService: StorageServiceIdentifiers.bundleIdentifier,
|
||||||
|
defaultAppGroupIdentifier: StorageServiceIdentifiers.appGroupIdentifier
|
||||||
|
)
|
||||||
|
await StorageRouter.shared.updateStorageConfiguration(storageConfig)
|
||||||
|
|
||||||
|
do {
|
||||||
|
try await StorageRouter.shared.registerCatalog(AppStorageCatalog.self)
|
||||||
|
} catch {
|
||||||
|
assertionFailure("Storage catalog registration failed: \(error)")
|
||||||
|
}
|
||||||
|
await StorageRouter.shared.registerKeyMaterialProvider(
|
||||||
|
ExternalKeyMaterialProvider(),
|
||||||
|
for: SampleKeyMaterialSources.external
|
||||||
|
)
|
||||||
|
}
|
||||||
|
#if DEBUG
|
||||||
|
let report = StorageAuditReport.renderText(for: AppStorageCatalog.self)
|
||||||
|
print(report)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
var body: some Scene {
|
||||||
|
WindowGroup {
|
||||||
|
ContentView()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import LocalData
|
import LocalData
|
||||||
|
import SharedKit
|
||||||
extension StorageKeys {
|
extension StorageKeys {
|
||||||
/// Stores a shared setting in App Group UserDefaults.
|
/// Stores a shared setting in App Group UserDefaults.
|
||||||
/// - Domain: App Group UserDefaults
|
/// - Domain: App Group UserDefaults
|
||||||
@ -10,7 +10,7 @@ extension StorageKeys {
|
|||||||
typealias Value = String
|
typealias Value = String
|
||||||
|
|
||||||
let name = "app_group_setting"
|
let name = "app_group_setting"
|
||||||
let domain: StorageDomain = .appGroupUserDefaults(identifier: AppGroupConfiguration.identifier)
|
let domain: StorageDomain = .appGroupUserDefaults(identifier: StorageServiceIdentifiers.appGroupIdentifier)
|
||||||
let security: SecurityPolicy = .none
|
let security: SecurityPolicy = .none
|
||||||
let serializer: Serializer<String> = .json
|
let serializer: Serializer<String> = .json
|
||||||
let owner = "SampleApp"
|
let owner = "SampleApp"
|
||||||
@ -24,7 +24,7 @@ extension StorageKeys {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var domain: StorageDomain {
|
var domain: StorageDomain {
|
||||||
.appGroupFileSystem(identifier: AppGroupConfiguration.identifier, directory: directory)
|
.appGroupFileSystem(identifier: StorageServiceIdentifiers.appGroupIdentifier, directory: directory)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import LocalData
|
import LocalData
|
||||||
|
import SharedKit
|
||||||
|
|
||||||
extension StorageKeys {
|
extension StorageKeys {
|
||||||
/// Stores user preferences in App Group UserDefaults.
|
/// Stores user preferences in App Group UserDefaults.
|
||||||
@ -10,7 +11,7 @@ extension StorageKeys {
|
|||||||
typealias Value = [String: AnyCodable]
|
typealias Value = [String: AnyCodable]
|
||||||
|
|
||||||
let name = "user_preferences"
|
let name = "user_preferences"
|
||||||
let domain: StorageDomain = .appGroupUserDefaults(identifier: AppGroupConfiguration.identifier)
|
let domain: StorageDomain = .appGroupUserDefaults(identifier: StorageServiceIdentifiers.appGroupIdentifier)
|
||||||
let security: SecurityPolicy = .none
|
let security: SecurityPolicy = .none
|
||||||
let serializer: Serializer<[String: AnyCodable]> = .json
|
let serializer: Serializer<[String: AnyCodable]> = .json
|
||||||
let owner = "SampleApp"
|
let owner = "SampleApp"
|
||||||
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// EncryptedStorageDemo.swift
|
// EncryptedStorageDemo.swift
|
||||||
// SecureStorgageSample
|
// SecureStorageSample
|
||||||
//
|
//
|
||||||
// Demonstrates encrypted file storage with LocalData package.
|
// Demonstrates encrypted file storage with LocalData package.
|
||||||
//
|
//
|
||||||
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// FileSystemDemo.swift
|
// FileSystemDemo.swift
|
||||||
// SecureStorgageSample
|
// SecureStorageSample
|
||||||
//
|
//
|
||||||
// Demonstrates file system storage with LocalData package.
|
// Demonstrates file system storage with LocalData package.
|
||||||
//
|
//
|
||||||
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// KeychainDemo.swift
|
// KeychainDemo.swift
|
||||||
// SecureStorgageSample
|
// SecureStorageSample
|
||||||
//
|
//
|
||||||
// Demonstrates Keychain storage with LocalData package.
|
// Demonstrates Keychain storage with LocalData package.
|
||||||
//
|
//
|
||||||
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// PlatformSyncDemo.swift
|
// PlatformSyncDemo.swift
|
||||||
// SecureStorgageSample
|
// SecureStorageSample
|
||||||
//
|
//
|
||||||
// Demonstrates platform availability and sync policies with LocalData package.
|
// Demonstrates platform availability and sync policies with LocalData package.
|
||||||
//
|
//
|
||||||
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// UserDefaultsDemo.swift
|
// UserDefaultsDemo.swift
|
||||||
// SecureStorgageSample
|
// SecureStorageSample
|
||||||
//
|
//
|
||||||
// Demonstrates UserDefaults storage with LocalData package.
|
// Demonstrates UserDefaults storage with LocalData package.
|
||||||
//
|
//
|
||||||
@ -1,14 +1,14 @@
|
|||||||
//
|
//
|
||||||
// SecureStorgageSampleTests.swift
|
// SecureStorageSampleTests.swift
|
||||||
// SecureStorgageSampleTests
|
// SecureStorageSampleTests
|
||||||
//
|
//
|
||||||
// Created by Matt Bruce on 1/13/26.
|
// Created by Matt Bruce on 1/13/26.
|
||||||
//
|
//
|
||||||
|
|
||||||
import Testing
|
import Testing
|
||||||
@testable import SecureStorgageSample
|
@testable import SecureStorageSample
|
||||||
|
|
||||||
struct SecureStorgageSampleTests {
|
struct SecureStorageSampleTests {
|
||||||
|
|
||||||
@Test func example() async throws {
|
@Test func example() async throws {
|
||||||
// Write your test here and use APIs like `#expect(...)` to check expected conditions.
|
// Write your test here and use APIs like `#expect(...)` to check expected conditions.
|
||||||
@ -1,13 +1,13 @@
|
|||||||
//
|
//
|
||||||
// SecureStorgageSampleUITests.swift
|
// SecureStorageSampleUITests.swift
|
||||||
// SecureStorgageSampleUITests
|
// SecureStorageSampleUITests
|
||||||
//
|
//
|
||||||
// Created by Matt Bruce on 1/13/26.
|
// Created by Matt Bruce on 1/13/26.
|
||||||
//
|
//
|
||||||
|
|
||||||
import XCTest
|
import XCTest
|
||||||
|
|
||||||
final class SecureStorgageSampleUITests: XCTestCase {
|
final class SecureStorageSampleUITests: XCTestCase {
|
||||||
|
|
||||||
override func setUpWithError() throws {
|
override func setUpWithError() throws {
|
||||||
// Put setup code here. This method is called before the invocation of each test method in the class.
|
// Put setup code here. This method is called before the invocation of each test method in the class.
|
||||||
@ -1,13 +1,13 @@
|
|||||||
//
|
//
|
||||||
// SecureStorgageSampleUITestsLaunchTests.swift
|
// SecureStorageSampleUITestsLaunchTests.swift
|
||||||
// SecureStorgageSampleUITests
|
// SecureStorageSampleUITests
|
||||||
//
|
//
|
||||||
// Created by Matt Bruce on 1/13/26.
|
// Created by Matt Bruce on 1/13/26.
|
||||||
//
|
//
|
||||||
|
|
||||||
import XCTest
|
import XCTest
|
||||||
|
|
||||||
final class SecureStorgageSampleUITestsLaunchTests: XCTestCase {
|
final class SecureStorageSampleUITestsLaunchTests: XCTestCase {
|
||||||
|
|
||||||
override class var runsForEachTargetApplicationUIConfiguration: Bool {
|
override class var runsForEachTargetApplicationUIConfiguration: Bool {
|
||||||
true
|
true
|
||||||
@ -1,29 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>SchemeUserState</key>
|
|
||||||
<dict>
|
|
||||||
<key>SecureStorageSample Watch App.xcscheme_^#shared#^_</key>
|
|
||||||
<dict>
|
|
||||||
<key>orderHint</key>
|
|
||||||
<integer>1</integer>
|
|
||||||
</dict>
|
|
||||||
<key>SecureStorageWatch Watch App.xcscheme_^#shared#^_</key>
|
|
||||||
<dict>
|
|
||||||
<key>orderHint</key>
|
|
||||||
<integer>1</integer>
|
|
||||||
</dict>
|
|
||||||
<key>SecureStorgageSample.xcscheme_^#shared#^_</key>
|
|
||||||
<dict>
|
|
||||||
<key>orderHint</key>
|
|
||||||
<integer>0</integer>
|
|
||||||
</dict>
|
|
||||||
<key>SecureStorgageSampleWatch.xcscheme_^#shared#^_</key>
|
|
||||||
<dict>
|
|
||||||
<key>orderHint</key>
|
|
||||||
<integer>3</integer>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
import Foundation
|
|
||||||
import SharedKit
|
|
||||||
|
|
||||||
enum AppGroupConfiguration {
|
|
||||||
static var identifier: String {
|
|
||||||
StorageServiceIdentifiers.appGroupIdentifier
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
//
|
|
||||||
// SecureStorgageSampleApp.swift
|
|
||||||
// SecureStorgageSample
|
|
||||||
//
|
|
||||||
// Created by Matt Bruce on 1/13/26.
|
|
||||||
//
|
|
||||||
|
|
||||||
import SwiftUI
|
|
||||||
import LocalData
|
|
||||||
|
|
||||||
@main
|
|
||||||
struct SecureStorgageSampleApp: App {
|
|
||||||
init() {
|
|
||||||
_ = WatchConnectivityService.shared
|
|
||||||
do {
|
|
||||||
try StorageRouter.shared.registerCatalog(AppStorageCatalog.self)
|
|
||||||
} catch {
|
|
||||||
assertionFailure("Storage catalog registration failed: \(error)")
|
|
||||||
}
|
|
||||||
Task {
|
|
||||||
await StorageRouter.shared.registerKeyMaterialProvider(
|
|
||||||
ExternalKeyMaterialProvider(),
|
|
||||||
for: SampleKeyMaterialSources.external
|
|
||||||
)
|
|
||||||
}
|
|
||||||
#if DEBUG
|
|
||||||
let report = StorageAuditReport.renderText(for: AppStorageCatalog.self)
|
|
||||||
print(report)
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
var body: some Scene {
|
|
||||||
WindowGroup {
|
|
||||||
ContentView()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user