Skip to content

Commit a0c90d7

Browse files
authored
[Fix]Tests and Warnings on Xcode 26 (#953)
1 parent b50d508 commit a0c90d7

File tree

25 files changed

+246
-84
lines changed

25 files changed

+246
-84
lines changed

Sources/StreamVideo/CallKit/CallKitService.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ open class CallKitService: NSObject, CXProviderDelegate, @unchecked Sendable {
121121
localizedCallerName: String,
122122
callerId: String,
123123
hasVideo: Bool = false,
124-
completion: @escaping (Error?) -> Void
124+
completion: @Sendable @escaping (Error?) -> Void
125125
) {
126126
let (callUUID, callUpdate) = buildCallUpdate(
127127
cid: cid,

Sources/StreamVideo/Utils/Extensions/Combine/Publisher+AsyncStream.swift

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,13 @@ public extension Publisher where Output: Sendable {
5353
function: StaticString = #function,
5454
line: UInt = #line
5555
) async throws -> Output {
56-
nonisolated(unsafe) let selfReference = self
57-
return try await Task(
56+
try await Task(
5857
timeoutInSeconds: timeoutInSeconds,
5958
file: file,
6059
function: function,
6160
line: line
62-
) {
63-
try await selfReference.firstValue(file: file, line: line)
61+
) { [self] in
62+
try await self.firstValue(file: file, line: line)
6463
}.value
6564
}
6665

Sources/StreamVideo/Utils/Logger/Logger.swift

Lines changed: 55 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -239,18 +239,19 @@ public enum LogConfig {
239239
}
240240
}
241241

242-
nonisolated(unsafe) private static var _destinations: [LogDestination]?
242+
private static let _destinations: AtomicStorage<[LogDestination]?> = .init(nil)
243243

244244
/// Destinations for the default logger. Please see `LogDestination`.
245245
/// Defaults to only `ConsoleLogDestination`, which only prints the messages.
246246
///
247247
/// - Important: Other options in `ChatClientConfig.Logging` will not take affect if this is changed.
248248
public static var destinations: [LogDestination] {
249249
get {
250-
if let destinations = _destinations {
250+
if let destinations = _destinations.get() {
251251
return destinations
252252
} else {
253-
_destinations = destinationTypes.map {
253+
let _destinationTypes = destinationTypes
254+
let newDestinations = _destinationTypes.map {
254255
$0.init(
255256
identifier: identifier,
256257
level: level,
@@ -266,12 +267,13 @@ public enum LogConfig {
266267
showFunctionName: showFunctionName
267268
)
268269
}
269-
return _destinations!
270+
_destinations.set(newDestinations)
271+
return newDestinations
270272
}
271273
}
272274
set {
273275
invalidateLogger()
274-
_destinations = newValue
276+
_destinations.set(newValue)
275277
}
276278
}
277279

@@ -303,25 +305,29 @@ public enum LogConfig {
303305
/// Invalidates the current logger instance so it can be recreated.
304306
private static func invalidateLogger() {
305307
_logger = nil
306-
_destinations = nil
308+
_destinations.set(nil)
307309
}
308310
}
309311

310312
/// Entity used for logging messages.
311-
public class Logger {
313+
public class Logger: @unchecked Sendable {
312314
/// Identifier of the Logger. Will be visible if a destination has `showIdentifiers` enabled.
313315
public let identifier: String
314316

315317
/// Destinations for this logger.
316318
/// See `LogDestination` protocol for details.
317-
public var destinations: [LogDestination]
318-
319+
@Atomic private var _destinations: [LogDestination]
320+
public var destinations: [LogDestination] {
321+
get { _destinations }
322+
set { _destinations = newValue }
323+
}
324+
319325
private let loggerQueue = DispatchQueue(label: "LoggerQueue \(UUID())")
320326

321327
/// Init a logger with a given identifier and destinations.
322328
public init(identifier: String = "", destinations: [LogDestination] = []) {
323329
self.identifier = identifier
324-
self.destinations = destinations
330+
_destinations = destinations
325331
}
326332

327333
/// Allows logger to be called as function.
@@ -371,23 +377,33 @@ public class Logger {
371377
subsystems: LogSubsystem = .other,
372378
error: Error?
373379
) {
374-
let enabledDestinations = destinations.filter { $0.isEnabled(level: level, subsystems: subsystems) }
375-
guard !enabledDestinations.isEmpty else { return }
376-
377-
let logDetails = LogDetails(
378-
loggerIdentifier: identifier,
379-
subsystem: subsystems,
380-
level: level,
381-
date: Date(),
382-
message: String(describing: message()),
383-
threadName: threadName,
384-
functionName: functionName,
385-
fileName: fileName,
386-
lineNumber: lineNumber,
387-
error: error
388-
)
389-
for destination in enabledDestinations {
390-
loggerQueue.async {
380+
let resolvedMessage = String(describing: message())
381+
let resolvedError = error
382+
let resolvedThreadName = threadName
383+
let timestamp = Date()
384+
let loggerIdentifier = identifier
385+
let destinations = self.destinations
386+
387+
loggerQueue.async {
388+
let enabledDestinations = destinations.filter {
389+
$0.isEnabled(level: level, subsystems: subsystems)
390+
}
391+
guard !enabledDestinations.isEmpty else { return }
392+
393+
let logDetails = LogDetails(
394+
loggerIdentifier: loggerIdentifier,
395+
subsystem: subsystems,
396+
level: level,
397+
date: timestamp,
398+
message: resolvedMessage,
399+
threadName: resolvedThreadName,
400+
functionName: functionName,
401+
fileName: fileName,
402+
lineNumber: lineNumber,
403+
error: resolvedError
404+
)
405+
406+
for destination in enabledDestinations {
391407
destination.process(logDetails: logDetails)
392408
}
393409
}
@@ -588,3 +604,15 @@ extension Data {
588604
}
589605
}
590606
}
607+
608+
final class AtomicStorage<Element>: @unchecked Sendable {
609+
610+
private let queue = UnfairQueue()
611+
private var value: Element
612+
613+
init(_ initial: Element) { value = initial }
614+
615+
func get() -> Element { queue.sync { value } }
616+
617+
func set(_ newValue: Element) { queue.sync { value = newValue } }
618+
}

Sources/StreamVideo/Utils/PermissionsStore/Namespace/Components/CameraPermissionProvider.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ protocol CameraPermissionProviding {
1313

1414
/// Requests camera permission from the user.
1515
/// - Parameter completion: Called with `true` if permission granted.
16-
func requestPermission(_ completion: @escaping (Bool) -> Void)
16+
func requestPermission(_ completion: @Sendable @escaping (Bool) -> Void)
1717
}
1818

1919
/// Default implementation for camera permission management using AVFoundation.
@@ -33,7 +33,7 @@ final class StreamCameraPermissionProvider: CameraPermissionProviding {
3333
}
3434
}
3535

36-
func requestPermission(_ completion: @escaping (Bool) -> Void) {
36+
func requestPermission(_ completion: @Sendable @escaping (Bool) -> Void) {
3737
AVCaptureDevice
3838
.requestAccess(for: .video, completionHandler: completion)
3939
}

Sources/StreamVideo/Utils/PermissionsStore/Namespace/Components/MicrophonePermissionProvider.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ protocol MicrophonePermissionProviding {
1313

1414
/// Requests microphone permission from the user.
1515
/// - Parameter completion: Called with `true` if permission granted.
16-
func requestPermission(_ completion: @escaping (Bool) -> Void)
16+
func requestPermission(_ completion: @Sendable @escaping (Bool) -> Void)
1717
}
1818

1919
/// Default implementation for microphone permission management using
@@ -45,7 +45,7 @@ final class StreamMicrophonePermissionProvider: MicrophonePermissionProviding {
4545
}
4646
}
4747

48-
func requestPermission(_ completion: @escaping (Bool) -> Void) {
48+
func requestPermission(_ completion: @Sendable @escaping (Bool) -> Void) {
4949
if #available(iOS 17.0, *) {
5050
AVAudioApplication
5151
.requestRecordPermission(completionHandler: completion)

Sources/StreamVideo/Utils/PermissionsStore/Namespace/Components/PushNotificationsPermissionProvider.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ protocol PushNotificationsPermissionProviding {
1818
/// - completion: Called with grant status and optional error.
1919
func requestPermission(
2020
with options: UNAuthorizationOptions,
21-
_ completion: @escaping (Bool, Error?) -> Void
21+
_ completion: @Sendable @escaping (Bool, Error?) -> Void
2222
)
2323
}
2424

@@ -56,7 +56,7 @@ final class StreamPushNotificationsPermissionProvider: PushNotificationsPermissi
5656

5757
func requestPermission(
5858
with options: UNAuthorizationOptions,
59-
_ completion: @escaping (Bool, Error?) -> Void
59+
_ completion: @Sendable @escaping (Bool, Error?) -> Void
6060
) {
6161
UNUserNotificationCenter
6262
.current()

Sources/StreamVideo/Utils/Store/StoreNamespace.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ import Foundation
3939
/// ```swift
4040
/// let store = MyFeature.store(initialState: .default)
4141
/// ```
42-
protocol StoreNamespace {
42+
protocol StoreNamespace: Sendable {
4343
/// The state type managed by this store.
4444
///
4545
/// Must be `Equatable` to enable change detection for publishers.

Sources/StreamVideo/WebRTC/Screensharing/BroadcastBufferReader.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import Foundation
88
import StreamWebRTC
99

1010
private class Message {
11-
nonisolated(unsafe) static let imageContextVar: CIContext? = {
11+
static let imageContextVar: CIContext? = {
1212
var imageContext = CIContext(options: nil)
1313
return imageContext
1414
}()

Sources/StreamVideo/WebRTC/v2/Extensions/AVFoundation/AVAudioRecorder+Sendable.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
import AVFoundation
66
import Combine
77

8-
#if compiler(>=6.0)
9-
extension AVAudioRecorder: @retroactive @unchecked Sendable {}
10-
#else
8+
#if compiler(<6.0)
119
extension AVAudioRecorder: @unchecked Sendable {}
1210
#endif

Sources/StreamVideo/WebRTC/v2/VideoCapturing/ActionHandlers/Camera/CameraInterruptionsHandler.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,10 @@ extension AVCaptureSession.InterruptionReason {
134134
return ".videoDeviceNotAvailableWithMultipleForegroundApps"
135135
case .videoDeviceNotAvailableDueToSystemPressure:
136136
return ".videoDeviceNotAvailableDueToSystemPressure"
137+
#if compiler(>=6.2)
138+
case .sensitiveContentMitigationActivated:
139+
return ".sensitiveContentMitigationActivated"
140+
#endif
137141
@unknown default:
138142
return "\(self)"
139143
}

0 commit comments

Comments
 (0)