为什么Xcode一直用'_'代替泛型

问题描述 投票:2回答:1

我正在使用Swift 5和Vapor 3制作服务器。在设置路由时,我想从我的控制器调用一个函数,它返回一个可选项,如下所示:

//Person.swift

struct Person: Content {
    ...
}
//PersonController.swift

func update(_ request: Request) throws -> Future<Person> {
    let uuid = try request.parameters.next(UUID.self)

    return try request.content.decode(Person.self).flatMap { content in
        request.withPooledConnection(to: DatabaseIdentifier<PostgreSQLDatabase>.psql) { connection in
            /*
            *  No code completion beyond this point,
            *  even connection appears as type '_' instead of
            *  PostgreSQLConnection (not relevant to the question tho,
            *  just worth noting)
            */
            if content.lastName != nil {
                return connection.raw("Very long SQL query...")
                .binds([...])
                .first(decoding: Person.self)
            }

            return connection.raw("Other long SQL query")
            .binds([...])
            .first(decoding: Person.self)
        }
    }

}
router.put("people", UUID.parameter, use: personController.update)

但后来我得到了这个错误

Cannot convert value of type '(Request) throws -> EventLoopFuture<Person?>' to expected argument type '(Request) throws -> _'

在使用Vapor时我看到很多实例,其中Xcode放弃了自动完成,而且所有内容都只是输入为_。主要是用作回调的内部闭包。这非常烦人,坦率地说我不确定它是否是由于Vapor,Swift或Xcode造成的。它是一个巨大的PITA但是一旦我编译它就会得到解决,这些类型就会被整理出来。但是在这种情况下它只是不起作用。

所以问题是:当(Request) throws -> _的实际定义需要Request.put(_:use:)时,Xcode为什么说预期的类型是(Request) throws -> T?这是如何使T成为Future<Person>Future<Person?>的?

swift xcode generics vapor server-side-swift
1个回答
2
投票

你在这里打电话的.first方法:

return connection.raw("Other long SQL query")
.binds([...])
.first(decoding: Person.self)

返回Future<Optional<Person>>Future<Person?>。路由处理程序的返回类型是Future<Person>,因此返回类型不正确。但即使您确实更改了处理程序的返回类型,也无法修复它。

你的主要问题是你不能从路由处理程序返回一个可选项,因为Optional绝不符合ResponseEncodable。如果您愿意,可以自己添加一致性。

如果您不想添加一致性,则可以在解码查询结果后使用.unwrap(or:)方法:

return connection.raw("Other long SQL query")
.binds([...])
.first(decoding: Person.self)
.unwrap(or: Abort(.notFound))

这将检查以后的值是否存在。如果是,则传递该值。否则,未来的链接收您传入的错误,而不是返回。

© www.soinside.com 2019 - 2024. All rights reserved.