假设您并不真正需要 SwiftUI 功能。即你import SwiftUI
的文件中没有。相反,您只需要
import protocol SwiftUI.UIViewControllerRepresentable
通常,您将不得不涉及一个委托对象:充其量是一个AnyObject
NSObject
,而且通常,因为 UIKit API 是旧的,一个.
常见的模式是为此使用一个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()
}
}