Eventually my Swift frontend will make API calls to an external server, but in the development process, I want to test things locally on my computer. How do I reach my localhost server from Xcode? At this point I'm just trying to ensure contact--I don't need to actually retrieve anything yet.
So far I have the following code:
let urlString = "MY_IP_ADDRESS"
let url = URL(string: urlString)!
do {
try url.checkResourceIsReachable()
print("Success!")
} catch {
print("Failure!")
}
In the urlString
variable, I tried my actual IP Address. I also tried localhost:4001/hello
where 4001 was the port my node.js server was listening on and I defined /hello
. Am I using the wrong address, the wrong code, or is there no way to contact my local machine from Xcode?
CodePudding user response:
If you print(error)
in your catch
block (which is always a good practice -- print("Failure!")
doesn't tell you why the catch
block was invoked) you'll notice that there's an error telling you:
The file couldn’t be opened because the specified URL type isn’t supported.
Although it isn't explicitly said, I think the implication here is that checkResourceIsReachable
is for filesystem URLs -- not remote http
requests.
Instead, use a system of verifying the URL is reachable meant for remote resources.
import SwiftUI
import Combine
class CheckURL : ObservableObject {
enum URLResult : String {
case unknown, unreachable, reachable
}
@Published var urlReachable : URLResult = .unknown
private var cancellable : AnyCancellable?
func verifyURL(urlPath: String) {
guard let url = URL(string: urlPath) else {
assertionFailure("Invalid URL")
self.urlReachable = .unknown
return
}
var request = URLRequest(url: url)
request.httpMethod = "HEAD"
cancellable = URLSession.shared.dataTaskPublisher(for: url).tryMap({ (_ , response: URLResponse) -> URLResult in
if let response = response as? HTTPURLResponse, response.statusCode == 200 {
return .reachable
} else {
return .unreachable
}
})
.replaceError(with: .unreachable)
.receive(on: RunLoop.main).sink { result in
self.urlReachable = result
}
}
}
struct ContentView : View {
@StateObject private var urlChecker = CheckURL()
var body: some View {
Text("Reachable? \(urlChecker.urlReachable.rawValue)")
.onAppear {
urlChecker.verifyURL(urlPath: "http://localhost:4001/")
}
}
}
As mentioned in the comments, you'll want to make sure you have NSAllowsArbitraryLoads
set to YES
in your Info.plist