In my project, I set up a viewModel, which has a Model:
import Foundation
import MultipeerConnectivity
public struct MCReceiveItem: Identifiable, Equatable {
public let id: String = UUID().uuidString
public let resourceName: String
public let fromPeer: MCPeerID
public var localURL: URL?
public var progress: Progress
public var isFinished: Bool = false
public init(resourceName: String, fromPeer: MCPeerID, progress: Progress) {
self.resourceName = resourceName
self.fromPeer = fromPeer
self.progress = progress
}
public static func == (lhs: MCReceiveItem, rhs: MCReceiveItem) -> Bool {
return lhs.id == rhs.id &&
lhs.resourceName == rhs.resourceName &&
lhs.fromPeer == rhs.fromPeer &&
lhs.localURL == rhs.localURL &&
lhs.progress == rhs.progress &&
lhs.isFinished == rhs.isFinished
}
}
I have changed 'isFinished' for 'receiveItem' here
@Observable
public class MCService: NSObject {
@MainActor
public var receiveItem: MCReceiveItem?
...
public func session(_ session: MCSession, didStartReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, with progress: Progress) {
Task{ @MainActor in
self.receiveItem = .init(resourceName: resourceName, fromPeer: peerID, progress: progress)
}
}
public func session(_ session: MCSession, didFinishReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, at localURL: URL?, withError error: Error?) {
Thread.sleep(forTimeInterval: 1)
Task { @MainActor in
if (self.receiveItem != nil) {
receiveItem?.localURL = localURL
receiveItem?.isFinished = true
}
}
if let error = error {
log.error("Receiving resource fail: \(error.localizedDescription)")
}
}
}
However, when I use 'onChange' in the swiftUI view to observe the change of 'receiveItem.isFinished', I find that the change process of 'isFinished' is as follows:
false -> True -> false -> true
Why does it become true and then false? I checked the code for my entire project and didn't see where I set it to false, which confused me
struct ReceivingView: View {
let receiveItem: MCReceiveItem
...
init(receiveItem: MCReceiveItem, completion: @escaping () -> Void = {}) {
self.receiveItem = receiveItem
selfpletion = completion
}
var body: some View {
...
.onChange(of: receiveItem.isFinished) { oldValue, newValue in
if newValue {
Task {
// Save
if let localURL = receiveItem.localURL {
await saveReceiveItem(resourceURL: localURL)
}
// Notify MCservice that the resource has been received, clear receiveItem
NotificationCenter.default.post(name: .is_receive_resource_finished, object: true)
}
self.dismiss?()
completion()
}
}
}
}
but when I change the MCReceiveItem
from struct into class, that works? I want to know why, Does this have anything to do with changing the underlying logic of struct and class attributes?
fixed