我正在尝试将MultiPeer Connectivity框架与swift ui一起使用,并且在使用ForEach时遇到问题。我有一个单例用来跟踪数组中的连接用户:
class MPCManager: NSObject {
static let instance = MPCManager()
var devices: [Device] = []
...
我的设备类:
class Device: NSObject {
let peerID: MCPeerID
var session: MCSession?
var name: String
var state = MCSessionState.notConnected
var lastMessageReceived: Message?
...
}
当MultiPeer连接框架找到新的对等方时,MPCManager会将新设备附加到阵列。我已经在调试器中确认了这一点。当我尝试在列表中显示设备时出现问题。这是我正在使用的代码:
struct ContentView : View {
var devices: [Device] = MPCManager.instance.devices
var body: some View {
List {
ForEach(self.devices.identified(by: \.name)) { device in
Text(device.name)
}
}
}
}
应用启动时,显示列表,但列表为空。当我在ForEach执行中的视图代码中放置断点时,永远不会停止。当我将数组更改为值的硬编码列表时,它显示得很好。我也尝试像这样直接在我的视图中从静态实例引用数组:
ForEach(self.devices.identified(by: \.name)) { device in
Text(device.name)
}
什么都没有。我是新手,所以可能有些容易遗失的东西,但我只是看不到。有什么想法吗?
答案 0 :(得分:1)
据我所知,这里有几个问题。
首先,我建议您尝试使用MPCManager
:
import SwiftUI
import Combine
class MPCManager: NSObject, BindableObject {
var didChange = PassthroughSubject<Void, Never>()
var devices: [Device] = [] {
didSet {
self.didChange.send(())
}
}
}
然后,在您的ContentView
中,执行以下操作:
struct ContentView : View {
@ObjectBinding var manager: MPCManager = MPCManager()
var body: some View {
List {
ForEach(self.manager.devices.identified(by: \.name)) { device in
Text(device.name)
}
}
}
}
回答您的问题的主要困难是我无法运行您的代码。如果您可以将代码提炼成可能知道答案的人可以将其复制并粘贴到Xcode中的内容,那么您的问题对其他人将更有用(并且更容易回答)。
答案 1 :(得分:0)
这是您可以运行的示例。当您点击一行时,假设要切换其选择。我已经用ObservableObject等添加了内容,直到脸色发青并且无法更新它。我觉得有一个简单,明显的解决方案,但我没有看到。
class Layer: NSObject, Identifiable, ObservableObject {
let didChange = PassthroughSubject<Void, Never>()
var id = UUID()
var name: String
var apiClass: String
var selected = false {
willSet {
didChange.send()
}
}
static func == (lhs: Layer, rhs: Layer) -> Bool {
lhs.id == rhs.id
}
init(name: String, apiClass: String, selected: Bool = false) {
self.name = name
self.apiClass = apiClass
self.selected = selected
}
}
class Manager: NSObject, ObservableObject {
let didChange = PassthroughSubject<Void, Never>()
@Published var layers = [
Layer(name: "All Assets", apiClass: "asset"),
Layer(name: "Stopped", apiClass: "asset", selected: true),
Layer(name: "Orders", apiClass: "orders")
]
func toggle(layer: Layer) {
layer.selected = !layer.selected
didChange.send()
}
}
struct ContentView: View {
@ObservedObject var manager = Manager()
var body: some View {
List {
ForEach(manager.layers) { layer in
HStack {
Image(systemName:
layer.selected ? "checkmark.circle.fill" : "circle"
)
Text(layer.name)
}
.onTapGesture {
self.manager.toggle(layer: layer)
}
.padding()
}
}
}
}
我觉得您实际上不需要真正拥有PassthroughSubject和send(),但是即使那样也不起作用。