SharePlay and Personas
One of the big benefits of VisionOS is the feeling of presence when in FaceTime. So how do you hook it into your apps and games?
//start an activity
let activity = GameShareActivity()
_ = try await activity.activate()With an activity you can check sessions:
//listen for sessions
for await session in GameShareActivity.sessions() {
}And with sessions you can listen for messages:
self.session = session
let messenger = GroupSessionMessenger(session: session)
self.messenger = messenger
for await (message, _) in messenger.messages(of: String.self) {
}And of course, you'll need something to send messages:
await messenger?.send(data)What is the data? There are a few options, I keep it as a string which as a bunch of json I can handle as I want.
Putting it all together
class SharePlayManager: ObservableObject {
static let shared = SharePlayManager()
private var session: GroupSession<GameShareActivity>? = nil
private var messenger: GroupSessionMessenger? = nil
private var sessionListeningTask: Task<Void, Never>? = nil
private var isListening = false
init() {
// Start listening for SharePlay sessions immediately when app launches
startListeningForSessions()
}
private func startListeningForSessions() {
guard !isListening else { return }
isListening = true
sessionListeningTask = Task {
for await session in GameShareActivity.sessions() {
await handleSession(session)
break // Only handle the first session
}
}
}
private func handleSession(_ session: GroupSession<GameShareActivity>) async {
self.session = session
let messenger = GroupSessionMessenger(session: session)
self.messenger = messenger
// Setup message listener
Task.detached { [weak self] in
for await (message, _) in messenger.messages(of: String.self) {
//handle message received
}
}
session.join()
}
func startSharePlay() async {
Task {
do {
let activity = GameShareActivity()
_ = try await activity.activate()
// The session will be automatically detected by our listener
} catch {
print("Failed to start SharePlay: \(error)")
}
}
}
func sendGameEvent(_ data: String) async {
Task {
do {
try await messenger?.send(data)
} catch {
print("Failed to send message: \(error)")
}
}
}
}Wait, what about Personas and all that?
Automatically handled 😃 But if you want to tweak some things, here are some options:
let systemCoordinator = await session.systemCoordinator
var configuration = SystemCoordinator.Configuration()
// make this change
configuration.supportsGroupImmersiveSpace = true
configuration.spatialTemplatePreference = .sideBySide
systemCoordinator?.configuration = configurationAll done!