Force Mobile Data usage on some API calls and other to be through wifi or the available network

I am working on an application where there is a need to do a specific API only through Mobile Data and not wifi, allowing other API calls to be done using the available network type whether cellular data or wifi or ....

Is there a way to force use Mobile data usage even if WIFI is ON on this API call.

Replies

Is there a way to force use Mobile data usage even if WIFI is ON on this API call.

Yes. When using Network Framework, take a look at requiredInterfaceType on NWConnection. For higher level APIs like URLSession, this would be an Enhancement Request.



Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com

Dear

I do not need to have a client side and a server side and this do not help me reach my goal.

For using Alamofire or URLSession I would like to have an API run ONLY on Mobile Data even if WIFI is on for the purpose of Header Enrichment which means to give priority to the Mobile Data in this case.

Please Advice.

For using Alamofire or URLSession I would like to have an API run ONLY on Mobile Data

There is is currently no way to force a URLSession task to run over WWAN. If you’d like to see that change in the future, we encourage you to file an enhancement request.

Please post your bug number, just for the record.

Note Alamofire is based on URLSession, and so it has the same restrictions as URLSession.

for the purpose of Header Enrichment

Please explain what you mean by this.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

By the way, I have created an enhancement request on Jan 4, 2023 with feedback ID: FB11921232.

George Paloukis

Atos Unify

I have created an enhancement request on Jan 4, 2023 with feedback ID: FB11921232.

Thanks.

Nothing to report on that front, alas.

Oh, and just FYI, since this thread kicked off I’ve written Running an HTTP Request over WWAN, part of my Extra-ordinary Networking series. It doesn’t offer any great solutions, but at least it codifies the answer.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Try this out:

import Foundation
import Network

class CellularRequest {
    static func execute(url: URL,
                        httpMethod: String,
                        postBody: String? = nil,
                        completion: @escaping (_ error: NWError?, _ httpBody: String?, _ httpHeaders: String?)
                            -> Void) {
        guard let urlHost = url.host else { return }
        let host = NWEndpoint.Host(urlHost)

        let tlsOptions = NWProtocolTLS.Options()
        let tcpOptions = NWProtocolTCP.Options()

        let parameters = NWParameters(tls: tlsOptions, tcp: tcpOptions)
        parameters.prohibitExpensivePaths = false

        #if targetEnvironment(simulator)
            parameters.requiredInterfaceType = .loopback
        #else
            parameters.requiredInterfaceType = .cellular
        #endif

        let connection = NWConnection(host: host, port: .https, using: parameters)

        connection.stateUpdateHandler = { newState in
            switch newState {
            case .ready:
                // The connection is ready; you can now send an HTTP request
                var httpRequest = "\(httpMethod) \(url.path) HTTP/1.1\r\nHost: \(urlHost)\r\n"

                if let postBody = postBody {
                    httpRequest += "Content-Type: application/json\r\n"
                    httpRequest += "Content-Length: \(postBody.utf8.count)\r\n\r\n"
                    httpRequest += postBody
                } else {
                    httpRequest += "\r\n"
                }
                let requestData = httpRequest.data(using: .utf8)

                connection.send(content: requestData, completion: .contentProcessed { error in
                    if let error = error {
                        completion(error, nil, nil)
                    } else {
                        connection.receive(minimumIncompleteLength: 1, maximumLength: .max) { data, _, _, error in
                            if let data = data {
                                if let response = String(data: data, encoding: .utf8),
                                   response.contains("\r\n\r\n") {
                                    // The headers are complete, and we have the full response
                                    let headersAndBody = response.components(separatedBy: "\r\n\r\n")
                                    completion(nil, headersAndBody.first, headersAndBody.last)
                                }

                            } else if let error = error {
                                completion(error, nil, nil)
                            }
                        }
                    }
                })

            case let .failed(error), let .waiting(error):
                completion(error, nil, nil)
            default:
                break
            }
        }

        // Start the connection
        connection.start(queue: DispatchQueue.global())
    }
}

This is a classic example of what TN3151 calls a “simplistic HTTP client”. It’s fine for very restricted scenarios, where you know that the server speaks the most basic form of HTTP/1.1. However, it’ll fail if the server uses a more modern HTTP or even if the server uses more advanced HTTP/1.1 features, like the chunked transfer encoding.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

@eskimo If the user is connected over wifi and we are consuming the cellular data of the user using NWConnection, could it create an issue for the developer in terms of app store guidelines or the app getting rejected, etc? Do we need to inform the user that we will consume the mobile data irrespective of wifi connection status as part of any TnC?