Skip to content

Commit 98fc26e

Browse files
pblazejclaude
andcommitted
Fix Xcode 27 beta warnings
- Silence unstructured throwing Task warnings with try? / do-catch - Replace deprecated onChange(of:perform:) via View+OnChange compat shim - Use .task(id:) for visionOS immersive space lifecycle - Wrap Slider-based RemoteAudioVolumeControl in #if !os(tvOS) (also fixes pre-existing tvOS build break) - Ignore .claude/ in git Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 4dfad05 commit 98fc26e

12 files changed

Lines changed: 109 additions & 50 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,6 @@ iOSInjectionProject/
9292

9393
# Ignore license files
9494
*.license
95+
96+
# Claude Code
97+
.claude/

LiveKitExample-dev.xcworkspace/xcshareddata/swiftpm/Package.resolved

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

LiveKitExample.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
68A50EE82C4C1ED500D2DE17 /* ScreenShareSourcePickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68A50ED32C4C1ED500D2DE17 /* ScreenShareSourcePickerView.swift */; };
2727
68A50EEA2C4C1ED500D2DE17 /* Participant+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68A50ECF2C4C1ED500D2DE17 /* Participant+Helpers.swift */; };
2828
68A50EEB2C4C1ED500D2DE17 /* Binding+OptionSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68A50ECB2C4C1ED500D2DE17 /* Binding+OptionSet.swift */; };
29+
7BBEBA9A2D79219600586EC4 /* View+OnChange.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BBEBA9B2D79219600586EC4 /* View+OnChange.swift */; };
2930
68A50EEC2C4C1ED500D2DE17 /* ParticipantView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68A50EDA2C4C1ED500D2DE17 /* ParticipantView.swift */; };
3031
68A50EED2C4C1ED500D2DE17 /* ConnectionHistory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68A50ECD2C4C1ED500D2DE17 /* ConnectionHistory.swift */; };
3132
68A50EEF2C4C1ED500D2DE17 /* Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68A50ECC2C4C1ED500D2DE17 /* Bundle.swift */; };
@@ -81,6 +82,7 @@
8182
68A50EC82C4C1ED500D2DE17 /* AppContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppContext.swift; sourceTree = "<group>"; };
8283
68A50EC92C4C1ED500D2DE17 /* RoomContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomContext.swift; sourceTree = "<group>"; };
8384
68A50ECB2C4C1ED500D2DE17 /* Binding+OptionSet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Binding+OptionSet.swift"; sourceTree = "<group>"; };
85+
7BBEBA9B2D79219600586EC4 /* View+OnChange.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+OnChange.swift"; sourceTree = "<group>"; };
8486
68A50ECC2C4C1ED500D2DE17 /* Bundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bundle.swift; sourceTree = "<group>"; };
8587
68A50ECD2C4C1ED500D2DE17 /* ConnectionHistory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectionHistory.swift; sourceTree = "<group>"; };
8688
68A50ECE2C4C1ED500D2DE17 /* ExampleRoomMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExampleRoomMessage.swift; sourceTree = "<group>"; };
@@ -247,6 +249,7 @@
247249
7BBEBA822D791CAF00586EC4 /* CIImage.swift */,
248250
68A50ECB2C4C1ED500D2DE17 /* Binding+OptionSet.swift */,
249251
68A50ECC2C4C1ED500D2DE17 /* Bundle.swift */,
252+
7BBEBA9B2D79219600586EC4 /* View+OnChange.swift */,
250253
);
251254
path = Extensions;
252255
sourceTree = "<group>";
@@ -398,6 +401,7 @@
398401
68A50EE82C4C1ED500D2DE17 /* ScreenShareSourcePickerView.swift in Sources */,
399402
68A50EEA2C4C1ED500D2DE17 /* Participant+Helpers.swift in Sources */,
400403
68A50EEB2C4C1ED500D2DE17 /* Binding+OptionSet.swift in Sources */,
404+
7BBEBA9A2D79219600586EC4 /* View+OnChange.swift in Sources */,
401405
6888FBE12C66B7B400AB93C1 /* ImmersiveView.swift in Sources */,
402406
68A50EEC2C4C1ED500D2DE17 /* ParticipantView.swift in Sources */,
403407
7BBEBA832D791CB300586EC4 /* CIImage.swift in Sources */,
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright 2026 LiveKit
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import SwiftUI
18+
19+
#if !os(tvOS) && !os(visionOS)
20+
extension View {
21+
@available(iOS, introduced: 14.0, obsoleted: 17.0)
22+
@available(macOS, introduced: 11.0, obsoleted: 14.0)
23+
func onChange(of value: some Equatable, _ action: @escaping () -> Void) -> some View {
24+
onChange(of: value) { _ in action() }
25+
}
26+
}
27+
#endif

Multiplatform/Views/ConnectView.swift

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,12 @@ struct ConnectView: View {
9797

9898
LKButton(title: "Connect") {
9999
Task { @MainActor in
100-
let room = try await roomCtx.connect()
101-
appCtx.connectionHistory.update(room: room, e2ee: roomCtx.isE2eeEnabled, e2eeKey: roomCtx.e2eeKey)
100+
do {
101+
let room = try await roomCtx.connect()
102+
appCtx.connectionHistory.update(room: room, e2ee: roomCtx.isE2eeEnabled, e2eeKey: roomCtx.e2eeKey)
103+
} catch {
104+
print("Failed to connect: \(error)")
105+
}
102106
}
103107
}
104108

@@ -107,8 +111,12 @@ struct ConnectView: View {
107111
ForEach(appCtx.connectionHistory.sortedByUpdated) { entry in
108112
Button {
109113
Task { @MainActor in
110-
let room = try await roomCtx.connect(entry: entry)
111-
appCtx.connectionHistory.update(room: room, e2ee: roomCtx.isE2eeEnabled, e2eeKey: roomCtx.e2eeKey)
114+
do {
115+
let room = try await roomCtx.connect(entry: entry)
116+
appCtx.connectionHistory.update(room: room, e2ee: roomCtx.isE2eeEnabled, e2eeKey: roomCtx.e2eeKey)
117+
} catch {
118+
print("Failed to connect: \(error)")
119+
}
112120
}
113121
} label: {
114122
Image(systemSymbol: .boltFill)

Multiplatform/Views/MessagesPanel.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ struct MessagesPanel: View {
3737
.onAppear(perform: {
3838
scrollToBottom(scrollView)
3939
})
40-
.onChange(of: roomCtx.messages, perform: { _ in
40+
.onChange(of: roomCtx.messages) {
4141
scrollToBottom(scrollView)
42-
})
42+
}
4343
.frame(
4444
minWidth: 0,
4545
maxWidth: .infinity,

Multiplatform/Views/ParticipantView.swift

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,11 +141,11 @@ struct ParticipantView: View {
141141
Menu {
142142
if case .subscribed = remotePub.subscriptionState {
143143
Button("Unsubscribe") {
144-
Task { try await remotePub.set(subscribed: false) }
144+
Task { try? await remotePub.set(subscribed: false) }
145145
}
146146
} else if case .unsubscribed = remotePub.subscriptionState {
147147
Button("Subscribe") {
148-
Task { try await remotePub.set(subscribed: true) }
148+
Task { try? await remotePub.set(subscribed: true) }
149149
}
150150
}
151151
} label: {
@@ -185,11 +185,11 @@ struct ParticipantView: View {
185185
Menu {
186186
if case .subscribed = remotePub.subscriptionState {
187187
Button("Unsubscribe") {
188-
Task { try await remotePub.set(subscribed: false) }
188+
Task { try? await remotePub.set(subscribed: false) }
189189
}
190190
} else if case .unsubscribed = remotePub.subscriptionState {
191191
Button("Subscribe") {
192-
Task { try await remotePub.set(subscribed: true) }
192+
Task { try? await remotePub.set(subscribed: true) }
193193
}
194194
}
195195
} label: {
@@ -221,11 +221,13 @@ struct ParticipantView: View {
221221
.foregroundColor(Color.white)
222222
}
223223

224+
#if !os(tvOS)
224225
ForEach(remoteAudioTracks) { remoteAudioTrack in
225226
RemoteAudioVolumeControl(track: remoteAudioTrack,
226227
showsPercentage: geometry.size.width > 180)
227228
.fixedSize()
228229
}
230+
#endif
229231

230232
if participant.connectionQuality == .excellent {
231233
Image(systemSymbol: .wifi)
@@ -267,6 +269,7 @@ struct ParticipantView: View {
267269
}
268270
}
269271

272+
#if !os(tvOS)
270273
struct RemoteAudioVolumeControl: View {
271274
let track: RemoteAudioTrack
272275
let showsPercentage: Bool
@@ -375,6 +378,7 @@ private extension View {
375378
#endif
376379
}
377380
}
381+
#endif
378382

379383
struct StatsView: View {
380384
private let track: Track

Multiplatform/Views/PublishOptionsView.swift

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ struct PublishOptionsView: View {
7171
ForEach(VideoCodec.all) {
7272
Text($0.id.uppercased()).tag($0 as VideoCodec?)
7373
}
74-
}.onChange(of: preferredVideoCodec) { newValue in
75-
if newValue?.isSVC ?? false {
74+
}.onChange(of: preferredVideoCodec) {
75+
if preferredVideoCodec?.isSVC ?? false {
7676
preferredBackupVideoCodec = .vp8
7777
} else {
7878
preferredBackupVideoCodec = nil
@@ -160,9 +160,11 @@ struct PublishOptionsView: View {
160160
}
161161
.onAppear(perform: {
162162
Task {
163-
devices = try await CameraCapturer.captureDevices()
164-
#if !os(macOS)
165-
.singleDeviceforEachPosition()
163+
let all = await (try? CameraCapturer.captureDevices()) ?? []
164+
#if os(macOS)
165+
devices = all
166+
#else
167+
devices = all.singleDeviceforEachPosition()
166168
#endif
167169
}
168170
})

Multiplatform/Views/RoomContextView.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,12 @@ struct RoomContextView: View {
5959
roomCtx.isE2eeEnabled = e2ee
6060
roomCtx.e2eeKey = e2eeKey
6161
if !roomCtx.token.isEmpty {
62-
let room = try await roomCtx.connect()
63-
appCtx.connectionHistory.update(room: room, e2ee: e2ee, e2eeKey: e2eeKey)
62+
do {
63+
let room = try await roomCtx.connect()
64+
appCtx.connectionHistory.update(room: room, e2ee: e2ee, e2eeKey: e2eeKey)
65+
} catch {
66+
print("Failed to connect: \(error)")
67+
}
6468
}
6569
}
6670
})

Multiplatform/Views/RoomSwitchView.swift

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,16 +55,14 @@ struct RoomSwitchView: View {
5555
}
5656
.preferredColorScheme(.dark)
5757
.navigationTitle(navigatonTitle)
58-
.onChange(of: shouldShowRoomView) { newValue in
59-
#if os(visionOS)
60-
Task {
61-
if newValue {
58+
#if os(visionOS)
59+
.task(id: shouldShowRoomView) {
60+
if shouldShowRoomView {
6261
await openImmersiveSpace(id: "ImmersiveSpace")
6362
} else {
6463
await dismissImmersiveSpace()
6564
}
6665
}
67-
#endif
68-
}
66+
#endif
6967
}
7068
}

0 commit comments

Comments
 (0)