最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

swiftUI's 'onChange' anomaly detection - Stack Overflow

programmeradmin0浏览0评论

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

发布评论

评论列表(0)

  1. 暂无评论