为什么这会在Combine中产生编译器错误?

时间:2019-12-16 16:31:39

标签: ios swift combine publisher

仅尝试在我的新项目中实现SwiftUI和Combine。 但陷入其中:

    func task() -> AnyPublisher<Int, Error> {

        return AnyPublisher { subscriber in

            subscriber.receive(Int(arc4random()))
            subscriber.receive(completion: .finished)
        }
    }

这会产生以下编译器错误:

类型'(_)->()'不符合协议'Publisher'

为什么?

更新

实际上Random只是一个示例。真实的代码将如下所示:

 func task() -> AnyPublisher<SomeCodableModel, Error> {

    return AnyPublisher { subscriber in

        BackendCall.MakeApiCallWithCompletionHandler { response, error in 

           if let error == error {

               subscriber.receive(.failure(error))
           } else {

               subscriber.receive(.success(response.data.filter))
               subscriber.receive(.finished)
           }
       }
    }
}

很遗憾,我没有访问BackendCall API的权限,因为它是私有的。 这是一种伪代码,但是非常接近真实代码。

3 个答案:

答案 0 :(得分:1)

您不能使用接受AnyPublisher的闭包来初始化Subscriber。您只能从AnyPublisher中初始化Publisher。如果要创建自定义Publisher并在收到订阅者并完成后立即发出单个随机Int的自定义类型,则可以创建符合Publisher且自定义类型的自定义类型方法receive(subscriber:),完全按照关闭时的操作进行操作。

struct RandomNumberPublisher: Publisher {
    typealias Output = Int
    typealias Failure = Never

    func receive<S>(subscriber: S) where S : Subscriber, Failure == S.Failure, Output == S.Input {
        subscriber.receive(Int.random(in: 0...Int.max))
        subscriber.receive(completion: .finished)
    }
}

然后,在您的task方法中,只需创建一个RandomNumberPublisher,然后键入“ ease”即可。

func task() -> AnyPublisher<Int, Never> {
    return RandomNumberPublisher().eraseToAnyPublisher()
}

答案 1 :(得分:1)

如果您想要的只是一个随机值,请使用Just

fun task() -> AnyPublisher<Int, Never> {
  return Just(Int.random(in: 0...Int.max)).eraseToAnyPublisher()
}

旁注:不要再使用Int(arc4random())

答案 2 :(得分:0)

您最好将其包装在Future发布者中,如果希望订阅时响应,也可以用Deferred包装。Future是包装外部异步API调用的绝佳方法,尤其是可以打包的异步API。不能完全控制或容易适应。

Using Combine中有一个"wrapping an async call with a Future to create a one-shot publisher"的示例,它看起来可能与您要尝试的操作非常接近。

如果您希望它返回的值不止一个值,那么您可能希望从PassthoughSubject或CurrentValueSubject中编写一些内容,从而为您提供-> AnyPublisher<YourType, Error>(或您要查找的内容)的接口。