我是Swift和SwiftUI的新手。
在我的macOS SwiftUI项目中,我试图验证URL是否可访问,因此我可以有条件地显示两个视图之一。一个视图加载图像URL,另一个视图显示错误图像(如果URL无法访问)。
这是我的带有扩展名的URL扩展名:
import Foundation
extension URL {
func isReachable(completion: @escaping (Bool) -> Void) {
var request = URLRequest(url: self)
request.httpMethod = "HEAD"
request.timeoutInterval = 1.0
URLSession.shared.dataTask(with: request) { data, response, error in
if error != nil {
DispatchQueue.main.async {
completion(false)
}
return
}
if let httpResp: HTTPURLResponse = response as? HTTPURLResponse {
DispatchQueue.main.async {
completion(httpResp.statusCode == 200)
}
return
} else {
DispatchQueue.main.async {
completion(false)
}
return
}
}.resume()
}
}
在其他地方,我试图在模型视图中使用它:
var imageURL: URL? {
if let url = self.book.image_url {
return URL(string: url)
} else {
return nil
}
}
var imageURLIsReachable: Bool {
if let url = self.imageURL {
url.isReachable { result in
return result // Error: Cannot convert value of type 'Bool' to closure result type 'Void'
}
} else {
return false
}
}
尽管Xcode显示此错误:
Cannot convert value of type 'Bool' to closure result type 'Void'
我在做什么错了?
答案 0 :(得分:0)
正如Xcode告诉您的那样,问题实际上位于return result
行中。创建函数func isReachable(completion: @escaping (Bool) -> Void)
时,您在告诉Xcode您将输入类型为(Bool) -> Void
的内容,该内容应类似于func someFunction(input: Bool) -> Void
。
但是,当您使用闭包输入完成处理程序时,您正在输入的类型为Bool -> Bool
。删除行return result
,或在您的func isReachable(completion:)
中更改完成类型。
编辑:
实际上,我不建议在计算属性中返回异步结果,否则会导致其他问题。
我将其更改为:
func isReachable(completion: @esacping (Bool) -> Void) {
...
}
func showResultView() {
guard let url = imageURL else {
// handling if the imageURL is nil
return
}
url.isReachable { result in
// do something with the result
if result {
// show viewController A
} else {
// show viewController B
}
}
}
// call showResultView anywhere you want, lets say you want to show it whenever the viewController appear
override func viewDidAppear() {
...
showResultView()
}
答案 1 :(得分:0)
在阅读了这里的一些评论并进行了更多的研究/实验之后,我开始进行这项工作。这是我更改的内容:
在URL扩展名中,我将其保留为几乎与以这种方式更易读的相同。我确实将csv
推到了一个参数:
timeoutInterval
我修改了// Extensions/URL.swift
import Foundation
extension URL {
func isReachable(timeoutInterval: Double, completion: @escaping (Bool) -> Void) {
var request = URLRequest(url: self)
request.httpMethod = "HEAD"
request.timeoutInterval = timeoutInterval
URLSession.shared.dataTask(with: request) { data, response, error in
if error != nil {
DispatchQueue.main.async {
completion(false)
}
return
}
if let httpResp: HTTPURLResponse = response as? HTTPURLResponse {
DispatchQueue.main.async {
completion(httpResp.statusCode == 200)
}
return
} else {
DispatchQueue.main.async {
completion(false)
}
return
}
}.resume()
}
}
,将其中两个属性设为BookViewModel
,并在那里使用了URL扩展名:
@Published
现在,我的// View Models/BookViewModel.swift
import Foundation
class BookViewModel: ObservableObject {
@Published var book: Book
@Published var imageURLIsReachable: Bool
@Published var imageURL: URL?
init(book: Book) {
self.book = book
self.imageURL = nil
self.imageURLIsReachable = false
if let url = book.image_url {
self.imageURL = URL(string: url)
self.imageURL!.isReachable(timeoutInterval: 1.0) { result in
self.imageURLIsReachable = result
}
}
}
// Rest of properties...
}
可以正确显示条件视图了:
BookThumbnailView
哇,那真是一次学习的经历。感谢所有发表评论并提供建议的人!