Skip to content

Commit

Permalink
Fix inline documentation and concurrency warnings with Xcode beta 3
Browse files Browse the repository at this point in the history
  • Loading branch information
Supereg committed Jul 11, 2024
1 parent b148d1c commit 91ba82d
Show file tree
Hide file tree
Showing 12 changed files with 54 additions and 38 deletions.
15 changes: 10 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ Pairing devices is a good way of making sure that your application only connects
non-authorized devices.
Further, it might be necessary to ensure certain operations stay secure.

Use the ``PairedDevices`` module to discover and pair ``PairableDevice``s and automatically manage connection establishment
Use the [`PairedDevices`](https://swiftpackageindex.com/stanfordspezi/spezidevices/documentation/spezidevices/paireddevices)
module to discover and pair ``PairableDevice``s and automatically manage connection establishment
of connected devices.

To support `PairedDevices`, you need to adopt the ``PairableDevice`` protocol for your device.
Expand Down Expand Up @@ -85,7 +86,8 @@ class MyDevice: PairableDevice {

#### Health Measurements

Use the ``HealthMeasurements`` module to collect health measurements from nearby Bluetooth devices like connected weight scales or
Use the [`HealthMeasurements`](https://swiftpackageindex.com/stanfordspezi/spezidevices/documentation/spezidevices/healthmeasurements)
module to collect health measurements from nearby Bluetooth devices like connected weight scales or
blood pressure cuffs.

To support `HealthMeasurements`, you need to adopt the ``HealthDevice`` protocol for your device.
Expand Down Expand Up @@ -142,7 +144,8 @@ SpeziDevicesUI helps you to visualize Bluetooth device state and communicate int

#### Displaying paired devices

When managing paired devices using ``PairedDevices``, SpeziDevicesUI provides reusable View components to display paired devices.
When managing paired devices using [`PairedDevices`](https://swiftpackageindex.com/stanfordspezi/spezidevices/documentation/spezidevices/paireddevices),
SpeziDevicesUI provides reusable View components to display paired devices.

The [`DevicesView`](https://swiftpackageindex.com/stanfordspezi/spezidevices/documentation/spezidevicesui/devicesview)
provides everything you need to pair and manage paired devices.
Expand All @@ -168,7 +171,8 @@ struct MyHomeView: View {

#### Displaying Measurements

When managing measurements using ``HealthMeasurements``, you can use the [`MeasurementsRecordedSheet`](https://swiftpackageindex.com/stanfordspezi/spezidevices/documentation/spezidevicesui/measurementsrecordedsheet)
When managing measurements using [`HealthMeasurements`](https://swiftpackageindex.com/stanfordspezi/spezidevices/documentation/spezidevices/healthmeasurements),
you can use the [`MeasurementsRecordedSheet`](https://swiftpackageindex.com/stanfordspezi/spezidevices/documentation/spezidevicesui/measurementsrecordedsheet)
to display pending measurements.
Below is a short code example on how you would configure this view.

Expand Down Expand Up @@ -201,7 +205,8 @@ device support.

The ``OmronBloodPressureCuff`` and ``OmronWeightScale`` devices provide reusable device implementations for the Omron `BP5250` blood pressure cuff
and the Omron `SC-150` weight scale.
Both devices automatically integrate with the ``HealthMeasurements`` and ``PairedDevices`` modules of SpeziDevices.
Both devices automatically integrate with the [`HealthMeasurements`](https://swiftpackageindex.com/stanfordspezi/spezidevices/documentation/spezidevices/healthmeasurements)
and [`PairedDevices`](https://swiftpackageindex.com/stanfordspezi/spezidevices/documentation/spezidevices/paireddevices) modules of SpeziDevices.
You just need to configure them for use with the [`Bluetooth`](https://swiftpackageindex.com/stanfordspezi/spezibluetooth/documentation/spezibluetooth/bluetooth#Configure-the-Bluetooth-Module)
module.

Expand Down
10 changes: 5 additions & 5 deletions Sources/SpeziDevices/HealthMeasurements.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// SPDX-License-Identifier: MIT
//

@preconcurrency import HealthKit
import HealthKit
import OSLog
import Spezi
import SpeziBluetooth
Expand Down Expand Up @@ -146,12 +146,12 @@ public final class HealthMeasurements: @unchecked Sendable {
let hkDevice = device.hkDevice

// make sure to not capture the device
service.$weightMeasurement.onChange { [weak self, weak service] measurement in
service.$weightMeasurement.onChange { @MainActor [weak self, weak service] measurement in
guard let self, let service else {
return
}
logger.debug("Received new weight measurement: \(String(describing: measurement))")
await handleNewMeasurement(.weight(measurement, service.features ?? []), from: hkDevice)
handleNewMeasurement(.weight(measurement, service.features ?? []), from: hkDevice)
}
}

Expand All @@ -166,12 +166,12 @@ public final class HealthMeasurements: @unchecked Sendable {
let hkDevice = device.hkDevice

// make sure to not capture the device
service.$bloodPressureMeasurement.onChange { [weak self, weak service] measurement in
service.$bloodPressureMeasurement.onChange { @MainActor [weak self, weak service] measurement in
guard let self, let service else {
return
}
logger.debug("Received new blood pressure measurement: \(String(describing: measurement))")
await handleNewMeasurement(.bloodPressure(measurement, service.features ?? []), from: hkDevice)
handleNewMeasurement(.bloodPressure(measurement, service.features ?? []), from: hkDevice)
}

logger.debug("Registered device \(device.label), \(device.id) with HealthMeasurements")
Expand Down
8 changes: 4 additions & 4 deletions Sources/SpeziDevices/Measurements/StoredMeasurement.swift
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,10 @@ private struct SwiftDataBluetoothHealthMeasurementWorkaroundContainer {
final class StoredMeasurement {
@Attribute(.unique) var associatedMeasurement: UUID

private let measurement: SwiftDataBluetoothHealthMeasurementWorkaroundContainer
fileprivate let codableDevice: CodableHKDevice
let storageDate: Date
private var measurement: SwiftDataBluetoothHealthMeasurementWorkaroundContainer
fileprivate var codableDevice: CodableHKDevice

var storageDate: Date

var device: HKDevice {
codableDevice.hkDevice
Expand Down
8 changes: 4 additions & 4 deletions Sources/SpeziDevices/Model/PairedDeviceInfo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ import SwiftData
@Model
public final class PairedDeviceInfo {
/// The CoreBluetooth device identifier.
@Attribute(.unique) public let id: UUID
@Attribute(.unique) public var id: UUID
/// The device type.
///
/// Stores the associated ``PairableDevice/deviceTypeIdentifier-9wsed`` device type used to locate the device implementation.
public let deviceType: String
public var deviceType: String
/// A model string of the device.
public let model: String?
public var model: String?

/// The user edit-able name of the device.
public internal(set) var name: String
Expand All @@ -30,7 +30,7 @@ public final class PairedDeviceInfo {
public internal(set) var lastBatteryPercentage: UInt8?

/// The date at which the device was paired.
public let pairedAt: Date
public var pairedAt: Date

/// Could not retrieve the device from the Bluetooth central.
@Transient public internal(set) var notLocatable: Bool = false
Expand Down
8 changes: 5 additions & 3 deletions Sources/SpeziDevices/PairedDevices.swift
Original file line number Diff line number Diff line change
Expand Up @@ -383,10 +383,12 @@ extension PairedDevices {
await device.connect()

let id = device.id
async let _ = withTimeout(of: timeout) { @MainActor in
ongoingPairings.removeValue(forKey: id)?.signalTimeout()
let timeoutHandler = { @MainActor in
_ = self.ongoingPairings.removeValue(forKey: id)?.signalTimeout()
}

async let _ = withTimeout(of: timeout, perform: timeoutHandler)

Check warning on line 390 in Sources/SpeziDevices/PairedDevices.swift

View workflow job for this annotation

GitHub Actions / CodeQL / Test using xcodebuild or run fastlane

capture of 'timeoutHandler' with non-sendable type '@mainactor () -> ()' in 'async let' binding

Check warning on line 390 in Sources/SpeziDevices/PairedDevices.swift

View workflow job for this annotation

GitHub Actions / Build and Test iOS / Test using xcodebuild or run fastlane

capture of 'timeoutHandler' with non-sendable type '@mainactor () -> ()' in 'async let' binding

Check warning on line 390 in Sources/SpeziDevices/PairedDevices.swift

View workflow job for this annotation

GitHub Actions / Build and Test Swift Package iOS / Test using xcodebuild or run fastlane

capture of 'timeoutHandler' with non-sendable type '@mainactor () -> ()' in 'async let' binding

try await withTaskCancellationHandler {
try await withCheckedThrowingContinuation { continuation in
ongoingPairings[id] = PairingContinuation(continuation)
Expand Down Expand Up @@ -671,7 +673,7 @@ extension Bluetooth {

extension PairableDevice {
fileprivate static func retrieveDevice(from bluetooth: Bluetooth, with id: UUID) async -> Self? {
await bluetooth.retrieveDevice(for: id)
await bluetooth.retrieveDevice(for: id, as: Self.self)
}
}

Expand Down
3 changes: 2 additions & 1 deletion Sources/SpeziDevices/SpeziDevices.docc/SpeziDevices.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ class MyDevice: PairableDevice {

### Health Measurements

Use the ``HealthMeasurements`` module to collect health measurements from nearby Bluetooth devices like connected weight scales or
Use the ``HealthMeasurements``
module to collect health measurements from nearby Bluetooth devices like connected weight scales or
blood pressure cuffs.

To support `HealthMeasurements`, you need to adopt the ``HealthDevice`` protocol for your device.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// SPDX-License-Identifier: MIT
//

@preconcurrency import HealthKit
import HealthKit
import OSLog
@_spi(TestingSupport) import SpeziDevices
import SpeziViews
Expand All @@ -15,10 +15,11 @@ import SwiftUI

/// A sheet view displaying one or many newly recorded measurements.
///
/// This view retrieves the pending measurements from the ``HealthMeasurements`` Module that is present in the SwiftUI environment.
/// This view retrieves the pending measurements from the [`HealthMeasurements`](https://swiftpackageindex.com/stanfordspezi/spezidevices/documentation/spezidevices/healthmeasurements)
/// Module that is present in the SwiftUI environment.
public struct MeasurementsRecordedSheet: View {
private let logger = Logger(subsystem: "edu.stanford.spezi.SpeziDevices", category: "MeasurementsRecordedSheet")
private let saveSamples: ([HKSample]) async throws -> Void
private let saveSamples: @MainActor ([HKSample]) async throws -> Void

@Environment(HealthMeasurements.self) private var measurements
@Environment(\.dismiss) private var dismiss
Expand Down Expand Up @@ -132,7 +133,7 @@ public struct MeasurementsRecordedSheet: View {


/// Create a new measurement sheet.
public init(save saveSamples: @escaping ([HKSample]) async throws -> Void) {
public init(save saveSamples: @MainActor @escaping ([HKSample]) async throws -> Void) {
self.saveSamples = saveSamples
}

Expand Down
6 changes: 4 additions & 2 deletions Sources/SpeziDevicesUI/SpeziDevicesUI.docc/SpeziDevicesUI.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ SpeziDevicesUI helps you to visualize Bluetooth device state and communicate int

### Displaying paired devices

When managing paired devices using ``PairedDevices``, SpeziDevicesUI provides reusable View components to display paired devices.
When managing paired devices using [`PairedDevices`](https://swiftpackageindex.com/stanfordspezi/spezidevices/documentation/spezidevices/paireddevices),
SpeziDevicesUI provides reusable View components to display paired devices.

The ``DevicesView`` provides everything you need to pair and manage paired devices.
It shows already paired devices in a grid layout using the ``DevicesGrid``. Additionally, it places an add button in the toolbar
Expand All @@ -43,7 +44,8 @@ struct MyHomeView: View {

### Displaying Measurements

When managing measurements using ``HealthMeasurements``, you can use the [`MeasurementsRecordedSheet`](https://swiftpackageindex.com/stanfordspezi/spezidevices/documentation/spezidevicesui/measurementsrecordedsheet)
When managing measurements using [`HealthMeasurements`](https://swiftpackageindex.com/stanfordspezi/spezidevices/documentation/spezidevices/healthmeasurements),
you can use the [`MeasurementsRecordedSheet`](https://swiftpackageindex.com/stanfordspezi/spezidevices/documentation/spezidevicesui/measurementsrecordedsheet)
to display pending measurements.
Below is a short code example on how you would configure this view.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ public enum OmronRecordAccessOperand {

// RESPONSE

/// The general response operand used with the ``RecordAccessOpCode/responseCode`` operation.
/// The general response operand used with the [`responseCode`](https://swiftpackageindex.com/stanfordspezi/spezibluetooth/documentation/spezibluetoothservices/recordaccessopcode/responsecode)
/// operation.
case generalResponse(RecordAccessGeneralResponse)
/// Reports the number of records in the ``RecordAccessOpCode/numberOfStoredRecordsResponse`` operation.
/// Reports the number of records in the [`numberOfStoredRecordsResponse`](https://swiftpackageindex.com/stanfordspezi/spezibluetooth/documentation/spezibluetoothservices/recordaccessopcode/numberofstoredrecordsresponse)
/// operation.
case numberOfRecords(UInt16)
/// Reports the sequence number of the latest records in the ``BluetoothServices/RecordAccessOpCode/omronSequenceNumberOfLatestRecordsResponse`` operation.
/// Reports the sequence number of the latest records in the ``SpeziBluetoothServices/RecordAccessOpCode/omronSequenceNumberOfLatestRecordsResponse`` operation.
case sequenceNumber(UInt16)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ extension RecordAccessControlPoint {
/// Report the sequence number of the latest records.
///
/// Reports the the sequence number of the latest records on the peripheral.
/// The operator is ``RecordAccessOperator/null`` and no operand is used.
/// The operator is [`null`](https://swiftpackageindex.com/stanfordspezi/spezibluetooth/documentation/spezibluetoothservices/recordaccessoperator/null)
/// and no operand is used.
///
/// The number of stored records is returned using ``BluetoothServices/RecordAccessOpCode/omronSequenceNumberOfLatestRecordsResponse``.
/// Erroneous conditions are returned using the ``responseCode`` code.
/// The number of stored records is returned using ``SpeziBluetoothServices/RecordAccessOpCode/omronSequenceNumberOfLatestRecordsResponse``.
/// Erroneous conditions are returned using the [`responseCode`](https://swiftpackageindex.com/stanfordspezi/spezibluetooth/documentation/spezibluetoothservices/recordaccessopcode/responsecode).
///
/// - Returns: The Record Access Control Point value.
public static func reportSequenceNumberOfLatestRecords() -> RecordAccessControlPoint {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,16 @@ extension RecordAccessOpCode {
/// Report the sequence number of the latest records.
///
/// Reports the the sequence number of the latest records on the peripheral.
/// The operator is ``RecordAccessOperator/null`` and no operand is used.
/// The operator is [`null`](https://swiftpackageindex.com/stanfordspezi/spezibluetooth/documentation/spezibluetoothservices/recordaccessoperator/null)
/// and no operand is used.
///
/// The number of stored records is returned using ``omronSequenceNumberOfLatestRecordsResponse``.
/// Erroneous conditions are returned using the ``responseCode`` code.
/// Erroneous conditions are returned using the [`responseCode`](https://swiftpackageindex.com/stanfordspezi/spezibluetooth/documentation/spezibluetoothservices/recordaccessopcode/responsecode).
public static let omronReportSequenceNumberOfLatestRecords = RecordAccessOpCode(rawValue: 0x10)
/// Response returning the sequence number of the latest records.
///
/// This is the response code to ``omronReportSequenceNumberOfLatestRecords``.
/// The operator is ``RecordAccessOperator/null``.
/// The operator is [`null`](https://swiftpackageindex.com/stanfordspezi/spezibluetooth/documentation/spezibluetoothservices/recordaccessoperator/null).
/// The operand contains the number of stored records as a `UInt16`.
public static let omronSequenceNumberOfLatestRecordsResponse = RecordAccessOpCode(rawValue: 0x11) // swiftlint:disable:this identifier_name
}
3 changes: 2 additions & 1 deletion Sources/SpeziOmron/SpeziOmron.docc/SpeziOmron.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ device support.

The ``OmronBloodPressureCuff`` and ``OmronWeightScale`` devices provide reusable device implementations for the Omron `BP5250` blood pressure cuff
and the Omron `SC-150` weight scale.
Both devices automatically integrate with the ``HealthMeasurements`` and ``PairedDevices`` modules of SpeziDevices.
Both devices automatically integrate with the [`HealthMeasurements`](https://swiftpackageindex.com/stanfordspezi/spezidevices/documentation/spezidevices/healthmeasurements)
and [`PairedDevices`](https://swiftpackageindex.com/stanfordspezi/spezidevices/documentation/spezidevices/paireddevices) modules of SpeziDevices.
You just need to configure them for use with the [`Bluetooth`](https://swiftpackageindex.com/stanfordspezi/spezibluetooth/documentation/spezibluetooth/bluetooth#Configure-the-Bluetooth-Module)
module.

Expand Down

0 comments on commit 91ba82d

Please sign in to comment.