Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ on:
workflow_dispatch:

env:
DEVELOPER_DIR: /Applications/Xcode_15.4.app
DEVELOPER_DIR: /Applications/Xcode_16.0.app

jobs:
publish-docs:
Expand Down
16 changes: 11 additions & 5 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,34 +10,40 @@ on:
workflow_dispatch:

env:
DEVELOPER_DIR: /Applications/Xcode_15.4.app
DEVELOPER_DIR: /Applications/Xcode_16.app

jobs:
test:
name: Test
runs-on: macos-14
strategy:
matrix:
xcode_version:
- 15.4
- 16
platform:
- ios
- macos
- tvos
- watchos
env:
DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode_version }}.app
steps:
- uses: actions/checkout@v4
- name: Test library
run: scripts/test.sh library ${{ matrix.platform }}
- name: Test example cross platform
if: matrix.platform == 'macos' || matrix.platform == 'tvos'
run: scripts/test.sh example-cross-platform ${{ matrix.platform }}

test_examples:
name: Test iOS examples
name: Test examples
runs-on: macos-14
steps:
- uses: actions/checkout@v4
- name: Test example iOS
run: scripts/test.sh example-ios ios
- name: Test example macOS
run: scripts/test.sh example-cross-platform macos
- name: Test example tvOS
run: scripts/test.sh example-cross-platform tvos

benchmark:
name: Benchmark
Expand Down
6 changes: 2 additions & 4 deletions Benchmarks/Project.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -251,8 +251,7 @@
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_STRICT_CONCURRENCY = complete;
SWIFT_VERSION = 5.0;
SWIFT_VERSION = 6;
};
name = Release;
};
Expand Down Expand Up @@ -383,8 +382,7 @@
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_STRICT_CONCURRENCY = complete;
SWIFT_VERSION = 5.0;
SWIFT_VERSION = 6;
};
name = Debug;
};
Expand Down
2 changes: 1 addition & 1 deletion Benchmarks/Tests/ViewTest.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import SwiftUI

struct ViewTest<Content: View>: _ViewTest {
struct ViewTest<Content: View & Sendable>: _ViewTest {
let rootView: @MainActor () -> Content

func initRootView() -> some View {
Expand Down
2 changes: 1 addition & 1 deletion Benchmarks/project.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ settings:
CODE_SIGNING_REQUIRED: NO
CODE_SIGN_IDENTITY: "-"
CODE_SIGN_STYLE: Manual
SWIFT_STRICT_CONCURRENCY: complete
SWIFT_VERSION: 6

packages:
swiftui-atom-properties:
Expand Down
33 changes: 8 additions & 25 deletions Examples/Packages/CrossPlatform/Package.swift
Original file line number Diff line number Diff line change
@@ -1,26 +1,8 @@
// swift-tools-version:5.10
// swift-tools-version:6.0

import PackageDescription

let swiftSettings: [SwiftSetting] = [
.enableExperimentalFeature("StrictConcurrency")
]

func target(name: String, dependencies: [Target.Dependency] = []) -> Target {
.target(
name: name,
dependencies: [.product(name: "Atoms", package: "swiftui-atom-properties")] + dependencies,
swiftSettings: swiftSettings
)
}

func testTarget(name: String, dependencies: [Target.Dependency]) -> Target {
.testTarget(
name: name,
dependencies: dependencies,
swiftSettings: swiftSettings
)
}
let atoms = Target.Dependency.product(name: "Atoms", package: "swiftui-atom-properties")

let package = Package(
name: "CrossPlatformExamples",
Expand All @@ -37,16 +19,17 @@ let package = Package(
.package(path: "../../..")
],
targets: [
target(
.target(
name: "CrossPlatformApp",
dependencies: [
atoms,
"ExampleCounter",
"ExampleTodo",
]
),
target(name: "ExampleCounter"),
testTarget(name: "ExampleCounterTests", dependencies: ["ExampleCounter"]),
target(name: "ExampleTodo"),
testTarget(name: "ExampleTodoTests", dependencies: ["ExampleTodo"]),
.target(name: "ExampleCounter", dependencies: [atoms]),
.testTarget(name: "ExampleCounterTests", dependencies: ["ExampleCounter"]),
.target(name: "ExampleTodo", dependencies: [atoms]),
.testTarget(name: "ExampleTodoTests", dependencies: ["ExampleTodo"]),
]
)
41 changes: 12 additions & 29 deletions Examples/Packages/iOS/Package.swift
Original file line number Diff line number Diff line change
@@ -1,26 +1,8 @@
// swift-tools-version:5.10
// swift-tools-version:6.0

import PackageDescription

let swiftSettings: [SwiftSetting] = [
.enableExperimentalFeature("StrictConcurrency")
]

func target(name: String, dependencies: [Target.Dependency] = []) -> Target {
.target(
name: name,
dependencies: [.product(name: "Atoms", package: "swiftui-atom-properties")] + dependencies,
swiftSettings: swiftSettings
)
}

func testTarget(name: String, dependencies: [Target.Dependency]) -> Target {
.testTarget(
name: name,
dependencies: dependencies,
swiftSettings: swiftSettings
)
}
let atoms = Target.Dependency.product(name: "Atoms", package: "swiftui-atom-properties")

let package = Package(
name: "iOSExamples",
Expand All @@ -35,23 +17,24 @@ let package = Package(
.package(path: "../CrossPlatform"),
],
targets: [
target(
.target(
name: "iOSApp",
dependencies: [
atoms,
.product(name: "CrossPlatformApp", package: "CrossPlatform"),
"ExampleMovieDB",
"ExampleMap",
"ExampleVoiceMemo",
"ExampleTimeTravel",
]
),
target(name: "ExampleMovieDB"),
testTarget(name: "ExampleMovieDBTests", dependencies: ["ExampleMovieDB"]),
target(name: "ExampleMap"),
testTarget(name: "ExampleMapTests", dependencies: ["ExampleMap"]),
target(name: "ExampleVoiceMemo"),
testTarget(name: "ExampleVoiceMemoTests", dependencies: ["ExampleVoiceMemo"]),
target(name: "ExampleTimeTravel"),
testTarget(name: "ExampleTimeTravelTests", dependencies: ["ExampleTimeTravel"]),
.target(name: "ExampleMovieDB", dependencies: [atoms]),
.testTarget(name: "ExampleMovieDBTests", dependencies: ["ExampleMovieDB"]),
.target(name: "ExampleMap", dependencies: [atoms]),
.testTarget(name: "ExampleMapTests", dependencies: ["ExampleMap"]),
.target(name: "ExampleVoiceMemo", dependencies: [atoms]),
.testTarget(name: "ExampleVoiceMemoTests", dependencies: ["ExampleVoiceMemo"]),
.target(name: "ExampleTimeTravel", dependencies: [atoms]),
.testTarget(name: "ExampleTimeTravelTests", dependencies: ["ExampleTimeTravel"]),
]
)
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ protocol AudioRecorderProtocol {
func stop()
}

final class AudioRecorder: NSObject, AVAudioRecorderDelegate, AudioRecorderProtocol {
final class AudioRecorder: NSObject, AVAudioRecorderDelegate, AudioRecorderProtocol, @unchecked Sendable {
private var recorder: AVAudioRecorder?
private let onFail: () -> Void

Expand Down
6 changes: 2 additions & 4 deletions Examples/Project.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -276,8 +276,7 @@
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_STRICT_CONCURRENCY = complete;
SWIFT_VERSION = 5.0;
SWIFT_VERSION = 6;
TVOS_DEPLOYMENT_TARGET = 16.0;
};
name = Release;
Expand Down Expand Up @@ -408,8 +407,7 @@
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_STRICT_CONCURRENCY = complete;
SWIFT_VERSION = 5.0;
SWIFT_VERSION = 6;
TVOS_DEPLOYMENT_TARGET = 16.0;
};
name = Debug;
Expand Down
2 changes: 1 addition & 1 deletion Examples/project.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ settings:
CODE_SIGNING_REQUIRED: NO
CODE_SIGN_IDENTITY: "-"
CODE_SIGN_STYLE: Manual
SWIFT_STRICT_CONCURRENCY: complete
SWIFT_VERSION: 6

targetTemplates:
App:
Expand Down
17 changes: 4 additions & 13 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
// swift-tools-version:5.10
// swift-tools-version:6.0

import Foundation
import PackageDescription

let swiftSettings: [SwiftSetting] = [
.enableExperimentalFeature("StrictConcurrency")
]

let package = Package(
name: "swiftui-atom-properties",
platforms: [
Expand All @@ -19,15 +14,11 @@ let package = Package(
.library(name: "Atoms", targets: ["Atoms"])
],
targets: [
.target(
name: "Atoms",
swiftSettings: swiftSettings
),
.target(name: "Atoms"),
.testTarget(
name: "AtomsTests",
dependencies: ["Atoms"],
swiftSettings: swiftSettings
dependencies: ["Atoms"]
),
],
swiftLanguageVersions: [.v5]
swiftLanguageModes: [.v5, .v6]
)
32 changes: 32 additions & 0 deletions Package@swift-5.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// swift-tools-version:5.10

import PackageDescription

let swiftSettings: [SwiftSetting] = [
.enableExperimentalFeature("StrictConcurrency")
]

let package = Package(
name: "swiftui-atom-properties",
platforms: [
.iOS(.v14),
.macOS(.v11),
.tvOS(.v14),
.watchOS(.v7),
],
products: [
.library(name: "Atoms", targets: ["Atoms"])
],
targets: [
.target(
name: "Atoms",
swiftSettings: swiftSettings
),
.testTarget(
name: "AtomsTests",
dependencies: ["Atoms"],
swiftSettings: swiftSettings
),
],
swiftLanguageVersions: [.v5]
)
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,8 @@ Open `Examples/Project.xcodeproj` and play around with it!

| |Minimum Version|
|------:|--------------:|
|Swift |5.10 |
|Xcode |15.4 |
|Swift |5.10, 6.0 |
|Xcode |15.4, 16.0 |
|iOS |14.0 |
|macOS |11.0 |
|tvOS |14.0 |
Expand Down
38 changes: 27 additions & 11 deletions Sources/Atoms/AsyncPhase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,35 @@ public enum AsyncPhase<Success, Failure: Error> {
}
}

/// Creates a new phase by evaluating a async throwing closure, capturing the
/// returned value as a success, or any thrown error as a failure.
///
/// - Parameter body: A async throwing closure to evaluate.
public init(catching body: @Sendable () async throws -> Success) async where Failure == Error {
do {
let value = try await body()
self = .success(value)
#if compiler(>=6)
/// Creates a new phase by evaluating a async throwing closure, capturing the
/// returned value as a success, or thrown error as a failure.
///
/// - Parameter body: A async throwing closure to evaluate.
public init(catching body: @Sendable () async throws(Failure) -> Success) async {
do {
let value = try await body()
self = .success(value)
}
catch {
self = .failure(error)
}
}
catch {
self = .failure(error)
#else
/// Creates a new phase by evaluating a async throwing closure, capturing the
/// returned value as a success, or thrown error as a failure.
///
/// - Parameter body: A async throwing closure to evaluate.
public init(catching body: @Sendable () async throws -> Success) async where Failure == Error {
do {
let value = try await body()
self = .success(value)
}
catch {
self = .failure(error)
}
}
}
#endif

/// A boolean value indicating whether `self` is ``AsyncPhase/suspending``.
public var isSuspending: Bool {
Expand Down
4 changes: 3 additions & 1 deletion Sources/Atoms/Atom/ObservableObjectAtom.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,9 @@ public extension ObservableObjectAtom {
}
}

context.onTermination = cancellable.cancel
context.onTermination = {
cancellable.cancel()
}
}
}
}
2 changes: 1 addition & 1 deletion Sources/Atoms/Atom/PublisherAtom.swift
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public extension PublisherAtom {
}
}

private extension Publisher {
private extension Publisher where Output: Sendable {
var results: AsyncStream<Result<Output, Failure>> {
AsyncStream { continuation in
let cancellable = map(Result.success)
Expand Down
Loading