我正在使用泛型和可编码的URLSession.
当我收到来自 API 的响应时,我检查状态是否在 200 - 299 范围内并像这样解码数据
guard let data = data, let value = try? JSONDecoder().decode(T.self, from: data) else {
return completion(.error("Could not decode JSON response"))
}
completion(.success(value))
Run Code Online (Sandbox Code Playgroud)
然后将其传递给完成处理程序,一切正常。
我有一个新的端点,我也必须 POST,但是,这个端点返回一个没有内容正文的 204。
因此,我无法解码响应,只是因为我无法传入类型?
我的完成处理程序期望
enum Either<T> {
case success(T)
case error(String?)
}
Run Code Online (Sandbox Code Playgroud)
并像这样打开我的响应状态代码
case 204:
let value = String(stringLiteral: "no content")
return completion(.success(value))
Run Code Online (Sandbox Code Playgroud)
产生错误
“Either< > ”中的成员“success”产生“Either”类型的结果,但上下文需要“Either< >”
我的 APIClient 是
protocol APIClientProtocol: class {
var task: URLSessionDataTask { get set }
var session: SessionProtocol …Run Code Online (Sandbox Code Playgroud) 我该如何嘲笑URLSession.DataTaskPublisher?我有一堂课Proxy需要注入URLSessionProtocol
protocol URLSessionProtocol {
func loadData(from url: URL) -> URLSession.DataTaskPublisher
}
Run Code Online (Sandbox Code Playgroud)
class Proxy {
private let urlSession: URLSessionProtocol
init(urlSession: URLSessionProtocol) {
self.urlSession = urlSession
}
func get(url: URL) -> AnyPublisher<Data, ProxyError> {
// Using urlSession.loadData(from: url)
}
}
Run Code Online (Sandbox Code Playgroud)
URLSession该代码最初与完成处理程序的传统版本一起使用。它非常完美,因为我可以轻松地模拟URLSession测试,就像 Sundell 的解决方案:Mocking in Swift。
是否可以使用组合框架做同样的事情?
我已经URLSessionWebSocketDelegate设置并实施了
urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didCloseWith closeCode: URLSessionWebSocketTask.CloseCode, reason: Data?)
Run Code Online (Sandbox Code Playgroud)
然而,如果服务器正确断开连接,它似乎只会影响委托。如果连接断开或服务器不提供断开连接代码,则委托函数永远不会运行。我还尝试检查URLSessionWebSocketTask属性closeCode以及closeReason断开连接之前和之后,除非服务器发送正确的断开连接代码,否则它们不会更改。
虽然我可以控制服务器并且可以确定故意断开连接有代码,但如果网络连接中断会发生什么?或者如果服务器宕机了?我认为委托函数仍然应该被调用。
有趣的是,我的监听函数出现错误,错误内容如下:
Error Domain=NSPOSIXErrorDomain Code=57 "Socket is not connected" UserInfo={NSErrorFailingURLStringKey=[urlomitted], NSErrorFailingURLKey=[urlomitted]
Run Code Online (Sandbox Code Playgroud)
因此,虽然如果我看到错误 57,我可以手动断开套接字,但我不知道这是否适用于所有不同的断开连接变体。
我认为我要么做错了什么,要么这是一个错误,但我找不到其他人有同样的问题,所以我想我应该在提交雷达之前询问。
我一直在研究拦截器,用于在我的应用程序中向网络请求添加身份验证标头。
final class AuthInterceptor: URLProtocol {
private var token: String = "my.access.token"
private var dataTask: URLSessionTask?
private struct UnexpectedValuesRepresentationError: Error { }
override class func canInit(with request: URLRequest) -> Bool {
guard URLProtocol.property(forKey: "is_handled", in: request) as? Bool == nil else { return false }
return true
//return false // URL Loading System will handle the request using the system’s default behavior
}
override class func canonicalRequest(for request: URLRequest) -> URLRequest {
return request
}
override func startLoading() {
guard …Run Code Online (Sandbox Code Playgroud) 我的大部分功能都在工作,并且返回的正是我想要的。photos然而,当涉及到将数组放入response并将它们分配给适当的位置employees以便能够渲染它们时,我有点脑残。这是发生的事情:
Response、Company、Employee和ProfileImages。Response是 API 返回的主要对象,然后解码为Company一个数组[Employee],每个数组有 3x ProfileImages(小、中、大尺寸)companyPublisher可以获取company详细信息以及一系列employeesphotosPublisher获取employees数组并对它们进行排序以便能够检索其profileImages.large个人资料图像Publishers.Zip(companyPublisher, photosPublisher)设置发布者.sink()在获取所有请求的内容后响应完成。有人可以建议我需要采取哪些适当的步骤才能将正确的员工图像分配给实际员工?我正在考虑在可编码结构中设置一个可选UIImage类型,但仍然不确定如何将适当的 Future 对象分配给该员工。propertyEmployee
任何帮助将不胜感激。提前致谢!
Response.JSON:
{
"success": true,
"company": {
"id": 64,
"name": "XYZ (Birmingham, AL)",
"enabled": true
},
"employees": [{
"id": 35,
"name": "Chad Hughes",
"email": …Run Code Online (Sandbox Code Playgroud) 测试在 iPhone 13 Pro 15.3.1 上进行,使用 Xcode 13.2.1。我已将问题范围缩小为以下两个测试。下面的测试代码只是发送一个简单的https请求。
我已允许 Wifi 和手机上的测试应用程序进行网络访问。我是一名付费开发人员。
下面两个测试在模拟器上都通过了,在iPhone上却失败了,说明我的iPhone这边有问题,找到一个帖子说国产品牌iPhone可能有这个问题,还在挖……orz
NSURLErrorNWPathKey=unsatisfied...

func testDownloadWebData() {
// Create an expectation for a background download task.
let expectation = XCTestExpectation(description: "Download apple.com home page")
// Create a URL for a web page to be downloaded.
let url = URL(string: "https://apple.com")!
// Create a background task to download the web page.
let dataTask = URLSession.shared.dataTask(with: url) { (data, _, _) in …Run Code Online (Sandbox Code Playgroud) 我正在开发一个简单的 Swift 测试应用程序,它只调用我的服务器上的 Perl 脚本。现在我只想发送用户名和 ID,然后将它们返回到 JSON 响应中。没什么,我还在学习阶段。
但无论我尝试哪种方式,我都无法成功发送 URLRequest 中的两个参数。
在下面的示例中,您会看到我尝试在主 url 中发送它们,我尝试将它们添加为 forHTTPHeaderFields,但我在 URLSessionDataDelegate 中返回的响应始终是:
数据为 {"userid":"","username":""} JSON 可选({ userid = ""; username = "";
let file = File(link: "http://example.com/cgi-bin/swift.pl?username=John&userid=01", data: "hello")
uploadService.start(file: file)
Run Code Online (Sandbox Code Playgroud)
在我的 URLSession 实例中我尝试过:
// From one of my view controllers I create a File struct
// from a YouTube lesson. Eventually I want to send a file.
// So for now am using just *Hello*:
let uploadTask = UploadTask(file: file)
let url = URL(string: …Run Code Online (Sandbox Code Playgroud) 为什么下面的代码会导致and都URLSession返回?nildataerror
let task = URLSession.shared.dataTask(with: storeRequest as URLRequest) { data, _, error -> Void in
// there is an error
if let networkError = error {
print("There was a network error")
return
}
// there is no data
guard let safeData = data else {
print("No network error, but no data either")
return
}
...
Run Code Online (Sandbox Code Playgroud)
运行此代码时,一名用户拨打了电话No network error, but no data either。
根据苹果公司的文档URLSession.dataTask:
如果请求成功完成,则完成处理程序块的 data 参数包含资源数据,并且 error 参数为零。如果请求失败,则 data 参数为 nil,error …
我正在尝试处理通过读取其响应状态代码而到达的响应DataTaskPublisher。
当状态代码大于 299 时,我想返回一个ServiceError失败类型。在我见过的每个示例中,我都使用过.mapError.......catch在这种特定情况下,从 a .flatMap,我真的不知道如何处理发布者响应以返回错误而不是TResponse......
return URLSession.DataTaskPublisher(request: urlRequest, session: .shared)
.mapError{error in return ServiceError.request}
.flatMap{ data, response -> AnyPublisher<TResponse, ServiceError> in
if let httpResponse = response as? HTTPURLResponse,
(200...299).contains(httpResponse.statusCode){
return Just(data)
.decode(type: TResponse.self, decoder: JSONDecoder())
.mapError{error in return ServiceError.decode}
.eraseToAnyPublisher()
}else{
//???? HOW TO HANDLE THE ERROR?
}
}
.receive(on: RunLoop.main)
.eraseToAnyPublisher()
Run Code Online (Sandbox Code Playgroud) 我使用 URLSession 来“POST”请求,但有时当在路上请求时,我会收到带有差异错误的错误代码,更常见的是:“超时”这是我在控制台中看到的错误消息示例“Error Domain=NSURLErrorDomain Code=” -1009“互联网连接似乎已离线。”
但我无法在代码中捕获此错误,我做错了什么?,我还收到另一个代码错误,但它不会改变情况。
错误信息:
2020-11-25 09:52:07.456207+0200 TestApp[40176:2305710] Connection 4: received failure notification
2020-11-25 09:52:07.456344+0200 TestApp[40176:2305710] Connection 4: failed to connect 1:50, reason -1
2020-11-25 09:52:07.456771+0200 TestApp[40176:2305710] Connection 4: encountered error(1:50)
2020-11-25 09:52:07.459696+0200 TestApp[40176:2305710] Task <888AA895-677A-403B-A436-599FF55DB3BB>.<1> HTTP load failed, 0/0 bytes (error code: -1009 [1:50])
2020-11-25 09:52:07.460557+0200 Venom[40176:2305710] Task <888AA895-677A-403B-A436-599FF55DB3BB>.<1> finished with error [-1009]
Error Domain=NSURLErrorDomain Code=-1009 "The Internet connection appears to be offline." UserInfo={_kCFStreamErrorCodeKey=50, NSUnderlyingError=0x600000116880
{Error Domain=kCFErrorDomainCFNetwork Code=-1009 "(null)" UserInfo={_kCFStreamErrorCodeKey=50, _kCFStreamErrorDomainKey=1}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask
<888AA895-677A-403B-A436-599FF55DB3BB>.<1>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <888AA895-677A-403B-A436-599FF55DB3BB>.<1>" …Run Code Online (Sandbox Code Playgroud) swift ×10
urlsession ×10
ios ×7
combine ×3
nsurlsession ×2
codable ×1
jsondecoder ×1
mocking ×1
request ×1
timeout ×1
websocket ×1
xctest ×1