I’m new to Swift and SwiftUI.
In my macOS SwiftUI project, I’m trying to verify that a URL is reachable so I can present one of two views conditionally. One view which loads the image URL, another one which displays an error image if the URL is not reachable.
Here’s my URL extension with completion:
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()
}
}
Elsewhere, I’m trying to use that in a model-view:
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
}
}
Though Xcode is showing this error:
Cannot convert value of type 'Bool' to closure result type 'Void'
What am I doing wrong?
2
Answers
I got this to work after reading some of the comments here and doing more research/experimentation. Here's what I changed:
In the URL extension, I left it pretty much the same as I find it more readable this way. I did push the
timeoutInterval
to a parameter:I modified my
BookViewModel
to make two of the properties to@Published
and used the URL extension there:Now my
BookThumbnailView
can properly display the conditional views:Whew, that was quite the learning experience. Thanks to everyone who commented with suggestions and provided hints on where to look!
The problem literally laid in the line
return result
, as Xcode tells you. When you create your functionfunc isReachable(completion: @escaping (Bool) -> Void)
, you are telling Xcode that you are going to input something in the type of(Bool) -> Void
, which should be something likefunc someFunction(input: Bool) -> Void
.But when you use a closure to input the completion handler, you’re inputting a function in type
Bool -> Bool
. Remove the linereturn result
, or change the type of the completion in yourfunc isReachable(completion:)
.Edit:
And indeed I don’t recommend returning a async result in a computed property, that would cause some other problem.
I would change it to something like: