实时组合@published 数组的最佳实践?

Best practices for combining @published arrays in real time?

所以我正在编写代码,可以使用本地(MultiPeers 和低功耗蓝牙)和网络(使用实时数据库按位置查找附近用户)找到附近的用户

    class ViewModel: ObservableObject{

    @Published nearbyMultipeers: [User]  = []
    @Published nearbyBluetoothUsers: [User]  = []
    @Published nearbyGeoUsers: [User]  = []


    // This gets the nearby users by GeoLocation and updates the nearbyGeoUsers array 
    func getNearbyUsersByGeoLocation(){ /* ... */ } 
   
   // This will loop through all of the nearby users obtained via multipeer and grab their user data from the database and append it to the nearbyMultipeers array 
    func getUsersFromPeers(nearbyPeers: [Peer])( /* ... */ )

    

  
   


}

现在这些列表将不断更新(因为 multipeers 仅在应用程序处于前台时有效,您自然会进出附近用户的范围)。

有时会出现重复数据的问题,nearbyBluetoothUsers可能包含一些nearbyMultipeersnearbyGeoUsers可能包含一些nearbyBluetoothUsers等,我需要一个方法实时显示所有这些用户的列表而不显示重复数据。

为简单起见,假设我将它们显示在这样的列表中

struct NearbyUsersView: View {

       // This observable object contains information on the nearby peers //(multipeers)
       // This is how I get the nearby peers 
       @ObservableObject var multipeerDataSource: MultipeerDataSource

       var body: some View {

           VStack{

              // Ideally I would display them in a scrollable list of some sort, this is 
                  // just to illustrate my issue 

                  ForEach(viewModel.$allUsersExcludingDuplicates){. user in 
                            
                           Text(user.name) 
     
                    }

         }
           .onAppear{
 
                      viewModel.getNearbyUsersByGeoLocation()
                      

}
           .onChange(of: multipeerDataSource.$nearbyPeers) { nearbyPeers

            // this array contains the nearby peers (users) 
           // We have to actually convert it to a `User`, or fetch the user data because //the objects here won't be the actual data it may just contain the user Id or some sort // so we have to grab the actual data 
            viewModel.getUsersFromPeers(nearbyPeers)

} 



    }

}

我省略了通过蓝牙抓取,因为没有必要理解这个问题。

现在我唯一能想到的NearbyUsersView就是做

ForEach((viewModel.nearByMultipeers + viewModel.nearbyBluetoothUsers + viewModel.nearbyGeoUsers).removeDuplicates()) { user in  /* ... */ }

但有些事情告诉我,我不会有预期的结果

您可以简单地在 ViewModel 中使用计算变量,假设 User 符合 Equatable,如下所示:

public var nearbyUsers: Set<User> {
   Set(nearbyMultipeers).union(Set(nearbyBluetoothUsers).union(Set(nearbyGeoUsers)))
}

这会将您的数组转换为集合,并通过多个并集创建一个集合。集合不能有重复项。如果你需要它作为一个数组,你可以这样做:

public var nearbyUsers: [User] {
   Array(Set(nearbyMultipeers).union(Set(nearbyBluetoothUsers).union(Set(nearbyGeoUsers))))
}

最后,如果 User 符合 Comparable,您可以 return 像这样的排序数组:

public var nearbyUsers: [User] {
   Array(Set(nearbyMultipeers).union(Set(nearbyBluetoothUsers).union(Set(nearbyGeoUsers)))).sorted()
}