前提条件:
protocol MobileOS {
associatedtype Version
var version: Version { get }
init(version: Version)
}
struct iOS: MobileOS {
var version: Float
}
struct Android: MobileOS {
var version: String
}
于是写一个函数:
func buildOS() -> MobileOS {
return iOS(version: 16.1)
}
这样编译器会报错, 因为它无法推断出 associatedtype, 但是在 MobleOS 前面加上 some, 它就不会报错, 所以 some 是让编译器忽略类型推断, 只需要返回的类型继承 MobileOS 即可?
那接着来:
func buildOS() -> some MobileOS {
let isEven = Int.random(in: 0...10) % 2 == 0
return isEven ? iOS(version: 16.1) : Android(version: "Pie")
}
这样编译器又报错了, 如果将 Android(version: "Pie")
改成 iOS(version: 16.2)
就不会报错. 所以编译器也是会推断返回值类型? 必须要返回相同的类型?
在 SwiftUI 中有很多这样的例子, 而且如果想返回多个不同类型, 需要加一个 @ViewBuilder
, 这样编译器又行了..???
类型和协议是两个不同的派系, 类型可以符合某些协议, 函数或者计算属性也可以用协议来替代类型作为返回. 基于以上, 为什么不让编译器宽泛一点, 却引入一个 some 来增加程序员的理解?
能有上述问题是因为我遇到了下面这个错误, 代码是按照官方例子中的 demo: https://developer.apple.com/tutorials/swiftui/interfacing-with-uikit
struct PageView<Page: View>: View {
var page: [Page]
// body ..
}
struct Page1: View {
var body: some View {
Color.red
}
}
struct Page2: View {
var body: some View {
Color.red
}
}
struct ContentView: View {
var body: some View {
PageView(page: [Page1(), Page2()])
}
}
这样编译器会直接报错, 并且错误原因也不给. 但当我将数组只放一个数据时候, 编译器就给通过了 PageView(page: [Page1()])
, 如果想要数组多个数据, 需要用 AnyView 包裹一下每个 Page.
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.