【问题标题】:Is there a reason a UIViewControllerRepresentable should never be a class?UIViewControllerRepresentable 永远不应该是一个类有什么原因吗?
【发布时间】:2021-04-01 06:05:06
【问题描述】:

假设您并不真正需要 SwiftUI 功能。 IE。您的文件中没有import SwiftUI。相反,您只需要

import protocol SwiftUI.UIViewControllerRepresentable

一般来说,您将不得不涉及一个委托对象:an AnyObject,而且通常,因为 UIKit API 是旧的,一个NSObject

常见的模式是为此使用 Coordinator 类,并让 View 本身成为一个结构,但是否总是指向该间接?

这是一个在实践中没有给我带来任何麻烦的例子:

import Combine
import MultipeerConnectivity
import protocol SwiftUI.UIViewControllerRepresentable

extension MCBrowserViewController {
  final class View: NSObject {
    init(
      serviceType: String,
      session: MCSession,
      peerCountRange: ClosedRange<Int>? = nil
    ) {
      self.serviceType = serviceType
      self.session = session
      self.peerCountRange = peerCountRange
    }

    private let serviceType: String
    private unowned let session: MCSession
    private let peerCountRange: ClosedRange<Int>?

    private let didFinishSubject = CompletionSubject()
    private let wasCancelledSubject = CompletionSubject()
  }
}

// MARK: - internal
extension MCBrowserViewController.View {
  var didFinishPublisher: AnyPublisher<Void, Never> { didFinishSubject.eraseToAnyPublisher() }
  var wasCancelledPublisher: AnyPublisher<Void, Never> { wasCancelledSubject.eraseToAnyPublisher() }
}

// MARK: - private
private extension MCBrowserViewController {
  typealias CompletionSubject = PassthroughSubject<Void, Never>
}

// MARK: - UIViewControllerRepresentable
extension MCBrowserViewController.View: UIViewControllerRepresentable {
  func makeUIViewController(context: Context) -> MCBrowserViewController {
    let browser = MCBrowserViewController(
      serviceType: serviceType,
      session: session
    )

    browser.delegate = self

    if let peerCountRange = peerCountRange {
      browser.minimumNumberOfPeers = peerCountRange.lowerBound
      browser.maximumNumberOfPeers = peerCountRange.upperBound
    }

    return browser
  }

  func updateUIViewController(_: MCBrowserViewController, context _: Context) { }
}

// MARK: - MCBrowserViewControllerDelegate
extension MCBrowserViewController.View: MCBrowserViewControllerDelegate {
  func browserViewControllerDidFinish(_: MCBrowserViewController) {
    didFinishSubject.send()
  }

  func browserViewControllerWasCancelled(_: MCBrowserViewController) {
    wasCancelledSubject.send()
  }
}

【问题讨论】:

    标签: swiftui uiviewcontrollerrepresentable


    【解决方案1】:

    对于您的问题,我没有完整详细的答案,但您的解决方案存在一些问题。

    在 SwiftUI 中,如果我们更新一个View,它会调用init 重新创建View,然后调用updateUIViewController

    在您的情况下,每当您更新 View 时,不仅会重新创建您的视图,还会重新创建您的两个主题,因此在重新创建后附加到 Publisher 的任何内容都不会再收到事件。

    也许这就是我们更喜欢使用Coordinator的原因。

    【讨论】:

    • 好像你说makeCoordinator + makeUIViewController 运行一次,和State 和Binding 的存储分配一样,不管视图创建多少次。准确吗?
    • @Jessy 是的,它是准确的。
    • 那么,从makeCoordinator返回self不会解决你提到的问题吗?我也从未见过有人这样做。
    • @Jessy 你可以自己轻松测试一下。
    • 这个问题不适合我。这是你想的。 (如果你能理解它,请将它添加到答案中。)考虑作为协调员返回 self 与我的提议有何不同。
    猜你喜欢
    • 2010-09-12
    • 2023-03-28
    • 2021-05-21
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    • 2012-09-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多