Swift的类型推断功能从一开始就是语言的核心部分,它大大减少了我们在声明具有默认值的变量和属性时必须手动指定类型的工作量。例如,表达式varnumber=7不需要包含任何类型注释,因为编译器可以推断出值7是Int并且我们的number变量应该相应地类型化。作为Xcode13.3的一部分发布的Swift5.6通过引入“类型占位符”的概念继续扩展这些类型推断功能,这在处理集合和其他泛型类型时很有用。例如,假设我们想在Combine中创建一个CurrentValueSubject的实例,并使用默认的整数值。关于如何做到这一点的最初想法可能是简单地将我们的默认值传递给主体的初始化程序,然后将结果本地存储在let声明的属性中(就像创建普通Int值时一样)。但是,这样做会给我们以下编译器错误://错误:“无法推断通用参数‘Failure’”//错误:“无法推断通用参数‘Failure’”letcounterSubject=CurrentValueSubject(0)This是因为CurrentValueSubject是泛型类型,实例化时不仅需要Output类型,还需要Failure类型——这是subject可以抛出的错误类型。由于我们不希望我们的主体在这种情况下抛出任何错误,我们将给它一个Never的Failure值(这是在Swift中使用Combine的常见习惯用法)。但是为了做到这一点,在Swift5.6之前,我们需要明确指定我们的Int输出类型——像这样:现在可以为我们的主题的输出类型使用类型占位符,这让我们再次利用编译器自动为我们推断类型,就像声明一个普通的Int值一样:letcounterSubject=CurrentValueSubject<_,Never>(0)这是不错,但可以说不是swift的巨大改进。毕竟,我们只是通过将Int替换为_来保存两个字符,并且手动指定像Int这样的简单类型首先没有问题。但现在让我们看看这个功能如何扩展到更复杂的类型,这才是它真正开始大放异彩的地方。例如,让我们加载一个用户注释的PDF文件,假设我们的项目包含以下函数:funcloadAnnotatedPDF(named:String)->Resource>{...}上面的函数使用了一个相当复杂的泛型作为它的返回类型,可能是因为我们需要在多个地方重用我们的Resource类型,也因为我们选择使用*phantom类型*来指定我们当前正在处理的PDF类型。现在让我们看看如果我们在创建主题时调用上面的函数而不是仅仅使用一个简单的整数,那么我们之前基于CurrentValueSubject的代码会是什么样子://在Swift5.6之前:letpdfSubject=CurrentValueSubject>,Never>(loadAnnotatedPDF(named:name))//Swift5.6:letpdfSubject=CurrentValueSubject<_,Never>(loadAnnotatedPDF(named:name))这是基于Swift5.6版本的相当大的改进,不仅节省了我们一些输入,而且由于pdfSubject的类型现在完全从loadAnnotatedPDF函数派生,这可能使迭代该函数(及其相关代码)更容易-因为如果我们更改该函数的返回类型,我们需要更新手动类型注释将减少。不过,值得指出的是,在上述情况下,还有另一种方法可以利用Swift的类型推断功能——那就是使用类型别名而不是类型占位符。例如,在这里我们可以定义一个UnfailingValueSubject类型别名,我们可以使用它来轻松创建不会产生任何错误的主题:我们的pdfSubject没有任何通用注释——因为编译器可以推断出T指的是什么类型,并且失败类型Never已经被硬编码到我们的新类型别名中:letpdfSubject=UnfailingValueSubject(loadAnnotatedPDF(named:name))但这并不意味着一般而言,类型别名比类型占位符更好,因为如果我们要为每个特定情况定义一个新的类型别名,它也会使我们的代码库变得更加复杂。有时内联指定所有内容绝对是个好主意(例如使用类型占位符时),因为这允许我们定义完全独立的表达式。在我们结束之前,让我们还看看类型占位符如何与集合文字一起使用-例如在创建字典时。在这里,我们选择手动指定我们字典的Key类型(为了能够使用点语法来引用枚举的各种情况),并为字典的值使用一个类型占位符:enumUserRole{caselocalcaseremote}letlatestMessages:[UserRole:_]=[.local:"",.remote:""]这是类型占位符——Swift5.6引入的新特性,在处理稍微复杂的泛型类型时,它可能真的很有用。但值得指出的是,这些占位符只能在调用处使用,不能在指定函数或计算属性的返回类型时使用。