Skip to content

Commit 45bc6de

Browse files
authored
FetchRequests v7: Swift 6 language mode (#51)
Also removes JSON
1 parent b11f4c0 commit 45bc6de

46 files changed

Lines changed: 415 additions & 1647 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/build.yml

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,24 +19,24 @@ jobs:
1919
- tvOS
2020
- watchOS
2121
- macOS
22-
#- visionOS
23-
runs-on: macos-14
22+
- visionOS
23+
runs-on: macos-latest
2424
steps:
2525
- name: Checkout
2626
uses: actions/checkout@v4
2727
- name: Build
28-
uses: mxcl/xcodebuild@v2
28+
uses: mxcl/xcodebuild@v3
2929
with:
3030
platform: ${{ matrix.platform }}
3131
scheme: FetchRequests-${{ matrix.platform }}
32-
xcode: 15.2
32+
swift: ~6.0
3333
action: test
3434
code-coverage: true
3535
- name: Code Coverage
3636
#uses: codecov/codecov-action@v2
3737
run: bash <(curl -s https://codecov.io/bash);
3838
validate:
39-
runs-on: macos-14
39+
runs-on: macos-latest
4040
needs: build
4141
steps:
4242
- name: Checkout
@@ -52,11 +52,10 @@ jobs:
5252
- name: Pod Lint
5353
run: pod lib lint --quick --fail-fast --verbose --skip-tests
5454
- name: Example Project
55-
uses: mxcl/xcodebuild@v2
55+
uses: mxcl/xcodebuild@v3
5656
with:
5757
platform: iOS
5858
scheme: iOS Example
59-
xcode: 15.2
59+
swift: ~6.0
6060
action: build
61-
warnings-as-errors: true
6261
working-directory: Example

.swiftformat

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
1-
--swiftversion 5.9
1+
--swiftversion 6.0
22

33
--exclude Pods
44

55
--rules andOperator
66
--rules anyObjectProtocol
77

8+
--rules blankLinesBetweenScopes
89
--rules blankLineAfterImports
910
--rules braces
1011
--rules conditionalAssignment
12+
--rules consecutiveSpaces
13+
--rules consistentSwitchCaseSpacing
1114
--rules duplicateImports
1215
--rules elseOnSameLine
1316
--rules genericExtensions
@@ -24,14 +27,18 @@
2427
--rules leadingDelimiters
2528
--rules linebreakAtEndOfFile
2629

30+
--rules redundantBreak
2731
--rules redundantClosure
2832
--rules redundantFileprivate
2933
--rules redundantGet
3034
--rules redundantInit
35+
--rules redundantLet
36+
--rules redundantLetError
3137
--rules redundantOptionalBinding
3238
--rules redundantParens
3339
--rules redundantPattern
3440
--rules redundantReturn
41+
--rules redundantTypedThrows
3542
--rules redundantVoidReturnType
3643
--rules semicolons
3744

@@ -49,6 +56,7 @@
4956

5057
--rules strongifiedSelf
5158
--rules todos
59+
--rules trailingClosures
5260
--rules trailingCommas
5361
--rules trailingSpace
5462
--rules typeSugar
@@ -58,5 +66,6 @@
5866
--wraparguments before-first
5967
--wrapcollections before-first
6068
--wrapparameters before-first
69+
--closingparen balanced
6170

6271
--rules wrapMultilineStatementBraces

.swiftlint.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ opt_in_rules:
5050
- optional_enum_case_matching
5151
- overridden_super_call
5252
- pattern_matching_keywords
53+
- prefer_key_path
5354
- prefer_self_type_over_type_of_self
55+
- private_swiftui_state
5456
- prohibited_super_call
5557
- private_outlet
5658
- private_subject
@@ -59,6 +61,7 @@ opt_in_rules:
5961
- redundant_nil_coalescing
6062
- redundant_objc_attribute
6163
- self_binding
64+
- shorthand_argument
6265
- single_test_class
6366
- shorthand_optional_binding
6467
- sorted_first_last
@@ -106,3 +109,4 @@ deployment_target:
106109
tvOS_deployment_target: 14
107110
watchOS_deployment_target: 7
108111
macOS_deployment_target: 11
112+
# visionOS_deployment_target: 1

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22
All notable changes to this project will be documented in this file.
33
`FetchRequests` adheres to [Semantic Versioning](https://semver.org/).
44

5+
## [7.0](https://github.com/square/FetchRequests/releases/tag/7.0.0)
6+
Release 2024-09-XX
7+
8+
* Compiles cleanly in the Swift 6 language mode
9+
* Requires the Swift 6 compiler
10+
* `JSON` has been removed from the library as it is no longer necessary
11+
512
## [6.1](https://github.com/square/FetchRequests/releases/tag/6.1.0)
613
Release 2024-04-03
714

Example/.DS_Store

-6 KB
Binary file not shown.

Example/iOS-Example.xcodeproj/project.pbxproj

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10-
472E8F6F23388380005045D2 /* Observable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472E8F6E23388380005045D2 /* Observable.swift */; };
10+
472E8F6F23388380005045D2 /* ObservableValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472E8F6E23388380005045D2 /* ObservableValue.swift */; };
1111
472E8F7723388E93005045D2 /* Atomic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472E8F7623388E93005045D2 /* Atomic.swift */; };
1212
4736ABC822CBE82A00253EB6 /* Model.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4736ABC722CBE82A00253EB6 /* Model.swift */; };
1313
4736ABD022CBE9C600253EB6 /* Model+Fetchable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4736ABCF22CBE9C600253EB6 /* Model+Fetchable.swift */; };
@@ -21,6 +21,20 @@
2121
/* End PBXBuildFile section */
2222

2323
/* Begin PBXContainerItemProxy section */
24+
2A6FBFED2C920B7300A7CDBE /* PBXContainerItemProxy */ = {
25+
isa = PBXContainerItemProxy;
26+
containerPortal = 47ACD1A422CBE3E200B3F1FE /* FetchRequests.xcodeproj */;
27+
proxyType = 2;
28+
remoteGlobalIDString = 2ABB235E2B98FC770015F902;
29+
remoteInfo = "FetchRequests-visionOS";
30+
};
31+
2A6FBFEF2C920B7300A7CDBE /* PBXContainerItemProxy */ = {
32+
isa = PBXContainerItemProxy;
33+
containerPortal = 47ACD1A422CBE3E200B3F1FE /* FetchRequests.xcodeproj */;
34+
proxyType = 2;
35+
remoteGlobalIDString = 2ABB23782B98FC7E0015F902;
36+
remoteInfo = "FetchRequests-visionOSTests";
37+
};
2438
4798B6DD22CBE4CA001F6B3D /* PBXContainerItemProxy */ = {
2539
isa = PBXContainerItemProxy;
2640
containerPortal = 47ACD1A422CBE3E200B3F1FE /* FetchRequests.xcodeproj */;
@@ -87,7 +101,7 @@
87101
/* End PBXContainerItemProxy section */
88102

89103
/* Begin PBXFileReference section */
90-
472E8F6E23388380005045D2 /* Observable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Observable.swift; sourceTree = "<group>"; };
104+
472E8F6E23388380005045D2 /* ObservableValue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObservableValue.swift; sourceTree = "<group>"; };
91105
472E8F7623388E93005045D2 /* Atomic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Atomic.swift; sourceTree = "<group>"; };
92106
4736ABC722CBE82A00253EB6 /* Model.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Model.swift; sourceTree = "<group>"; };
93107
4736ABCF22CBE9C600253EB6 /* Model+Fetchable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Model+Fetchable.swift"; sourceTree = "<group>"; };
@@ -148,7 +162,7 @@
148162
4736ABC722CBE82A00253EB6 /* Model.swift */,
149163
4736ABCF22CBE9C600253EB6 /* Model+Fetchable.swift */,
150164
4736ABD122CBEBDD00253EB6 /* Model+Persistence.swift */,
151-
472E8F6E23388380005045D2 /* Observable.swift */,
165+
472E8F6E23388380005045D2 /* ObservableValue.swift */,
152166
472E8F7623388E93005045D2 /* Atomic.swift */,
153167
47ACD19922CBE39700B3F1FE /* Assets.xcassets */,
154168
47ACD19B22CBE39700B3F1FE /* LaunchScreen.storyboard */,
@@ -168,6 +182,8 @@
168182
47ACD1B922CBE3E200B3F1FE /* FetchRequests-tvOSTests.xctest */,
169183
47ACD1BB22CBE3E200B3F1FE /* FetchRequests.framework */,
170184
669AE0F0269E446F006DD76C /* FetchRequests-watchOSTests.xctest */,
185+
2A6FBFEE2C920B7300A7CDBE /* FetchRequests.framework */,
186+
2A6FBFF02C920B7300A7CDBE /* FetchRequests-visionOSTests.xctest */,
171187
);
172188
name = Products;
173189
sourceTree = "<group>";
@@ -234,6 +250,20 @@
234250
/* End PBXProject section */
235251

236252
/* Begin PBXReferenceProxy section */
253+
2A6FBFEE2C920B7300A7CDBE /* FetchRequests.framework */ = {
254+
isa = PBXReferenceProxy;
255+
fileType = wrapper.framework;
256+
path = FetchRequests.framework;
257+
remoteRef = 2A6FBFED2C920B7300A7CDBE /* PBXContainerItemProxy */;
258+
sourceTree = BUILT_PRODUCTS_DIR;
259+
};
260+
2A6FBFF02C920B7300A7CDBE /* FetchRequests-visionOSTests.xctest */ = {
261+
isa = PBXReferenceProxy;
262+
fileType = wrapper.cfbundle;
263+
path = "FetchRequests-visionOSTests.xctest";
264+
remoteRef = 2A6FBFEF2C920B7300A7CDBE /* PBXContainerItemProxy */;
265+
sourceTree = BUILT_PRODUCTS_DIR;
266+
};
237267
47ACD1AF22CBE3E200B3F1FE /* FetchRequests.framework */ = {
238268
isa = PBXReferenceProxy;
239269
fileType = wrapper.framework;
@@ -314,7 +344,7 @@
314344
D958902C2A27A3300060A0CF /* SwiftUIView.swift in Sources */,
315345
47ACD19522CBE39600B3F1FE /* ViewController.swift in Sources */,
316346
4736ABD022CBE9C600253EB6 /* Model+Fetchable.swift in Sources */,
317-
472E8F6F23388380005045D2 /* Observable.swift in Sources */,
347+
472E8F6F23388380005045D2 /* ObservableValue.swift in Sources */,
318348
472E8F7723388E93005045D2 /* Atomic.swift in Sources */,
319349
47ACD19322CBE39600B3F1FE /* AppDelegate.swift in Sources */,
320350
);

Example/iOS-Example.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

Lines changed: 4 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Example/iOS-Example/Model+Fetchable.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class ModelCreationToken<T: Model>: ObservableToken {
4141
notificationToken.invalidate()
4242
}
4343

44-
func observe(handler: @escaping (T.RawData) -> Void) {
44+
func observe(handler: @escaping @Sendable @MainActor (T.RawData) -> Void) {
4545
let include = self.include
4646
notificationToken.observe { notification in
4747
guard let object = notification.object as? T else {
@@ -66,7 +66,7 @@ class ModelClearedToken<T: Model>: ObservableToken {
6666
notificationToken.invalidate()
6767
}
6868

69-
func observe(handler: @escaping (()) -> Void) {
69+
func observe(handler: @escaping @Sendable @MainActor (()) -> Void) {
7070
notificationToken.observe { notification in
7171
handler(())
7272
}

Example/iOS-Example/Model.swift

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import Foundation
1111
import FetchRequests
1212

1313
@dynamicMemberLookup
14-
class Model: NSObject {
14+
final class Model: NSObject, @unchecked Sendable {
1515
typealias ID = String
1616

1717
struct RawData: Codable, Identifiable, Equatable {
@@ -20,7 +20,7 @@ class Model: NSObject {
2020
var updatedAt: Date
2121
}
2222

23-
@Observable
23+
@ObservableValue
2424
var data: RawData {
2525
willSet {
2626
integrate(data: newValue)
@@ -117,10 +117,12 @@ extension Model: FetchableObjectProtocol {
117117

118118
func observeIsDeletedChanges(_ handler: @escaping @MainActor () -> Void) -> InvalidatableToken {
119119
self.observe(\.isDeleted, options: [.old, .new]) { object, change in
120-
guard let old = change.oldValue, let new = change.newValue, old != new else {
121-
return
120+
MainActor.assumeIsolated {
121+
guard let old = change.oldValue, let new = change.newValue, old != new else {
122+
return
123+
}
124+
handler()
122125
}
123-
unsafeHandler(for: handler)
124126
}
125127
}
126128

@@ -133,13 +135,6 @@ extension Model: FetchableObjectProtocol {
133135
}
134136
}
135137

136-
@MainActor(unsafe)
137-
private func unsafeHandler(for handler: @MainActor () -> Void) {
138-
assert(Thread.isMainThread)
139-
// This is a dumb wrapper, but I can't otherwise have a "clean" compile
140-
handler()
141-
}
142-
143138
// MARK: - Private Helpers
144139

145140
private extension Model {
Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//
2-
// Observable.swift
2+
// ObservableValue.swift
33
// iOS Example
44
//
55
// Created by Adam Lickel on 9/22/19.
@@ -16,14 +16,14 @@ struct Change<Value> {
1616
}
1717

1818
@propertyWrapper
19-
class Observable<Value> {
19+
class ObservableValue<Value> {
2020
typealias Handler = @MainActor (Change<Value>) -> Void
2121

2222
fileprivate var observers: Atomic<[UUID: Handler]> = Atomic(wrappedValue: [:])
2323

2424
var wrappedValue: Value {
2525
didSet {
26-
unsafeHandler {
26+
MainActor.assumeIsolated {
2727
let change = Change(oldValue: oldValue, newValue: wrappedValue)
2828
let observers = self.observers.wrappedValue
2929

@@ -45,14 +45,7 @@ class Observable<Value> {
4545
}
4646
}
4747

48-
@MainActor(unsafe)
49-
private func unsafeHandler(for handler: @MainActor () -> Void) {
50-
assert(Thread.isMainThread)
51-
// This is a dumb wrapper, but I can't otherwise have a "clean" compile
52-
handler()
53-
}
54-
55-
extension Observable where Value: Equatable {
48+
extension ObservableValue where Value: Equatable {
5649
func observeChanges(handler: @escaping Handler) -> InvalidatableToken {
5750
observe { change in
5851
guard change.oldValue != change.newValue else {
@@ -65,9 +58,9 @@ extension Observable where Value: Equatable {
6558

6659
private class Token<Value>: InvalidatableToken {
6760
let uuid = UUID()
68-
private weak var parent: Observable<Value>?
61+
private weak var parent: ObservableValue<Value>?
6962

70-
init(parent: Observable<Value>) {
63+
init(parent: ObservableValue<Value>) {
7164
self.parent = parent
7265
}
7366

0 commit comments

Comments
 (0)