我的 iOS 项目中有多个实时侦听器,它们应该实时侦听来自 supabase 的事件。我正在使用当前的 realtimeV2,但有时似乎没有推理,它就不会被触发。其他时候它被解雇得很好。广播也是如此。
我有一个
DataManager
类,我将其注入到 @Environment
中,因此每当应用程序启动时我都会设置大量任务,然后该对象会不断侦听来自数据库的更改以保持用户设备正常运行 -最新数据。
我在这里使用的功能是一个“QRScanner”,它执行以下操作。
这是我的
init
的DataManager
。重申一下。该初始化程序在应用程序启动时调用,然后调度所有侦听器。该对象始终存在于 @Environment
中的
root view
中
public init(_ client: SupabaseClient) {
self.client = client
supabaseUser = nil
loadingRewards = true
rewards = []
rewardWeeklySchedules = []
customerProfiles = []
rewardTransactions = []
Task.detached(priority: .high) { @MainActor in
self.supabaseUser = try? await self.client.auth.user()
try? await self.refreshProfile()
try? await self.loadWeeklySchedules()
try? await self.loadRewards()
}
Task.detached(priority: .background) { @MainActor in
let channel = await self.client.realtimeV2.channel("public:messages")
self.singleProfileRealtimeUpdates(channel)
self.rewardsUpdatedRealtimeUpdate(channel)
self.rewardScheduleRealtimeUpdate(channel)
await channel.subscribe()
}
}
这是我最常遇到问题的实时侦听器之一。我期望发生的是,每当
DeviceB
扫描 DeviceA
的二维码时,它就会显示 DeviceA
的个人资料。他们对其进行更改,并将其推送到数据库。那时它应该触发 DeviceA
的更新,以便与真实数据同步。
func singleProfileRealtimeUpdates(_ channel: RealtimeChannelV2) {
guard let profile else {
return
}
Task.detached(priority: .background) {
for await update in await channel.postgresChange(UpdateAction.self, table: "reward_profiles", filter: "user_id=eq.\(profile.id)") {
withAnimation {
self.profile = try? update.decodeRecord(as: Profile.self, decoder: JSONDecoder())
}
}
}
}
如果您有其他解决方案,除了
Realtime
之外,我100%愿意改变它的工作方式。我唯一可以考虑的是,也许我需要为每个侦听器设置自定义通道,并让它们仅对特定通道进行唯一响应。现在我只对所有这些使用 public:messages
。
但是我有一个我担心的限制;这是一个白标应用程序,这意味着我们将针对许多不同的客户重新命名它。我可以选择为每个品牌创建自定义频道,或者只是为特定听众创建整体自定义频道,这没有什么区别,但我不知道 SUBABASE 对此有何限制。
我是 Supabase Mobile SDK 团队的 Guilherme。
可能发生的情况是,您的任务可能在
await channel.subscribe()
调用之后开始,这不会在订阅中包含 postgresChange
,但这种情况会在代码中触发前置条件失败,您是否看到触发了任何前置条件有时?
要解决上述问题,您需要从
postgresChange
中调用 Task.detached
方法,例如:
func singleProfileRealtimeUpdates(_ channel: RealtimeChannelV2) async {
guard let profile else {
return
}
let updates = await channel.postgresChange(UpdateAction.self, table: "reward_profiles", filter: "user_id=eq.\(profile.id)")
Task.detached(priority: .background) {
for await update in updates {
withAnimation {
self.profile = try? update.decodeRecord(as: Profile.self, decoder: JSONDecoder())
}
}
}
}