Я пытаюсь написать валидатор URL-адресов в Swift w / Combine, и на него подписывается представление SwiftUI. Кажется, он отлично работает в симуляторе, но вылетает на моем телефоне разработчика (работает 13.1).
Сценарий ... Пользователь вводит UITextField, который подключен к переменной urlString в модели представления. Когда это изменяется, я очищаю строку, создаю URL-адрес, а затем выполняю тест HEAD с помощью URLSession. Все это работает в симуляторе, но при нажатии текстового поля на устройстве происходит сбой приложения, и я не получаю никаких хороших трассировок стека. Любые идеи?
static func testURLPublisher(string: String) -> AnyPublisher<URL?, Never> {
let validatedURL = try? validateURL(string: string)
guard let urlToCheck = validatedURL else {
return Just(nil).eraseToAnyPublisher()
}
var request = URLRequest(url: urlToCheck)
request.httpMethod = "HEAD"
let publisher = URLSession.shared.dataTaskPublisher(for: request)
.handleEvents(receiveSubscription: { _ in
networkActivityPublisher.send(true)
}, receiveCompletion: { _ in
networkActivityPublisher.send(false)
}, receiveCancel: {
networkActivityPublisher.send(false)
})
.tryMap { data, response -> URL? in
// URL Responded - Check Status Code
guard let urlResponse = response as? HTTPURLResponse, ((urlResponse.statusCode >= 200 && urlResponse.statusCode < 400) || urlResponse.statusCode == 405) else {
throw URLValidatorError.serverError("Could not find the a servr at: \(urlToCheck)")
}
return urlResponse.url?.absoluteURL
}
.catch { err in
return Just(nil)
}
.eraseToAnyPublisher()
return publisher
}
Представление, которое его использует, выглядит так ...
class NewSiteViewModel: ObservableObject {
@Published var validatedURL: URL?
//@Published var secretKey: String?
@Published var urlString: String = ""
@Published var isValidURL: Bool = false
private var cancellable = Set<AnyCancellable>()
init() {
$urlString
.dropFirst(1)
.throttle(for: 0.5, scheduler: DispatchQueue(label: "Validator"), latest: true)
.removeDuplicates()
.compactMap { string -> AnyPublisher<URL?, Never> in
return URL.testURLPublisher(string: string)
}
.switchToLatest()
.receive(on: RunLoop.main)
.sink { recievedURL in
guard let url = recievedURL else {
self.validatedURL = nil
self.isValidURL = false
return
}
self.validatedURL = url
self.isValidURL = true
}
.store(in: &cancellable)
}
}