Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
7530b3f
Updated build to Swift 6.1 and demo to iOS18/macOS15
itsniper Jul 22, 2025
696b632
Migrated peripheral UI to Observable
itsniper Jul 22, 2025
a91d0ec
Refactored central UI to Observable
itsniper Jul 22, 2025
75b145f
Fixed incorrect concurrent queues
itsniper Jul 22, 2025
1e3f961
Merge pull request #14 from Five3Apps/11-migrating-from-the-observabl…
itsniper Jul 22, 2025
dec7edc
Pulled in updated Willow and updated for Swift 6
itsniper Jun 2, 2026
165a372
Merge pull request #16 from Five3Apps/15-willow-swift-6-concurrency
itsniper Jun 2, 2026
7d84735
Updated demo to Swift 6 with Complete concurrency checking
itsniper Jul 22, 2025
f7a96a2
Added Swift 6 concurrency investigation report
itsniper Jun 3, 2026
3d04228
Updated peripheral and logging to Swift Concurrency
itsniper Sep 27, 2025
c87c683
Updates for AI coding agents
itsniper Jun 9, 2026
80f0c04
Introduce BluetoothActor to serialize CoreBluetooth state (Step 1 of …
itsniper Jun 11, 2026
83e5bca
Apply Copilot PR review fixes from #23 evaluation
itsniper Jun 13, 2026
3503fbb
Merge pull request #23 from Five3Apps/13-make-bluetoothmanager-swift-…
itsniper Jun 13, 2026
e48ca32
Make Peripheral a Sendable value type (Step 2 of 5 for #10)
itsniper Jun 18, 2026
3fcda54
Narrowed the scope of `SendableWrapper`
itsniper Jun 19, 2026
54deb25
Apply suggestions from Copilot code review
itsniper Jun 20, 2026
3523f59
Added PR #23 review report
itsniper Jun 13, 2026
d5bab56
Added plan and critique for removing Combine
itsniper Jun 24, 2026
9272827
Merge pull request #24 from Five3Apps/17-peripheral-sendable
itsniper Jun 23, 2026
f2439f5
Replace Combine event surfaces with AsyncStream broadcaster (Step 3 o…
itsniper Jun 24, 2026
a683a48
Updated agent instruction pointer for Demo app
itsniper Jun 23, 2026
66f77a6
Collapse BluetoothManager into ReliaBLEManager (Step 4 of 5, #10)
itsniper Jun 27, 2026
3ffd9c0
Addressed Copilot's PR feedback
itsniper Jun 27, 2026
1b00e41
Merge pull request #25 from Five3Apps/12-remove-combine
itsniper Jun 24, 2026
436ef62
Added Swift 6 strict concurrency checking (Step 5 of 5, #10)
itsniper Jun 27, 2026
5b30b44
Merge pull request #26 from Five3Apps/18-collapse-bluetoothmanager
itsniper Jun 27, 2026
de64b18
[demo] Route SwiftData writes through background DeviceStoreActor (#20)
itsniper Jun 27, 2026
2af69d7
Merge pull request #27 from Five3Apps/19-strict-concurrency-flag
itsniper Jun 27, 2026
84f880a
Address Copilot PR feedback on DeviceStoreActor (#20)
itsniper Jun 27, 2026
42edd51
Merge pull request #28 from Five3Apps/20-demo-background-data
itsniper Jun 27, 2026
baa0896
Address PR #29 review: bound discovery buffer, fix init race, order d…
itsniper Jun 28, 2026
daa5601
Update DocC for suspending authorize, connect error, and bounded disc…
itsniper Jun 28, 2026
a0f23d6
Fix demo crash when deleting SwiftData discoveries on device
itsniper Jun 28, 2026
e40bb7d
[demo] Lazily create CBPeripheralManager only when starting advertising
itsniper Jun 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .agents/skills/xcodebuildmcp/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
name: xcodebuildmcp
description: Official skill for XcodeBuildMCP. Use when doing iOS/macOS/watchOS/tvOS/visionOS work (build, test, run, debug, log, UI automation).
---

# XcodeBuildMCP

Use XcodeBuildMCP tools instead of raw `xcodebuild`, `xcrun`, or `simctl`.

Capabilities:
- Session defaults: Configure project, scheme, simulator, and device defaults to avoid repetitive parameters
- Project discovery: Find Xcode projects/workspaces, list schemes, inspect build settings
- Simulator workflows: Build, run, test, install, and launch apps on iOS simulators; manage simulator state (boot, erase, location, appearance)
- Device workflows: Build, test, install, and launch apps on physical devices with code signing
- macOS workflows: Build, run, and test macOS applications
- Log capture: Stream and capture logs from simulators and devices
- LLDB debugging: Attach debugger, set breakpoints, inspect stack traces and variables, execute LLDB commands
- UI automation: Capture screenshots, inspect view hierarchy with coordinates, perform taps/swipes/gestures, type text, press hardware buttons
- SwiftPM: Build, run, test, and manage Swift Package Manager projects
- Project scaffolding: Generate new iOS/macOS project templates

Only simulator workflow tools are enabled by default. If capabilities like device, macOS, debugging, or UI automation are not available, the user must configure XcodeBuildMCP to enable them. See https://xcodebuildmcp.com/docs/configuration for workflow configuration.

## Step 1: Establish Session Context

- Call `session_show_defaults` before the first build/run/test action in a session.
- Use `discover_projs` only when defaults show missing or incorrect project/workspace context.
- Do not run discovery speculatively or in parallel with `session_show_defaults`.
- For simulator run intent, prefer the combined build-and-run tool instead of separate build then run calls.
- Do not chain build-only then build-and-run unless the user explicitly requests both.

## Step 2: Understand Workflow-Scoped Tool Availability

- Not all tools are enabled by default; tool availability depends on enabled workflows.
- If a tool is expected but missing, check enabled workflows first.
- Update enabled workflows in `.xcodebuildmcp/config.yaml`, then ask user to reload/restart the session to surface refreshes.

## Step 3: Report Context Clearly

- Return the active defaults context used for execution (project/workspace, scheme, simulator/device).
- For failures, include the exact failing step and the next actionable command/tool call.
22 changes: 22 additions & 0 deletions .xcodebuildmcp/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
schemaVersion: 1
enabledWorkflows:
- macos
- simulator
- coverage
- debugging
- device
- project-discovery
- swift-package
- xcode-ide
debug: false
sentryDisabled: false
sessionDefaults:
scheme: ReliaBLE Demo
simulatorName: iPhone 17 Pro Max
simulatorId: C0B74568-2B47-4981-ACA8-389277E1BB02
deviceId: 3D0082F1-03D3-5FD1-8F46-55595E121B15
workspacePath: /Users/jus10sb/Documents/Five3Apps/Projects/OpenSource/ReliaBLE/ReliaBLE.xcworkspace
setupPreferences:
platforms:
- iOS
- macOS
58 changes: 58 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# AGENTS.md

This file provides guidance to AI Agents (Claude Code, Codex, Grok Build, OpenCode, etc.) when working with code in this repository.

## Repository layout

Two related projects share this repo:

- **ReliaBLE library** (this directory) — Swift Package at `Package.swift` / `Sources/` / `Tests/`. swift-tools-version 6.1, iOS 18+ / macOS 10.15+, builds under **Swift 6 with complete concurrency checking**. This is the supported, shipped product.
- **Demo app** — `Demo/ReliaBLE Demo/`, consumes the library locally. Has its own `Demo/CLAUDE.md` with different conventions (looser concurrency, exploratory code). Treat it as a separate project — don't carry its patterns back into the library.

Open `ReliaBLE.xcworkspace` at the root to work on both together.

### Working on the Demo app

The Demo is a **separate project** with its own conventions and build tooling, kept out of the library's context on purpose:

- Before performing ANY Demo build/run/test task, **read `Demo/CLAUDE.md` first** — it documents the Demo's conventions and its required build tooling (XcodeBuildMCP, not raw `xcodebuild`).
- For substantial Demo work, **delegate to a sub-agent** and instruct it to read `Demo/CLAUDE.md` first. This keeps Demo conventions in an isolated context so they don't pollute the main library session. (A sub-agent does not auto-load `Demo/CLAUDE.md` — tell it to read that file explicitly.)
- Do not carry Demo patterns back into the library.

## Build, test

```sh
swift build # build all targets
swift test # run ReliaBLETests
swift test --filter ReliaBLETests.correctFunction # single test
```

## Architecture

### Three-target SPM trick for CoreBluetooth mocking

The package declares **three targets** that share a single source tree to make `CoreBluetooth` mockable in tests without polluting the production binary:

- `ReliaBLE` — production target. Uses real `CoreBluetooth`. Includes `Sources/ReliaBLE/CBCentralManagerFactory.swift`, a thin enum that returns a real `CBCentralManager`.
- `ReliaBLEMock` — same sources as `ReliaBLE`, but **excludes** `CBCentralManagerFactory.swift` and the DocC catalog, and links `CoreBluetoothMock` (Nordic Semi). In `Sources/ReliaBLEMock/CoreBluetoothMockAliases.swift`, public typealiases rebind `CBCentralManager`, `CBPeripheral`, `CBCentralManagerFactory`, etc. to their `CBM*` mock counterparts.
- `ReliaBLETests` — depends on `ReliaBLEMock` (not `ReliaBLE`).

**Consequence:** the library code only ever calls `CBCentralManagerFactory.instance(...)`, never `CBCentralManager(...)` directly. The factory's identity is swapped at compile time per target. When editing core BLE code, keep this constraint — `import CoreBluetooth` is fine, but instantiate the central via the factory.

### Swift Concurrency

The library is built with Swift 6 and **complete concurrency checking**. The `ReliaBLEManager` public API should be callable from `@MainActor`, but the library itself should avoid `@MainActor` and instead use `@BluetoothActor` (a custom actor defined in `BluetoothManager.swift`) to serialize all Bluetooth interactions. This keeps the library thread-safe and allows the integrating app to decide how to bridge to the main thread for UI updates.

### Logging

`LoggingService` wraps Willow's `Logger` with an async execution queue. The service is `Sendable` and passed by reference into both managers. Default writer is an `OSLogWriter` (`subsystem: com.five3apps.relia-ble`, `category: BLE`), configurable via `ReliaBLEConfig`. Logging is **disabled by default** — `config.loggingEnabled` must be set to true. Log calls take a `tags: [LogTag]` array; use `.category(.scanning)`, `.peripheral(id)`, etc. rather than embedding the category in the message.

### Authorization flow

`ReliaBLEManager.init` does **not** instantiate `CBCentralManager` unless the user has already granted `.allowedAlways`. This is deliberate so the integrating app controls when the iOS permission prompt appears — callers invoke `authorizeBluetooth()` when they want the prompt. Preserve this lazy-init behavior when touching `BluetoothManager.setupCentralManager()`.

## Notes for editing

- Public API on `ReliaBLEManager` is the supported surface for external consumers. Adding/removing methods there is a breaking change.
- `forceMock: true` is currently passed to `CBCentralManagerFactory.instance(...)` in `BluetoothManager`. The production factory ignores this parameter; the mock factory honors it. Don't "clean it up" — it's load-bearing for the test target.
- DocC catalog lives at `Sources/ReliaBLE/Documentation.docc/`. The `swift-docc-plugin` is a package dep so `swift package generate-documentation` works. This documentation **must** be kept up to date with the public API on `ReliaBLEManager` and the overall architecture and usage patterns.
1 change: 1 addition & 0 deletions CLAUDE.md
71 changes: 71 additions & 0 deletions Demo/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# AGENTS.md

This file provides guidance to AI Agents (Claude Code, Codex, Grok Build, OpenCode, etc.) when working with code in this repository.

## What this project is

The **ReliaBLE Demo** is a sample iOS app whose only purpose is to exercise and show off the ReliaBLE library that lives one directory up. It is not shipped, not a product, and not held to the same bar as the library:

- **Looser style bar.** The target does build under Swift 6 complete concurrency checking, but `@Observable` view models, `DispatchQueue.main`-based Combine sinks, `try?` discards, and `print(...)` for error paths are all fine here. Don't port library patterns (actors, custom `LoggingService`, three-target mocking, etc.) into the demo unless they're needed to talk to the library's public API.
- **Exploratory code is welcome.** Quick wiring, hardcoded values, `TODO` stubs, and view-model shortcuts are acceptable as long as they demonstrate a library feature clearly.
- **Don't refactor demo code "for quality"** unless asked. If something looks wrong in the demo, it's often deliberately minimal.

If you're working on a feature here and it forces you to also change the library, surface that — it usually means the library's public API needs work, which is a separate conversation.

## Build / run

Uses `CoreBluetooth` (central) and `CBPeripheralManager` (peripheral), plus SwiftData. The root workspace must be used — not the project file — so the local `ReliaBLE` package resolves correctly.

**Preferred: XcodeBuildMCP**

When using XcodeBuildMCP, use the installed XcodeBuildMCP skill before calling XcodeBuildMCP tools. Always verify defaults before the first build.

```
workspace: /path/to/ReliaBLE/ReliaBLE.xcworkspace
scheme: ReliaBLE Demo
```

- Simulator: `build_run_sim` (BLE radio unavailable — UI only)
- Device: `build_run_device` with `-allowProvisioningUpdates`; on first run the user must trust the developer certificate at **Settings → General → VPN & Device Management**

Real device recommended for full BLE. The peripheral tab requires a device with a BLE radio to actually advertise.

To open in Xcode manually:

```sh
open ../ReliaBLE.xcworkspace # from the Demo/ dir
```

Scheme: **"ReliaBLE Demo"**.

## App structure

`ReliaBLE Demo.xcodeproj` lives at `Demo/ReliaBLE Demo/ReliaBLE Demo.xcodeproj`. The app is a 3-tab SwiftUI app:

- **Central** (`Central/`) — uses `ReliaBLEManager` (the library) to scan, surfaces discoveries into a SwiftData store. `CentralView` subscribes to the library's `AsyncStream` surfaces in `.task { for await … }` loops; `CentralViewModel` holds UI state and BLE actions only. All SwiftData writes go through `DeviceStoreActor` (manual `ModelActor` conformance). State observed via `@Observable`.
- **Peripheral** (`Peripheral/`) — uses raw `CBPeripheralManager` directly (not the library — the library doesn't yet expose peripheral mode). This is intentional; the demo shows both sides of BLE even though only the central side flows through ReliaBLE.
- **Settings** (`Settings/`) — app-level toggles.

### How the library is wired in

- `ReliaBLE_DemoApp.swift` constructs a single `ReliaBLEManager` with `loggingEnabled = true` and injects it via a custom `EnvironmentKey` (`@Environment(\.bleManager)`).
- There's also a `BLEManagerKey.defaultValue` for previews — keep that working when changing the env injection.
- A `ModelContainer` for `Device` and `DiscoveryEvent` is set on the root scene. `CentralView` creates a `DeviceStoreActor` off the main thread via `DeviceStoreActor.create(container:)` and routes all SwiftData writes through it as the library emits events. Reads stay on `@MainActor` via `@Query`.

## Swift Concurrency

The library is built with Swift 6 and **complete concurrency checking**. Therefore, `ReliaBLE Demo` is also built with Swift 6 and complete concurrency checking.

### SwiftData models

- `Device` — one row per unique discovered peripheral (by `ReliaBLE.Peripheral.id`), updated on each `discoveredPeripherals` stream tick via `DeviceStoreActor.syncDevices`.
- `DiscoveryEvent` — one row per raw advertisement (every `peripheralDiscoveries` event), inserted via `DeviceStoreActor.insertDiscovery`. Grows quickly; "Clear All Data" in the Central view nukes both tables.

### Off-main persistence pattern

`DeviceStoreActor` is the canonical pattern for library consumers: hold `ReliaBLEManager` on the main actor, consume `AsyncStream`s in `.task`, and `await` the store for every SwiftData write. See the file-level comment in `Central/DeviceStoreActor.swift`.

## Don't

- Don't add the library's `CBCentralManagerFactory` indirection here — the demo imports `CoreBluetooth` directly for the peripheral side and that's fine.
- Don't replace `print(...)` debug calls in `CentralViewModel` with a logging service. The library has logging; the demo doesn't need one.
1 change: 1 addition & 0 deletions Demo/CLAUDE.md
24 changes: 13 additions & 11 deletions Demo/ReliaBLE Demo/ReliaBLE Demo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@
attributes = {
BuildIndependentTargetsInParallel = 1;
LastSwiftUpdateCheck = 1610;
LastUpgradeCheck = 1620;
LastUpgradeCheck = 1640;
TargetAttributes = {
8B771A932CEC3B9A002F0E31 = {
CreatedOnToolsVersion = 16.1;
Expand Down Expand Up @@ -316,6 +316,7 @@
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = AU92CYH9BP;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
Expand All @@ -338,7 +339,10 @@
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
SWIFT_APPROACHABLE_CONCURRENCY = YES;
SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_STRICT_CONCURRENCY = complete;
};
name = Debug;
};
Expand Down Expand Up @@ -378,6 +382,7 @@
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = AU92CYH9BP;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
Expand All @@ -392,7 +397,10 @@
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SWIFT_APPROACHABLE_CONCURRENCY = YES;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;
SWIFT_STRICT_CONCURRENCY = complete;
};
name = Release;
};
Expand All @@ -406,7 +414,6 @@
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "\"ReliaBLE Demo/Preview Content\"";
DEVELOPMENT_TEAM = AU92CYH9BP;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
Expand All @@ -424,10 +431,10 @@
"INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 17.6;
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 14.0;
MACOSX_DEPLOYMENT_TARGET = 15.0;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = "com.five3apps.ReliaBLE-Demo";
PRODUCT_NAME = "$(TARGET_NAME)";
Expand All @@ -451,7 +458,6 @@
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "\"ReliaBLE Demo/Preview Content\"";
DEVELOPMENT_TEAM = AU92CYH9BP;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
Expand All @@ -469,10 +475,10 @@
"INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 17.6;
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 14.0;
MACOSX_DEPLOYMENT_TARGET = 15.0;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = "com.five3apps.ReliaBLE-Demo";
PRODUCT_NAME = "$(TARGET_NAME)";
Expand All @@ -493,7 +499,6 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = AU92CYH9BP;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 18.1;
MACOSX_DEPLOYMENT_TARGET = 15.1;
Expand All @@ -517,7 +522,6 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = AU92CYH9BP;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 18.1;
MACOSX_DEPLOYMENT_TARGET = 15.1;
Expand All @@ -540,7 +544,6 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = AU92CYH9BP;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 18.1;
MACOSX_DEPLOYMENT_TARGET = 15.1;
Expand All @@ -563,7 +566,6 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = AU92CYH9BP;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 18.1;
MACOSX_DEPLOYMENT_TARGET = 15.1;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1620"
LastUpgradeVersion = "1640"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
Loading
Loading