Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
533 views
in Technique[技术] by (71.8m points)

functional programming - How to chain Swift Futures

I have defined the following functions:

func createAccessControl() -> Future<SecAccessControl, Error>

func evaluatePolicy(context: LAContext, localizedReason: String) -> Future<LAContext, Error>

func evaluateAccessControl(
    context: LAContext,
    accessControl: SecAccessControl,
    operation: LAAccessControlOperation,
    localizedReason: String
) -> Future<LAContext, Error>

func copy(query: [String: Any]) -> Future<Data, Error>

And I want to chain them together like this:

func load(key: String, context: LAContext = LAContext(), localizedReason: String) -> Future<Data, Error> {
        createAccessControl().flatMap { accessControl in
            evaluatePolicy(context: context, localizedReason: localizedReason)
                .flatMap { context in
                    evaluateAccessControl(context: context, accessControl: accessControl, operation: .useItem, localizedReason: localizedReason)
                }
                .flatMap { context in
                    copy(query: [
                        kSecClass as String: kSecClassGenericPassword as String,
                        kSecAttrService as String: service,
                        kSecAttrAccount as String: account,
                        kSecAttrAccessControl as String: accessControl,
                        kSecUseAuthenticationContext as String: context,
                        kSecReturnData as String: kCFBooleanTrue,
                        kSecMatchLimit as String: kSecMatchLimitOne,
                    ])
                }
        }
    }

However, I get this error:

Cannot convert return expression of type 'Publishers.FlatMap<Publishers.FlatMap<Future<Data, Error>, Publishers.FlatMap<Future<LAContext, Error>, Future<LAContext, Error>>>, Future<SecAccessControl, Error>>' to return type 'Future<Data, Error>'

I thought flatMap was supposed to flatten the resulting type, but that doesn't seem to be happening the way I expect.

How do I chain futures together, similar to JavaScript's "then"?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Changing my return types from Future<> to AnyPublisher<> eliminated all the compiler errors, and simply required a call to eraseToAnyPublisher() inside those functions. For example:

func evaluateAccessControl(context: LAContext, accessControl: SecAccessControl, operation: LAAccessControlOperation, localizedReason: String) -> AnyPublisher<LAContext, Error> {
    Future() { promise in
        context.evaluateAccessControl(accessControl, operation: operation, localizedReason: localizedReason) { success, error in
            if let error = decodeLAError(error) {
                promise(.failure(error))
            } else if success {
                promise(.success(context))
            }
        }
    }.eraseToAnyPublisher()
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...