Swift 从 URLSession.shared.dataTaskPublisher 合并 Return Int
Swift Combine Return Int From URLSession.shared.dataTaskPublisher
我有以下代码进行 API 调用,接收数据并将其分配给 Core Data 托管对象。这很好用,并更新了我的数据。
func importUsers(url: URL) {
URLSession.shared.dataTaskPublisher(for: url)
.map(\.data)
.sink(receiveCompletion: { completion in
if case .failure(let error) = completion {
print("DataImporter.runImport failed with error: \(error)")
}
}, receiveValue: { [weak self] data in
guard let self = self
else { return }
self.importContext.perform {
do {
// 2. Decode the response. This decodes directly to the Core Data Store
let users = try self.decoder.decode([GitUser].self, from: data)
try? self.importContext.save()
} catch {
print("DataImporter.runImport failed to decode json with error: \(error)")
}
}
})
.store(in: &self.cancellables) // store the returned cancellable in a property on `DataImporter`
}
但是,我需要 return 作为此调用的结果 return 编辑和解码的对象数量。如果失败,我 return 0。本质上,我想要这个:
func importUsers(url: URL) -> Int {
URLSession.shared.dataTaskPublisher(for: url)
.map(\.data)
.sink(receiveCompletion: { completion in
if case .failure(let error) = completion {
print("DataImporter.runImport failed with error: \(error)")
}
}, receiveValue: { [weak self] data in
guard let self = self
else { return 0 }
var users: [GitUser] = []
self.importContext.perform {
do {
// 2. Decode the response. This decodes directly to the Core Data Store
users = try self.decoder.decode([GitUser].self, from: data)
try? self.importContext.save()
} catch {
print("DataImporter.runImport failed to decode json with error: \(error)")
}
}
return users.count
}).store(in: &self.cancellables) // error: Cannot convert return expression of type '()' to return type 'Int'
}
我如何 return 作为网络调用的结果收到的对象计数?
我的建议是解码数据并在管道和 return 发布者中创建核心数据记录。在另一个函数中订阅发布者和 sink
项目数 and/or 处理错误。
我没有你的自定义物品,你得妥善管理self
func importUsers(url: URL) -> AnyPublisher<Int,Error> {
URLSession.shared.dataTaskPublisher(for: url)
.map(\.data)
.tryMap{data -> Int in
var users: [GitUser] = []
var cdError : Error?
self.importContext.performAndWait {
do {
let users = try self.decoder.decode([GitUser].self, from: data)
try self.importContext.save()
} catch {
cdError = error
}
}
if let error = cdError { throw error }
return users.count
}
.eraseToAnyPublisher()
}
不过你也可以使用 async/await
func importUsers(url: URL) async throws -> Int {
let (data, _) = try await URLSession.shared.data(from: url)
let users = try await self.importContext.perform {
try self.decoder.decode([GitUser].self, from: data)
try self.importContext.save()
}
return users.count
}
或者一个iOS13兼容的async
版本,这里perform
可以异步
func importUsers(url: URL) async throws -> Int {
try await withCheckedThrowingContinuation { continuation in
let task = URLSession.shared.dataTask(with: url) { [unowned self] (data, _ , error) in
if let error = error { continuation.resume(with: .failure(error)); return }
self.importContext.perform {
do {
let users = try self.decoder.decode([GitUser].self, from: data!)
try self.importContext.save()
continuation.resume(with: .success(users.count))
} catch {
continuation.resume(with: .failure(error))
}
}
}
task.resume()
}
}
我有以下代码进行 API 调用,接收数据并将其分配给 Core Data 托管对象。这很好用,并更新了我的数据。
func importUsers(url: URL) {
URLSession.shared.dataTaskPublisher(for: url)
.map(\.data)
.sink(receiveCompletion: { completion in
if case .failure(let error) = completion {
print("DataImporter.runImport failed with error: \(error)")
}
}, receiveValue: { [weak self] data in
guard let self = self
else { return }
self.importContext.perform {
do {
// 2. Decode the response. This decodes directly to the Core Data Store
let users = try self.decoder.decode([GitUser].self, from: data)
try? self.importContext.save()
} catch {
print("DataImporter.runImport failed to decode json with error: \(error)")
}
}
})
.store(in: &self.cancellables) // store the returned cancellable in a property on `DataImporter`
}
但是,我需要 return 作为此调用的结果 return 编辑和解码的对象数量。如果失败,我 return 0。本质上,我想要这个:
func importUsers(url: URL) -> Int {
URLSession.shared.dataTaskPublisher(for: url)
.map(\.data)
.sink(receiveCompletion: { completion in
if case .failure(let error) = completion {
print("DataImporter.runImport failed with error: \(error)")
}
}, receiveValue: { [weak self] data in
guard let self = self
else { return 0 }
var users: [GitUser] = []
self.importContext.perform {
do {
// 2. Decode the response. This decodes directly to the Core Data Store
users = try self.decoder.decode([GitUser].self, from: data)
try? self.importContext.save()
} catch {
print("DataImporter.runImport failed to decode json with error: \(error)")
}
}
return users.count
}).store(in: &self.cancellables) // error: Cannot convert return expression of type '()' to return type 'Int'
}
我如何 return 作为网络调用的结果收到的对象计数?
我的建议是解码数据并在管道和 return 发布者中创建核心数据记录。在另一个函数中订阅发布者和 sink
项目数 and/or 处理错误。
我没有你的自定义物品,你得妥善管理self
func importUsers(url: URL) -> AnyPublisher<Int,Error> {
URLSession.shared.dataTaskPublisher(for: url)
.map(\.data)
.tryMap{data -> Int in
var users: [GitUser] = []
var cdError : Error?
self.importContext.performAndWait {
do {
let users = try self.decoder.decode([GitUser].self, from: data)
try self.importContext.save()
} catch {
cdError = error
}
}
if let error = cdError { throw error }
return users.count
}
.eraseToAnyPublisher()
}
不过你也可以使用 async/await
func importUsers(url: URL) async throws -> Int {
let (data, _) = try await URLSession.shared.data(from: url)
let users = try await self.importContext.perform {
try self.decoder.decode([GitUser].self, from: data)
try self.importContext.save()
}
return users.count
}
或者一个iOS13兼容的async
版本,这里perform
可以异步
func importUsers(url: URL) async throws -> Int {
try await withCheckedThrowingContinuation { continuation in
let task = URLSession.shared.dataTask(with: url) { [unowned self] (data, _ , error) in
if let error = error { continuation.resume(with: .failure(error)); return }
self.importContext.perform {
do {
let users = try self.decoder.decode([GitUser].self, from: data!)
try self.importContext.save()
continuation.resume(with: .success(users.count))
} catch {
continuation.resume(with: .failure(error))
}
}
}
task.resume()
}
}