Home > Back-end >  Pinging localhost in Swift w/ Xcode
Pinging localhost in Swift w/ Xcode

Time:10-31

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

  • Related