Когда я использую издателя, который на самом деле делает вызов API, все работает нормально. Однако, если я попытаюсь смоделировать его, я получу сбой с надписью EXC_BAD_ACCESS (код = 2, адрес = 0x16b827ed0).
Вот модель представления:
`
class ViewModel: ObservableObject {
@Published var dataString: String = ""
let dataService: DataServiceProtocol
init(dataService: DataServiceProtocol) {
self.dataService = dataService
self.nasaPublisher
.assign(to: &$dataString). // The app crashes here when i use the mock data service
}
private lazy var nasaPublisher: AnyPublisher<String, Never> = {
$dataString
.flatMap { [unowned self] string in
self.dataService.getNasaData()
}
.eraseToAnyPublisher()
}()
}
`
А вот и служба данных:
`
enum Endpoint: String {
case search = "/search"
}
protocol DataServiceProtocol {
func getNasaData() -> AnyPublisher<String, Never>
}
class DataService: DataServiceProtocol {
let host = "https://images-api.nasa.gov"
func getNasaData() -> AnyPublisher<String, Never> {
var components = URLComponents()
components.scheme = "https"
components.host = "images-api.nasa.gov"
components.path = "/search"
components.queryItems = [
URLQueryItem(name: "q", value: "apollo")
]
guard let url = components.url else {
return Just("false").eraseToAnyPublisher()
}
return URLSession.shared.dataTaskPublisher(for: url)
.map { data, response in
do {
let decoder = JSONDecoder()
let str = String(decoding: data, as: UTF8.self)
print(data.prettyPrintedJSONString)
return str
}
// catch {
// return "false"
// }
}
.replaceError(with: "false")
.eraseToAnyPublisher()
}
}
class MockDataService: DataServiceProtocol {
let mock = Just("Test string")
.setFailureType(to: Never.self)
.eraseToAnyPublisher()
func getNasaData() -> AnyPublisher<String, Never> {
return mock
}
}
`
Любые советы о том, что я делаю неправильно, будут высоко оценены. Спасибо!
Я запустил и протестировал код с реальным вызовом API, и он отлично работает, но вылетает, если я использую фиктивный вызов API.





В init у вас есть:
self.nasaPublisher
.assign(to: &$dataString)
Итак, это издатель, который присваивает свой вывод опубликованной переменной dataString
Тогда nasaPublisher определяется как:
private lazy var nasaPublisher: AnyPublisher<String, Never> = {
$dataString
.flatMap { [unowned self] string in
self.dataService.getNasaData()
}
.eraseToAnyPublisher()
}()
Это издатель, который реагирует всякий раз, когда значение в dataString изменяется.
Когда dataString изменяется, это заставляет nasaPublisher выдавать значение. Это значение присваивается dataString, что заставляет nasaPublisher выдавать значение. Это значение присваивается dataString, что заставляет nasaPublisher выдавать значение. Это значение присвоено dataString ...
Это бесконечный цикл.
Когда вы используете службу реальных данных, она создает уникального издателя каждый раз, когда цикл вызывает getNasaData.
Однако при использовании вашего фиктивного сервиса он создает одного издателя и getNasaData каждый раз возвращает один и тот же.
Этот один издатель собирается выполнить один раз, а затем выпустить все имеющиеся у него активы. Я подозреваю, что во второй раз через бесконечный цикл один из этих активов был выпущен, что привело к сбою.