强制通过 wifi 或可用网络对某些 API 调用和其他调用使用移动数据

问题描述 投票:0回答:2

我正在开发一个应用程序,需要仅通过移动数据而不是 wifi 来执行特定的 API,从而允许使用可用的网络类型(无论是蜂窝数据还是 wifi 或 ....)来完成其他 API 调用。

有没有办法强制使用移动数据使用,即使在此 API 调用上 WIFI 已打开。

向苹果开发者开票后,这是他们的回复:

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


但我仍然陷入困境,不知道如何继续。

swift networking alamofire mobile-data network-framework
2个回答
1
投票
您可以通过在 iOS 13(以及同年 Apple 操作系统)及更高版本上设置

allowsConstrainedNetworkAccess

 上的 
allowsExpensiveNetworkAccess
URLRequest
 来获得一些控制权。

allowsConstrainedNetworkAccess

在 iOS 13 及更高版本中,用户可以将设备设置为使用低数据模式作为“设置”应用中的蜂窝数据选项之一。用户可以打开低数据模式来减少应用程序的网络数据使用量。当用户打开低数据模式时,此属性控制请求的行为。如果没有可用的非约束网络接口并且请求的 allowedConstrainedNetworkAccess 属性为 false,则从请求创建的任何连接都会失败。在这种情况下,连接失败时提供的错误有一个 networkUnavailableReason 属性,其值为 NSURLErrorNetworkUnavailableReason.constrained。

在请求上设置此属性会覆盖 URLSessionConfiguration 的 allowedConstrainedNetworkAccess 属性。例如,如果会话配置的 allowedConstrainedNetworkAccess 值为 false,并且您根据 allowedConstrainedNetworkAccess 为 true 的请求创建任务,则该任务会将该值视为 true。

限制您的应用程序对用户启动的任务使用受限网络访问,并推迟酌情任务,直到非受限界面可用。

allowsExpensiveNetworkAccess

系统根据网络接口的性质和其他因素来确定什么构成“昂贵”。 iOS 13 认为大多数蜂窝网络和个人热点都很昂贵。如果没有可用的廉价网络接口并且请求的 allowedExpectiveNetworkAccess 属性为 false,则从请求创建的任何任务都会失败。在这种情况下,任务失败时提供的错误有一个 networkUnavailableReason 属性,其值为 NSURLErrorNetworkUnavailableReason.expective。

在请求上设置此属性会覆盖 URLSessionConfiguration 的 allowedExpectiveNetworkAccess 属性。例如,如果会话配置的 allowedExpectiveNetworkAccess 值为 false,并且您根据 allowedExpectiveNetworkAccess 为 true 的请求创建任务,则该任务会将该值视为 true。

限制您的应用程序对用户启动的任务使用昂贵的网络访问,并推迟可自由支配的任务,直到有便宜的界面可用。


0
投票
试试这个:

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()) } }
    
© www.soinside.com 2019 - 2024. All rights reserved.