macOS
The iOS package is a macOS package too — one Swift Package, one AppEngine, the same delegate. This page covers only what is different on the desktop: windows instead of view controllers, and sandbox entitlements on top of the Info.plist prompts.
Requirements#
| Minimum | |
|---|---|
| macOS | 11 Big Sur |
| Xcode | 15 |
| Swift | 5.9 |
| Architectures | Apple silicon and Intel (universal xcframework) |
Installation#
Add the package to your Mac target exactly as on iOS. The manifest declares both platforms.
dependencies: [.package(url: "https://github.com/AppLooma-RTC/iOS-SDK", from: "0.6.1")],targets: [.target(name: "MyMacApp", dependencies: [.product(name: "AppLoomaRTC", package: "iOS-SDK")])]
In Xcode: File → Add Package Dependencies…, paste the URL, and addAppLoomaRTC to your macOS target.
Sandbox and entitlements
A sandboxed Mac app must ask for the network and the hardware explicitly, or the call connects and no audio ever leaves the machine.
<key>com.apple.security.network.client</key> <true/><key>com.apple.security.device.audio-input</key> <true/><key>com.apple.security.device.camera</key> <true/>
<key>NSCameraUsageDescription</key><string>Shows you to the people you are calling.</string><key>NSMicrophoneUsageDescription</key><string>Lets the people you are calling hear you.</string>
Screen share on the Mac
Screen share from the Swift SDK is on the roadmap. If your product needs it today, the Electron path ships with window and display picking built in.
A minimal call window#
import AppKitimport AppLoomaRTCfinal class CallWindowController: NSWindowController, AppEngineDelegate {private lazy var engine = AppEngine.create(appId: "YOUR_APP_ID", delegate: self)private let remoteView = AppVideoView()private let localView = AppVideoView()func start(token: String, wsUrl: String) {let content = NSView(frame: NSRect(x: 0, y: 0, width: 960, height: 600))remoteView.frame = content.boundsremoteView.autoresizingMask = [.width, .height]localView.frame = NSRect(x: 780, y: 420, width: 160, height: 160)content.addSubview(remoteView)content.addSubview(localView)window?.contentView = contentTask {try await engine.joinChannel(token: token, wsUrl: wsUrl,options: AppJoinOptions(role: .host, camera: true))localView.attachLocal(engine: engine)}}func appEngine(_ engine: AppEngine, trackSubscribedFor user: AppRemoteUser) {remoteView.attach(user: user)}func windowWillClose(_ notification: Notification) {Task { await engine.leaveChannel() }}}
SwiftUI
AppVideoView is an NSView on macOS. Wrap it once withNSViewRepresentable and use it like any other view.
struct RemoteVideo: NSViewRepresentable {let user: AppRemoteUserfunc makeNSView(context: Context) -> AppVideoView { AppVideoView() }func updateNSView(_ view: AppVideoView, context: Context) { view.attach(user: user) }}
Cameras and microphones#
- The SDK follows the system default camera and microphone; when the user changes it in System Settings, the call follows. A per-call device picker is on the roadmap.
- Nothing to do for Bluetooth or USB audio: macOS routes to whatever the user has selected in the menu bar.
- Video publishes at 1080p with simulcast by default, the same as every other platform.
Differences from iOS#
| iOS | macOS | |
|---|---|---|
| Rendering view | UIView | NSView |
| Background audio | Needs the audio background mode | Runs while the window is hidden; nothing to declare |
| Permission prompt | On first use, per app | On first use, plus the sandbox entitlements above |
| Screen share | Roadmap | Roadmap (use Electron today) |
| Camera | Front and back | Built-in or the system default external camera |