0

Working on API, which uses Combine instead of closures. Fetching a resource with a closure using URLSession task and .resume gives no errors, while fetching with Combine gives:

Connection 57: unable to determine fallback status without a connection
struct Item: View {
    @ObservedObject var item: Item
    @State var thumbnail: UIImage?
    
    var body: some View {
        NavigationLink(destination: ItemView(item: item, thumbnail: thumbnail)) {
            ItemRowView(item: item, thumbnail: thumbnail)
        }
        .onAppear {
             let url = URL(string: "valid address")!
             let cancellable = URLSession.shared.dataTaskPublisher(for: url)
                 .receive(on: DispatchQueue.main)
                 .sink(receiveCompletion: { print ("Received completion: \($0).") },
                       receiveValue: { print ("Received data: \($0.data).")})
        }
    }
}

There's a similar question at Unable to determine interface type without an established connection Xcode. However, there shouldn't be any TLS errors in my case as the endpoint has a valid certificate and works okay without Combine.

Could you please interpret the error itself as it's not clear what fallback status is missing and why there's no connection?

hsrv
  • 1,372
  • 10
  • 22

1 Answers1

1

It appeared that cancellable must be assigned to a view's state variable like here:

struct Item: View {
    @ObservedObject var item: Item
    @State var thumbnail: UIImage?
    @State var cancellable: AnyCancellable?
    
    var body: some View {
        NavigationLink(destination: ItemView(item: item, thumbnail: thumbnail)) {
            ItemRowView(item: item, thumbnail: thumbnail)
        }
        .onAppear {
             let url = URL(string: "valid address")!
             cancellable = URLSession.shared.dataTaskPublisher(for: url)
                 .receive(on: DispatchQueue.main)
                 .sink(receiveCompletion: { print ("Received completion: \($0).") },
                       receiveValue: { print ("Received data: \($0.data).")})
        }
    }
}

otherwise a request is not executed.

hsrv
  • 1,372
  • 10
  • 22
  • 1
    While it's possible, you should avoid performing logic and calling tasks with side effects (network request) directly in the view. Move logic and network code to some view model or model and provide the view a value representing its content what is to be rendered. That way, you reduce convoluted code in the view, avoid unnecessary `@State` variables, prevent invalid recursions in the `body` resulting in runtime errors, get better performance (`@State` is slow) and you gain testability. – CouchDeveloper Jul 11 '21 at 18:24