Skip to content

Commit

Permalink
Support Swift 6 language mode (#20)
Browse files Browse the repository at this point in the history
# Support Swift 6 language mode

## ♻️ Current situation & Problem
SpeziChat currently does not support Swift 6 language mode with complete
concurrency checking.

Addresses #15

## ⚙️ Release Notes 
- Support Swift 6 language mode
- Lift dependencies
- Fix UI tests on iOS and macOS


## 📚 Documentation
Necessary workarounds regarding the MainActor documented


## ✅ Testing
--


## 📝 Code of Conduct & Contributing Guidelines 

By submitting creating this pull request, you agree to follow our [Code
of
Conduct](https://github.com/StanfordSpezi/.github/blob/main/CODE_OF_CONDUCT.md)
and [Contributing
Guidelines](https://github.com/StanfordSpezi/.github/blob/main/CONTRIBUTING.md):
- [x] I agree to follow the [Code of
Conduct](https://github.com/StanfordSpezi/.github/blob/main/CODE_OF_CONDUCT.md)
and [Contributing
Guidelines](https://github.com/StanfordSpezi/.github/blob/main/CONTRIBUTING.md).
  • Loading branch information
philippzagar authored Dec 21, 2024
1 parent 2fa1a93 commit 21e235a
Show file tree
Hide file tree
Showing 7 changed files with 39 additions and 13 deletions.
8 changes: 4 additions & 4 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// swift-tools-version:5.9
// swift-tools-version:6.0

//
// This source file is part of the Stanford Spezi open source project
Expand All @@ -23,9 +23,9 @@ let package = Package(
.library(name: "SpeziChat", targets: ["SpeziChat"])
],
dependencies: [
.package(url: "https://github.com/StanfordSpezi/SpeziFoundation", from: "2.0.0-beta.3"),
.package(url: "https://github.com/StanfordSpezi/SpeziSpeech", from: "1.0.1"),
.package(url: "https://github.com/StanfordSpezi/SpeziViews", from: "1.3.1")
.package(url: "https://github.com/StanfordSpezi/SpeziFoundation", from: "2.0.0"),
.package(url: "https://github.com/StanfordSpezi/SpeziSpeech", from: "1.1.1"),
.package(url: "https://github.com/StanfordSpezi/SpeziViews", from: "1.8.0")
],
targets: [
.target(
Expand Down
1 change: 1 addition & 0 deletions Sources/SpeziChat/ChatView+ShareSheet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ extension ChatView {
func updateUIViewController(_ uiViewController: UIActivityViewController, context: Context) {}
}
#else
@MainActor // On non-macOS SDKs, `UIViewControllerRepresentable` enforces the `MainActor` isolation
struct ShareSheet {
let sharedItem: Data
let sharedItemType: ChatExportFormat
Expand Down
14 changes: 13 additions & 1 deletion Sources/SpeziChat/ChatView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,19 @@ public struct ChatView: View {
MessageInputView($chat, messagePlaceholder: messagePlaceholder, speechToText: speechToText)
.disabled(disableInput)
.onPreferenceChange(MessageInputViewHeightKey.self) { newValue in
messageInputHeight = newValue + 12
// The `onPreferenceChange` view modfier now takes a `@Sendable` closure, therefore we cannot capture `@MainActor` isolated properties
// on the `View` directly anymore: https://developer.apple.com/documentation/swiftui/view/onpreferencechange(_:perform:)?changes=latest_minor
// However, as the `@Sendable` closure is still run on the MainActor (at least in my testing on 18.2 RC SDKs), we can use `MainActor.assumeIsolated`
// to avoid scheduling a `MainActor` `Task`, which could delay execution and cause unexpected UI behavior
if Thread.isMainThread {
MainActor.assumeIsolated {
messageInputHeight = newValue + 12
}
} else {
Task { @MainActor in
messageInputHeight = newValue + 12
}
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/SpeziChat/Helpers/MessageInputViewHeightKey.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import SwiftUI
/// A SwiftUI `PreferenceKey` that is used by the ``MessageInputView`` to propagate the height of the view up the view hierarchy.
public struct MessageInputViewHeightKey: PreferenceKey {
/// Default height of 0.
public static var defaultValue: CGFloat = 0
public static let defaultValue: CGFloat = 0


/// Writes the received value to the `PreferenceKey`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ extension ChatEntity {
/// static let testType = HiddenMessageType(name: "testType")
/// }
/// ```
public struct HiddenMessageType: Codable, Equatable, Hashable {
public struct HiddenMessageType: Codable, Equatable, Hashable, Sendable {
/// Default ``HiddenMessageType``.
public static let unknown = HiddenMessageType(name: "unknown")

Expand Down
19 changes: 16 additions & 3 deletions Tests/UITests/TestAppUITests/TestAppUITests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,13 @@ class TestAppUITests: XCTestCase {
}

func testChatExport() throws { // swiftlint:disable:this function_body_length
// Skip chat export test on visionOS and macOS
#if os(visionOS)
throw XCTSkip("VisionOS is unstable and are skipped at the moment")
#elseif os(macOS)
throw XCTSkip("macOS export to a file is not possible (regular sharesheet is)")
#endif

let app = XCUIApplication()

Check warning on line 50 in Tests/UITests/TestAppUITests/TestAppUITests.swift

View workflow job for this annotation

GitHub Actions / Build and Test UI Tests visionOS (Debug, TestApp-visionOS.xcresult, TestApp-visionOS.xcresult) / Test using xcodebuild or run fastlane

code after 'throw' will never be executed

Check warning on line 50 in Tests/UITests/TestAppUITests/TestAppUITests.swift

View workflow job for this annotation

GitHub Actions / Build and Test UI Tests visionOS (Release, TestApp-visionOS-Release.xcresult, TestApp-visionOS-Re... / Test using xcodebuild or run fastlane

code after 'throw' will never be executed

Check warning on line 50 in Tests/UITests/TestAppUITests/TestAppUITests.swift

View workflow job for this annotation

GitHub Actions / Build and Test UI Tests visionOS (Release, TestApp-visionOS-Release.xcresult, TestApp-visionOS-Re... / Test using xcodebuild or run fastlane

code after 'throw' will never be executed
let filesApp = XCUIApplication(bundleIdentifier: "com.apple.DocumentsApp")
let maxRetries = 10
Expand Down Expand Up @@ -78,7 +81,13 @@ class TestAppUITests: XCTestCase {
#endif

sleep(3)
XCTAssert(app.buttons["Save"].waitForExistence(timeout: 2))

// Select "On My iPhone / iPad" directory, if necessary
let predicate = NSPredicate(format: "label BEGINSWITH[c] %@", "On My")
let matchingStaticTexts = app.staticTexts.containing(predicate)
matchingStaticTexts.allElementsBoundByIndex.first?.tap()

XCTAssert(app.buttons["Save"].waitForExistence(timeout: 5))
app.buttons["Save"].tap()
sleep(10) // Wait until file is saved

Expand Down Expand Up @@ -144,8 +153,12 @@ class TestAppUITests: XCTestCase {
XCTAssert(app.staticTexts["SpeziChat"].waitForExistence(timeout: 1))
XCTAssert(app.buttons["Speaker strikethrough"].waitForExistence(timeout: 2))
XCTAssert(!app.buttons["Speaker"].waitForExistence(timeout: 2))


#if os(macOS)
app.buttons["Speaker strikethrough"].firstMatch.tap() // on macOS, need to match for first speaker that is found
#else
app.buttons["Speaker strikethrough"].tap()
#endif

XCTAssert(!app.buttons["Speaker strikethrough"].waitForExistence(timeout: 2))
XCTAssert(app.buttons["Speaker"].waitForExistence(timeout: 2))
Expand Down
6 changes: 3 additions & 3 deletions Tests/UITests/UITests.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_STRICT_CONCURRENCY = complete;
SWIFT_VERSION = 5.0;
SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2,7";
};
name = Debug;
Expand Down Expand Up @@ -437,7 +437,7 @@
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_STRICT_CONCURRENCY = complete;
SWIFT_VERSION = 5.0;
SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2,7";
};
name = Release;
Expand Down Expand Up @@ -584,7 +584,7 @@
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_STRICT_CONCURRENCY = complete;
SWIFT_VERSION = 5.0;
SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2,7";
};
name = Test;
Expand Down

0 comments on commit 21e235a

Please sign in to comment.