我有一个类MapSearch,当我需要自动完成地址结果时,我会实例化它。它工作得很完美,但它从不去初始化,我也不知道为什么。
通过创建下面的文件轻松地进行测试。导航到测试页并查看控制台消息后使用后退按钮。您将看到视图模型按其应有的方式初始化和去初始化,但您将只看到MapSearch初始化。
HomeView.swift
import SwiftUI
struct HomeView: View {
var body: some View {
NavigationView {
NavigationLink(destination: TestView(viewModel: TestViewModel()) {
Text("TestView")
}
}
}
}TestView.swift
import SwiftUI
struct TestView: View {
@StateObject var viewModel: ViewModel
var body: some View {
Text("Hello World")
}
}TestViewModel.swift
import Foundation
extension TestView {
@MainActor
class ViewModel: ObservableObject {
@Published var mapSearch: MapSearch()
init() {
print("Test View Model Initialized")
}
deinit {
print("Test View Model Deinitialized")
}
}
}MapSearch.swift
import Combine
import CoreLocation
import Foundation
import MapKit
/// Uses MapKit and CoreLocation to auto-complete an address
class MapSearch: NSObject, ObservableObject {
@Published var countryName: String = "United States"
@Published var locationResults: [MKLocalSearchCompletion] = []
@Published var searchTerm = ""
private var cancellables: Set<AnyCancellable> = []
private var searchCompleter = MKLocalSearchCompleter()
private var currentPromise: ((Result<[MKLocalSearchCompletion], Error>) -> Void)?
override init() {
super.init()
searchCompleter.delegate = self
searchCompleter.resultTypes = MKLocalSearchCompleter.ResultType([.address])
$searchTerm
.debounce(for: .seconds(0.2), scheduler: RunLoop.main)
.removeDuplicates()
.flatMap({ (currentSearchTerm) in
self.searchTermToResults(searchTerm: currentSearchTerm, countryName: self.countryName)
})
.sink(receiveCompletion: { (_) in
}, receiveValue: { (results) in
// Show country specific results
self.locationResults = results.filter { $0.subtitle.contains(self.countryName) }
})
.store(in: &cancellables)
print("MapSearch Initialized")
}
deinit {
print("MapSearch Deinitialized")
}
func searchTermToResults(searchTerm: String, countryName: String) -> Future<[MKLocalSearchCompletion], Error> {
Future { promise in
self.searchCompleter.queryFragment = searchTerm
self.currentPromise = promise
}
}
}
extension MapSearch: MKLocalSearchCompleterDelegate {
func completerDidUpdateResults(_ completer: MKLocalSearchCompleter) {
currentPromise?(.success(completer.results))
}
func completer(_ completer: MKLocalSearchCompleter, didFailWithError error: Error) {
// deal with the error here, it will finish the Combine publisher stream
currentPromise?(.failure(error))
}
}发布于 2022-05-30 16:28:48
需要对MapSearch类进行调整,以便在组合调用中添加弱自。现在它正确地发挥了作用。
以下是供参考的代码:
import Combine
import CoreLocation
import Foundation
import MapKit
/// Uses MapKit and CoreLocation to auto-complete an address
class MapSearch: NSObject, ObservableObject {
@Published var countryName: String = "United States"
@Published var locationResults: [MKLocalSearchCompletion] = []
@Published var searchTerm = ""
private var cancellables: Set<AnyCancellable> = []
private var searchCompleter = MKLocalSearchCompleter()
private var currentPromise: ((Result<[MKLocalSearchCompletion], Error>) -> Void)?
override init() {
super.init()
searchCompleter.delegate = self
searchCompleter.resultTypes = MKLocalSearchCompleter.ResultType([.address])
$searchTerm
.debounce(for: .seconds(0.2), scheduler: RunLoop.main)
.removeDuplicates()
.flatMap({ [weak self] (currentSearchTerm) in
(self?.searchTermToResults(searchTerm: currentSearchTerm, countryName: self?.countryName ?? "")) ??
Future { [weak self] promise in
self?.searchCompleter.queryFragment = self?.searchTerm ?? ""
self?.currentPromise = promise
}
})
.sink(receiveCompletion: { (_) in
}, receiveValue: { [weak self] (results) in
// Show country specific results
self?.locationResults = results.filter { $0.subtitle.contains(self?.countryName ?? "") }
})
.store(in: &cancellables)
print("MapSearch Initialized")
}
deinit {
print("MapSearch Deinitialized")
}
func searchTermToResults(searchTerm: String, countryName: String) -> Future<[MKLocalSearchCompletion], Error> {
Future { [weak self] promise in
self?.searchCompleter.queryFragment = searchTerm
self?.currentPromise = promise
}
}
}
extension MapSearch: MKLocalSearchCompleterDelegate {
func completerDidUpdateResults(_ completer: MKLocalSearchCompleter) {
currentPromise?(.success(completer.results))
}
func completer(_ completer: MKLocalSearchCompleter, didFailWithError error: Error) {
// deal with the error here, it will finish the Combine publisher stream
currentPromise?(.failure(error))
}
}https://stackoverflow.com/questions/72436930
复制相似问题