Skip to content

Commit 9721078

Browse files
authored
Drop support for Xcode15 (#180)
1 parent 9e59598 commit 9721078

19 files changed

+196
-442
lines changed

.github/workflows/test.yml

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ on:
1212
env:
1313
DEVELOPER_DIR: /Applications/Xcode_16.1.app
1414
IOS_SIMULATOR: '"platform=iOS Simulator,name=iPhone 16 Pro"'
15-
IOS_SIMULATOR_XCODE_15: '"platform=iOS Simulator,name=iPhone 15 Pro"'
1615
MACOS: '"platform=macOS"'
1716
TVOS_SIMULATOR: '"platform=tvOS Simulator,name=Apple TV 4K (3rd generation)"'
1817
WATCHOS_SIMULATOR: '"platform=watchOS Simulator,name=Apple Watch Ultra 2 (49mm)"'
@@ -32,22 +31,6 @@ jobs:
3231
- name: Test library watchOS
3332
run: scripts/test.sh library -destinations ${{ env.WATCHOS_SIMULATOR }}
3433

35-
test_with_xcode_15:
36-
name: Test with Xcode 15
37-
runs-on: macos-14
38-
env:
39-
DEVELOPER_DIR: /Applications/Xcode_15.4.app
40-
steps:
41-
- uses: actions/checkout@v4
42-
- name: Test library iOS
43-
run: scripts/test.sh library -destinations ${{ env.IOS_SIMULATOR_XCODE_15 }}
44-
- name: Test library macOS
45-
run: scripts/test.sh library -destinations ${{ env.MACOS }}
46-
- name: Test library tvOS
47-
run: scripts/test.sh library -destinations ${{ env.TVOS_SIMULATOR }}
48-
- name: Test library watchOS
49-
run: scripts/test.sh library -destinations ${{ env.WATCHOS_SIMULATOR }}
50-
5134
test_examples:
5235
name: Test examples
5336
runs-on: macos-14
@@ -61,16 +44,6 @@ jobs:
6144
${{ env.MACOS }} \
6245
${{ env.TVOS_SIMULATOR }}
6346
64-
test_upcoming_features:
65-
name: Test upcoming features with Xcode 15
66-
runs-on: macos-14
67-
env:
68-
DEVELOPER_DIR: /Applications/Xcode_15.4.app
69-
steps:
70-
- uses: actions/checkout@v4
71-
- name: Test upcoming features
72-
run: ENABLE_UPCOMING_FEATURES=1 scripts/test.sh library -destinations ${{ env.IOS_SIMULATOR_XCODE_15 }}
73-
7447
test_language_mode:
7548
name: Test Swift 5 language mode
7649
runs-on: macos-14

Package@swift-5.swift

Lines changed: 0 additions & 43 deletions
This file was deleted.

README.md

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -125,14 +125,14 @@ Open `Examples/Project.xcodeproj` and play around with it!
125125

126126
### Requirements
127127

128-
| |Minimum Version|
129-
|------:|--------------:|
130-
|Swift |5.10, 6.0 |
131-
|Xcode |15.4, 16.1 |
132-
|iOS |14.0 |
133-
|macOS |11.0 |
134-
|tvOS |14.0 |
135-
|watchOS|7.0 |
128+
| |Minimum Version|
129+
|------------:|--------------:|
130+
|Language mode|5, 6 |
131+
|Xcode |16.1 |
132+
|iOS |14.0 |
133+
|macOS |11.0 |
134+
|tvOS |14.0 |
135+
|watchOS |7.0 |
136136

137137
### Installation
138138

@@ -519,11 +519,9 @@ struct MoviesView: View {
519519
| |Description|
520520
|:----------|:----------|
521521
|Summary |Provides an `AsyncPhase` value that represents a result of the given asynchronous throwable function.|
522-
|Output |`AsyncPhase<T, E: Error>` (`AsyncPhase<T, any Error>` in Swift 5)|
522+
|Output |`AsyncPhase<T, E: Error>`|
523523
|Use Case |Throwing or non-throwing asynchronous operation e.g. API call|
524524

525-
Note:
526-
The [typed throws](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0413-typed-throws.md) feature introduced in Swift 6 allows the `Failure` type of the produced `AsyncPhase` to be specified as any type or even non-throwing, but in Swift 5 without it, the `Failure` type is always be `any Error`.
527525
Here is a chart of the syntax in `typed throws` and the type of resulting `AsyncPhase`.
528526

529527
|Syntax |Shorthand |Produced |

Sources/Atoms/AsyncPhase.swift

Lines changed: 13 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -24,37 +24,21 @@ public enum AsyncPhase<Success, Failure: Error> {
2424
}
2525
}
2626

27-
#if compiler(>=6)
28-
/// Creates a new phase by evaluating a async throwing closure, capturing the
29-
/// returned value as a success, or thrown error as a failure.
30-
///
31-
/// - Parameter body: A async throwing closure to evaluate.
32-
public init(
33-
@_inheritActorContext catching body: () async throws(Failure) -> Success
34-
) async {
35-
do {
36-
let value = try await body()
37-
self = .success(value)
38-
}
39-
catch {
40-
self = .failure(error)
41-
}
27+
/// Creates a new phase by evaluating a async throwing closure, capturing the
28+
/// returned value as a success, or thrown error as a failure.
29+
///
30+
/// - Parameter body: A async throwing closure to evaluate.
31+
public init(
32+
@_inheritActorContext catching body: () async throws(Failure) -> Success
33+
) async {
34+
do {
35+
let value = try await body()
36+
self = .success(value)
4237
}
43-
#else
44-
/// Creates a new phase by evaluating a async throwing closure, capturing the
45-
/// returned value as a success, or thrown error as a failure.
46-
///
47-
/// - Parameter body: A async throwing closure to evaluate.
48-
public init(catching body: @Sendable () async throws -> Success) async where Failure == any Error {
49-
do {
50-
let value = try await body()
51-
self = .success(value)
52-
}
53-
catch {
54-
self = .failure(error)
55-
}
38+
catch {
39+
self = .failure(error)
5640
}
57-
#endif
41+
}
5842

5943
/// A boolean value indicating whether `self` is ``AsyncPhase/suspending``.
6044
public var isSuspending: Bool {

Sources/Atoms/Atom/AsyncPhaseAtom.swift

Lines changed: 33 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -39,74 +39,40 @@ public protocol AsyncPhaseAtom: AsyncAtom where Produced == AsyncPhase<Success,
3939
/// The type of success value that this atom produces.
4040
associatedtype Success
4141

42-
#if compiler(>=6)
43-
/// The type of errors that this atom produces.
44-
associatedtype Failure: Error
42+
/// The type of errors that this atom produces.
43+
associatedtype Failure: Error
4544

46-
/// Asynchronously produces a value to be provided via this atom.
47-
///
48-
/// Values provided or errors thrown by this method are converted to the unified enum
49-
/// representation ``AsyncPhase``.
50-
///
51-
/// - Parameter context: A context structure to read, watch, and otherwise
52-
/// interact with other atoms.
53-
///
54-
/// - Throws: The error that occurred during the process of creating the resulting value.
55-
///
56-
/// - Returns: The process's result.
57-
@MainActor
58-
func value(context: Context) async throws(Failure) -> Success
59-
#else
60-
/// The type of errors that this atom produces.
61-
typealias Failure = any Error
62-
63-
/// Asynchronously produces a value to be provided via this atom.
64-
///
65-
/// Values provided or errors thrown by this method are converted to the unified enum
66-
/// representation ``AsyncPhase``.
67-
///
68-
/// - Parameter context: A context structure to read, watch, and otherwise
69-
/// interact with other atoms.
70-
///
71-
/// - Throws: The error that occurred during the process of creating the resulting value.
72-
///
73-
/// - Returns: The process's result.
74-
@MainActor
75-
func value(context: Context) async throws -> Success
76-
#endif
45+
/// Asynchronously produces a value to be provided via this atom.
46+
///
47+
/// Values provided or errors thrown by this method are converted to the unified enum
48+
/// representation ``AsyncPhase``.
49+
///
50+
/// - Parameter context: A context structure to read, watch, and otherwise
51+
/// interact with other atoms.
52+
///
53+
/// - Throws: The error that occurred during the process of creating the resulting value.
54+
///
55+
/// - Returns: The process's result.
56+
@MainActor
57+
func value(context: Context) async throws(Failure) -> Success
7758
}
7859

7960
public extension AsyncPhaseAtom {
8061
var producer: AtomProducer<Produced> {
8162
AtomProducer { context in
8263
let task = Task {
83-
#if compiler(>=6)
84-
do throws(Failure) {
85-
let value = try await context.transaction(value)
86-
87-
if !Task.isCancelled {
88-
context.update(with: .success(value))
89-
}
90-
}
91-
catch {
92-
if !Task.isCancelled {
93-
context.update(with: .failure(error))
94-
}
95-
}
96-
#else
97-
do {
98-
let value = try await context.transaction(value)
64+
do throws(Failure) {
65+
let value = try await context.transaction(value)
9966

100-
if !Task.isCancelled {
101-
context.update(with: .success(value))
102-
}
67+
if !Task.isCancelled {
68+
context.update(with: .success(value))
10369
}
104-
catch {
105-
if !Task.isCancelled {
106-
context.update(with: .failure(error))
107-
}
70+
}
71+
catch {
72+
if !Task.isCancelled {
73+
context.update(with: .failure(error))
10874
}
109-
#endif
75+
}
11076
}
11177

11278
context.onTermination = task.cancel
@@ -119,33 +85,18 @@ public extension AsyncPhaseAtom {
11985
var phase = Produced.suspending
12086

12187
let task = Task {
122-
#if compiler(>=6)
123-
do throws(Failure) {
124-
let value = try await context.transaction(value)
125-
126-
if !Task.isCancelled {
127-
phase = .success(value)
128-
}
129-
}
130-
catch {
131-
if !Task.isCancelled {
132-
phase = .failure(error)
133-
}
134-
}
135-
#else
136-
do {
137-
let value = try await context.transaction(value)
88+
do throws(Failure) {
89+
let value = try await context.transaction(value)
13890

139-
if !Task.isCancelled {
140-
phase = .success(value)
141-
}
91+
if !Task.isCancelled {
92+
phase = .success(value)
14293
}
143-
catch {
144-
if !Task.isCancelled {
145-
phase = .failure(error)
146-
}
94+
}
95+
catch {
96+
if !Task.isCancelled {
97+
phase = .failure(error)
14798
}
148-
#endif
99+
}
149100
}
150101

151102
context.onTermination = task.cancel

Sources/Atoms/Core/Environment.swift

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,6 @@
11
import SwiftUI
22

3-
#if compiler(>=6)
4-
internal extension EnvironmentValues {
5-
@Entry
6-
var store: StoreContext? = nil
7-
}
8-
#else
9-
internal extension EnvironmentValues {
10-
var store: StoreContext? {
11-
get { self[StoreEnvironmentKey.self] }
12-
set { self[StoreEnvironmentKey.self] = newValue }
13-
}
14-
}
15-
16-
private struct StoreEnvironmentKey: EnvironmentKey {
17-
static var defaultValue: StoreContext? {
18-
nil
19-
}
20-
}
21-
#endif
3+
internal extension EnvironmentValues {
4+
@Entry
5+
var store: StoreContext? = nil
6+
}

Sources/Atoms/Core/Producer/AtomProducerContext.swift

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,10 @@ internal struct AtomProducerContext<Value> {
3434
return body(context)
3535
}
3636

37-
#if compiler(>=6)
38-
func transaction<T, E: Error>(_ body: @MainActor (AtomTransactionContext) async throws(E) -> T) async throws(E) -> T {
39-
transactionState.begin()
40-
let context = AtomTransactionContext(store: store, transactionState: transactionState)
41-
defer { transactionState.commit() }
42-
return try await body(context)
43-
}
44-
#else
45-
func transaction<T>(_ body: @MainActor (AtomTransactionContext) async throws -> T) async rethrows -> T {
46-
transactionState.begin()
47-
let context = AtomTransactionContext(store: store, transactionState: transactionState)
48-
defer { transactionState.commit() }
49-
return try await body(context)
50-
}
51-
#endif
37+
func transaction<T, E: Error>(_ body: @MainActor (AtomTransactionContext) async throws(E) -> T) async throws(E) -> T {
38+
transactionState.begin()
39+
let context = AtomTransactionContext(store: store, transactionState: transactionState)
40+
defer { transactionState.commit() }
41+
return try await body(context)
42+
}
5243
}

0 commit comments

Comments
 (0)