Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/107.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 快速联合收割机:发送值后发送完成_Ios_Swift_Combine - Fatal编程技术网

Ios 快速联合收割机:发送值后发送完成

Ios 快速联合收割机:发送值后发送完成,ios,swift,combine,Ios,Swift,Combine,我正在为我的网络模块进行缓存。对于每个请求,我的模块将向调用者返回一个AnyCancallable。如果缓存数据不可用,我使用URLSession.dataTaskPublisher,它可以处理两个事件:数据接收和完成。如果缓存数据可用,我将使用CurrentValueSubject创建AnyCancallable返回。我发送了关于这个主题的两个事件,但在调用方,它只在完成时收到通知,没有数据 cacheSubject.send(cachedData.data) cacheSubject.sen

我正在为我的网络模块进行缓存。对于每个请求,我的模块将向调用者返回一个
AnyCancallable
。如果缓存数据不可用,我使用
URLSession.dataTaskPublisher
,它可以处理两个事件:数据接收和完成。如果缓存数据可用,我将使用
CurrentValueSubject
创建AnyCancallable返回。我发送了关于这个主题的两个事件,但在调用方,它只在完成时收到通知,没有数据

cacheSubject.send(cachedData.data)
cacheSubject.send(completion: Subscribers.Completion<Error>.finished)
cacheSubject.send(cachedData.data)
cacheSubject.send(完成:订阅者.completion.finished)
删除完成发送,现在它可以接收数据,但没有完成通知

有人能告诉我我做错了什么吗

这是完整的文件,以备你们需要:

public class SSNetworkManager {
    public static let shared = SSNetworkManager()
    
    private var cache: [String: CachedData] = [:]
    private let cacheSubject = CurrentValueSubject<Data, Error>(Data())
    
    @discardableResult public func makeServiceCall<D: Decodable>(forRequest request: SSNetworkRequest<D>, onMainThread: Bool = true) -> AnyPublisher<D, Error>? {
        guard let urlRequest = request.urlRequest else {
            return nil
        }
        
        var cancelable: AnyPublisher<Data, Error>
        
        if let url = urlRequest.url?.absoluteString,
           let cachedData = cache[url],
           cachedData.isValid {
            cancelable = cacheSubject.eraseToAnyPublisher()
            cacheSubject.send(cachedData.data)
            cacheSubject.send(completion: Subscribers.Completion<Error>.finished)
        } else {
            cancelable = URLSession.shared.dataTaskPublisher(for: urlRequest).tryMap {[weak self] (data, response) -> Data in
                guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {
                    throw SSNetworkError(httpCode: (response as? HTTPURLResponse)?.statusCode ?? 0, data: data)
                }
                if request.shouldCacheNow,
                   let url = urlRequest.url?.absoluteString {
                    self?.cache[url] = CachedData(data: data, expirationTime: request.cacheExpirationTime)
                }
                return data
            }.eraseToAnyPublisher()
        }
        
        if onMainThread {
            return cancelable
                .receive(on: RunLoop.main)
                .decode(type: D.self, decoder: JSONDecoder())
                .eraseToAnyPublisher()
        } else {
            return cancelable
                .decode(type: D.self, decoder: JSONDecoder())
                .eraseToAnyPublisher()
        }
    }
}

fileprivate struct CachedData {
    let data: Data
    let expirationTime: Date
    
    var isValid: Bool {
        return Date().compare(expirationTime) != .orderedDescending
    }
}
公共类SSNetworkManager{
公共静态let shared=SSNetworkManager()
私有变量缓存:[String:CachedData]=[:]
private let cacheSubject=CurrentValueSubject(Data())
@discardableResult public func makeServiceCall(forRequest请求:SSNetworkRequest,onMainThread:Bool=true)->AnyPublisher{
guard let urlRequest=request.urlRequest else{
归零
}
var可取消:AnyPublisher
如果让url=urlRequest.url?.absoluteString,
让cachedData=cache[url],
cachedData.isValid{
cancelable=cacheSubject.橡皮擦到任何发布者()
cacheSubject.send(cachedData.data)
cacheSubject.send(完成:订阅者.completion.finished)
}否则{
cancelable=URLSession.shared.dataTaskPublisher(for:urlRequest).tryMap{[weak self](数据,响应)->中的数据
guard让httpResponse=响应为?HTTPURLResponse,httpResponse.statusCode==200其他{
抛出SSNetworkError(httpCode:(响应为?HTTPURLResponse)?。状态码??0,数据:数据)
}
如果request.shouldCacheNow,
让url=urlRequest.url?.absoluteString{
self?.cache[url]=CachedData(数据:数据,过期时间:request.cacheExpirationTime)
}
返回数据
}.删除任何发布者()
}
如果在mainthread上{
可取消返回
.receive(打开:RunLoop.main)
.decode(类型:D.self,解码器:JSONDecoder())
.删除任何发布者()
}否则{
可取消返回
.decode(类型:D.self,解码器:JSONDecoder())
.删除任何发布者()
}
}
}
fileprivate结构缓存数据{
让数据:数据
let expirationTime:日期
变量isValid:Bool{
返回日期().compare(expirationTime)!=.orderedDescending
}
}

这不是使用主题的正确情况。相反,请返回与每个案例相关的发布者:

public class SSNetworkManager {
    // ...
    
    public func makeServiceCall<D: Decodable>(
           forRequest request: SSNetworkRequest<D>, 
           onMainThread: Bool = true
        ) -> AnyPublisher<D, Error>? {

        // consider just returning Empty().eraseToAnyPublisher() instead of nil
        guard let urlRequest = request.urlRequest else {
            return nil
        }

        var resultPublisher: AnyPublisher<D: Error>
        
        if let url = urlRequest.url?.absoluteString,
           let cachedData = cache[url],
           cachedData.isValid {

            resultPublisher = Just(cachedData.data)
                      .setFailureType(to: Error.self)
                      .eraseToAnyPublisher()

        } else {
            resultPublisher = URLSession.shared
                .dataTaskPublisher(for: urlRequest)
                .tryMap { ... }
                .decode(type: D.self, decoder: JSONDecoder())
                .eraseToAnyPublisher()
        }

        return onMainThread
               ? resultPublisher
                    .receive(on: DispatchQueue.main)
                    .eraseToAnyPublisher()
               : resultPublisher
                    .eraseToAnyPublisher()
    }
}
公共类SSNetworkManager{
// ...
公共函数makeServiceCall(
forRequest请求:SSNetworkRequest,
onMainThread:Bool=true
)->有出版商吗{
//只考虑返回空().ErasToEnPusithErter()而不是NIL。
guard let urlRequest=request.urlRequest else{
归零
}
var resultPublisher:AnyPublisher
如果让url=urlRequest.url?.absoluteString,
让cachedData=cache[url],
cachedData.isValid{
resultPublisher=Just(cachedData.data)
.setFailureType(收件人:Error.self)
.删除任何发布者()
}否则{
resultPublisher=URLSession.shared
.dataTaskPublisher(用于:urlRequest)
.tryMap{…}
.decode(类型:D.self,解码器:JSONDecoder())
.删除任何发布者()
}
返回mainthread
?结果发布者
.receive(在:DispatchQueue.main上)
.删除任何发布者()
:resultPublisher
.删除任何发布者()
}
}

我可以注意到的一件事是,您的Cancelable属性位于一个函数中,这是错误的,我想它应该位于您的类中,否则它不会在函数作用域之后保存任何值。缓存代码是同步发生的,因此您在有订阅者接收它之前发送一个值。受试者不储存价值观——基本上是gone@CrackIt,我随后返回,调用方负责保留对cancallable@NewDev抢手货Thanks@NewDev我试图在返回订户后呼叫发送,但它仍然只发送完成感谢@NewDev,你让我免于头痛。不知道只是存在。而且异步主题发送也不起作用,因为我创建了一个混乱的引用。