Skip to content

Commit

Permalink
feat: Make more CareKitEssentialView methods public (#8)
Browse files Browse the repository at this point in the history
* feat: Make createOutcomeWithValues public

* update readme

* update readme

* nit

* fix spi documentation

* add new method

* nit

* remove swiftlint sandboxing
  • Loading branch information
cbaker6 authored Jul 3, 2024
1 parent 1cf1120 commit 1e6e5bb
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 69 deletions.
4 changes: 2 additions & 2 deletions .spi.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
version: 1
builder:
configs:
- documentation_targets: [CareKitUtilities]
swift_version: 5.9
- documentation_targets: [CareKitEssentials]
swift_version: 6.0
6 changes: 3 additions & 3 deletions CareKitEssentials.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -199,10 +199,10 @@
isa = PBXGroup;
children = (
OBJ_26 /* Calendar+Dates.swift */,
700DA9062C2A66BF00435E2C /* Logger.swift */,
911BDB272A11C491004F8442 /* CGFloat.swift */,
OBJ_32 /* CustomLinearCareTaskProgress.swift */,
OBJ_27 /* Image.swift */,
700DA9062C2A66BF00435E2C /* Logger.swift */,
OBJ_29 /* OCKAnyEvent.swift */,
OBJ_28 /* OCKAnyEvent+CustomStringConvertable.swift */,
OBJ_30 /* OCKAnyOutcome.swift */,
Expand Down Expand Up @@ -489,7 +489,7 @@
ENABLE_NS_ASSERTIONS = YES;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
Expand Down Expand Up @@ -547,7 +547,7 @@
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = s;
GCC_PREPROCESSOR_DEFINITIONS = (
Expand Down
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,20 @@
![Codecov](https://codecov.io/gh/netreconlab/CareKitEssentials/branches/main/graph/badge.svg)
[![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/netreconlab/ParseCareKit/#license)

A description of this package.
Provides essential cards, views, models, protocols, and extentions to expedite building [CareKit](https://github.com/carekit-apple/CareKit) based applications.

## Entensions
A number of public extensions are available to make using CareKit easier. All of the extensions can be found in the [Extensions](https://github.com/netreconlab/CareKitEssentials/tree/main/Sources/CareKitEssentials/Extensions) folder.

## Usage
You can create SwiftUI views that conform to [CareKitEssentialView](https://github.com/netreconlab/CareKitEssentials/blob/main/Sources/CareKitEssentials/Cards/Shared/CareKitEssentialView.swift) to obtain a number of convenience methods for saving and deleting outcomes. The following views are based on `CareKitEssentialView`:

### iOS
[SliderLogTaskView](https://github.com/netreconlab/CareKitEssentials/blob/main/Sources/CareKitEssentials/Cards/iOS/SliderLog/SliderLogTaskView.swift) can be used to quickly create a slider view

<img width="342" alt="image" src="https://github.com/netreconlab/CareKitEssentials/assets/8621344/3efb4226-50e2-41e1-beef-91bc84cc7d63">

### watchOS
[DigitalCrownView](https://github.com/netreconlab/CareKitEssentials/blob/main/Sources/CareKitEssentials/Cards/watchOS/DigitalCrown/DigitalCrownView.swift) can be used to quickly create a view that responds to the crown

<img width="332" alt="image" src="https://github.com/netreconlab/CareKitEssentials/assets/8621344/02023682-75f4-4dff-a575-fa3ffd213cc3">
2 changes: 1 addition & 1 deletion Sources/CareKitEssentials/Cards/Shared/CardViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ open class CardViewModel: ObservableObject {
public private(set) var detailsInformation: String?

var initialValue: OCKOutcomeValue
var action: ((OCKOutcomeValue?) async -> Void)? = nil
var action: ((OCKOutcomeValue?) async -> Void)?

/// Create an instance with specified content for an event. The view will update when changes
/// occur in the store.
Expand Down
105 changes: 45 additions & 60 deletions Sources/CareKitEssentials/Cards/Shared/CareKitEssentialView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,12 @@ public protocol CareKitEssentialView: View {
with values: [OCKOutcomeValue]?
) async throws

/// Update an `OCKAnyEvent` with new a `OCKOutcome`.
/// Save a new `OCKAnyOutcome`.
/// - Parameters:
/// - event: The event to update.
/// - outcome: A new `OCKOutcome`.
/// - Throws: An error if the outcome values cannot be updated.
func updateEvent(
_ event: OCKAnyEvent,
with outcome: OCKOutcome?
/// - outcome: A new `OCKAnyOutcome`.
/// - Throws: An error if the outcome cannot be updated.
func saveOutcome(
_ outcome: OCKAnyOutcome
) async throws

/// Create an `OCKEventQuery` constrained to a set of `taskIDs` on a particular date.
Expand All @@ -50,43 +48,31 @@ public protocol CareKitEssentialView: View {

public extension CareKitEssentialView {

func deleteEventOutcome(_ event: OCKAnyEvent) async throws {
guard let outcome = event.outcome else {
throw CareKitEssentialsError.errorString("The event does not contain an outcome: \(event)")
}
_ = try await careStore.deleteAnyOutcome(outcome)
}

func updateEvent(
_ event: OCKAnyEvent,
with values: [OCKOutcomeValue]?
) async throws {
guard let values = values else {
// Attempts to delete outcome if it already exists.
_ = try await self.saveOutcomeValues(
[],
event: event,
store: careStore
)
try await deleteEventOutcome(event)
return
}
_ = try await self.appendOutcomeValues(
values,
event: event,
store: careStore
event: event
)
}

func updateEvent(
_ event: OCKAnyEvent,
with outcome: OCKOutcome?
func saveOutcome(
_ outcome: OCKAnyOutcome
) async throws {
guard let outcome = outcome else {
guard let task = event.task as? OCKAnyVersionableTask else {
throw CareKitEssentialsError.errorString("Cannot make outcome for event: \(event)")
}
let outcome = OCKOutcome(
taskUUID: task.uuid,
taskOccurrenceIndex: event.scheduleEvent.occurrence,
values: []
)
// Attempts to set the latest outcome values to an empty array.
_ = try await careStore.deleteAnyOutcome(outcome)
return
}
_ = try await careStore.addAnyOutcome(outcome)
}

Expand All @@ -98,22 +84,20 @@ public extension CareKitEssentialView {
/// Otherwise a new `OCKOutcome` is created with the respective outcome values.
func appendOutcomeValues(
_ values: [OCKOutcomeValue],
event: OCKAnyEvent,
store: OCKAnyStoreProtocol
event: OCKAnyEvent
) async throws {

// Update the outcome with the new value
guard var outcome = event.outcome else {
let outcome = try createOutcomeWithValues(
let outcome = createOutcomeWithValues(
values,
event: event,
store: store
event: event
)
_ = try await store.addAnyOutcome(outcome)
_ = try await careStore.addAnyOutcome(outcome)
return
}
outcome.values.append(contentsOf: values)
_ = try await store.updateAnyOutcome(outcome)
_ = try await careStore.updateAnyOutcome(outcome)
return
}

Expand All @@ -124,35 +108,42 @@ public extension CareKitEssentialView {
/// - Note: Setting `values` to an empty array will delete the current `OCKOutcome` if it currently exists.
func saveOutcomeValues(
_ values: [OCKOutcomeValue],
event: OCKAnyEvent,
store: OCKAnyStoreProtocol
event: OCKAnyEvent
) async throws {

// Check if outcome values need to be updated.
guard !values.isEmpty else {
// If the event has already been completed
guard let oldOutcome = event.outcome else {
return
}
// Delete the outcome, and create a new one.
_ = try await store.deleteAnyOutcome(oldOutcome)
try await deleteEventOutcome(event)
return
}

// If the event has already been completed
guard var currentOutcome = event.outcome else {
// Create a new outcome with the new values.
let outcome = try createOutcomeWithValues(
let outcome = createOutcomeWithValues(
values,
event: event,
store: store
event: event
)
_ = try await store.addAnyOutcome(outcome)
_ = try await careStore.addAnyOutcome(outcome)
return
}
// Update the outcome with the new values.
currentOutcome.values = values
_ = try await store.updateAnyOutcome(currentOutcome)
_ = try await careStore.updateAnyOutcome(currentOutcome)
}

/// Create an outcome for an event.
/// - Parameters:
/// - event: The event the outcome is made for.
func createOutcomeForEvent(
_ event: OCKAnyEvent
) -> OCKAnyOutcome {
OCKOutcome(
taskUUID: event.task.uuid,
taskOccurrenceIndex: event.scheduleEvent.occurrence,
values: []
)
}

static func eventQuery(
Expand All @@ -170,19 +161,13 @@ extension CareKitEssentialView {
/// Create an outcome for an event with the given outcome values.
/// - Parameters:
/// - values: The outcome values to attach to the outcome.
/// - event: The event the outcome is made for.
func createOutcomeWithValues(
_ values: [OCKOutcomeValue],
event: OCKAnyEvent,
store: OCKAnyStoreProtocol
) throws -> OCKAnyOutcome {
guard let task = event.task as? OCKAnyVersionableTask else {
throw CareKitEssentialsError.errorString("Cannot make outcome for event: \(event)")
}
let outcome = OCKOutcome(
taskUUID: task.uuid,
taskOccurrenceIndex: event.scheduleEvent.occurrence,
values: values
)
event: OCKAnyEvent
) -> OCKAnyOutcome {
var outcome = createOutcomeForEvent(event)
outcome.values = values
return outcome
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ public extension LabeledValueTaskView where Header == InformationHeaderView {
/// - Parameters:
/// - event: The data that appears in the view.
/// - numberFormatter: An object that formats the progress and target values.
init(event: CareStoreFetchedResult<OCKAnyEvent>,
numberFormatter: NumberFormatter? = nil) {
init(
event: CareStoreFetchedResult<OCKAnyEvent>,
numberFormatter: NumberFormatter? = nil
) {

let currentEvent = event.result

Expand Down

0 comments on commit 1e6e5bb

Please sign in to comment.