// Control how video fits within the viewvideoView.layoutMode = .fill // .fill or .fit// Mirror video (useful for front camera)videoView.mirrorMode = .auto // .auto, .mirror, or .off// Rotation overridevideoView.rotationOverride = .r90
// Check if switching is supportedlet canSwitch = try await CameraCapturer.canSwitchPosition()// Get current camera trackif let cameraTrack = room.localParticipant.cameraTrack { try await cameraTrack.capturer.switchCameraPosition()}
On iOS 16+, you can enable camera access when your app is in the background:
if let cameraCapturer = cameraTrack?.capturer as? CameraCapturer { if cameraCapturer.isMultitaskingAccessSupported { cameraCapturer.isMultitaskingAccessEnabled = true }}
// For playback onlyAudioSessionConfiguration.playback// For video calls (speaker)AudioSessionConfiguration.playAndRecordSpeaker// For voice calls (receiver)AudioSessionConfiguration.playAndRecordReceiver
See AudioSessionConfiguration.swift:17 for available configurations.
<key>NSCameraUsageDescription</key><string>This app needs camera access for video calls</string><key>NSMicrophoneUsageDescription</key><string>This app needs microphone access for audio calls</string>
VideoView is a UI component and must be accessed from the main thread.
// Correct: Update VideoView on main threadDispatchQueue.main.async { videoView.track = track}// Or use MainActorTask { @MainActor in videoView.track = track}
Other SDK classes (Room, Participant, Track) can be accessed from any thread.
For collection views with many video cells, disable rendering for off-screen cells:
// Disable rendering when cell scrolls off screenvideoView.isEnabled = false// Re-enable when cell becomes visiblevideoView.isEnabled = true
Avoid using UICollectionViewDelegate’s willDisplay/didEndDisplaying as they can be unreliable. Instead, use a timer to periodically check visible cells.