swift - 关于 SwiftUI 中 View 作为类型约束的问题
问题描述
我正在尝试创建一个名为 Lesson 的类。每个课程对象应包含不同的课程页面(视图),以便每个课程卡片可以导航到不同的页面。
课程课程的代码如下:
class Lesson<T: View>: Identifiable {
let id = UUID()
var lessonName: String
var lessonPage: T
init(lessonName: String,
lessonPage: T = DefaultLessonPageView() as! T) {
self.lessonName = lessonName
self.lessonPage = lessonPage
}
}
问题是编译以下代码时发生错误:
struct ButtonPageView: View {
var lesson: Lesson<View>
var body: some View {
NavigationLink(destination: lesson.lessonPage()) {
some view here
}
}
}
错误如下:
协议类型“View”的值不能符合“View”;只有结构/枚举/类类型可以符合协议
我应该怎么做才能解决这个问题?
解决方案
对于泛型,我们应该记住类型是在编译类型中推断出来的,因此在编写表达式时应该知道视图。因此 SwiftUI 为此使用了构建器模式。
这是一个演示如何通过支持通用页面和提供的一些默认页面来解决它。
使用 Xcode 12.4 / iOS 14.4 测试
class Lesson<T: View>: Identifiable {
let id = UUID()
var lessonName: String
var builder: (() -> T)? // << optional builder
@ViewBuilder
func lessonPage() -> some View { // ViewBuilder gives possibility
if let page = builder?() { // to provide default view
page
} else {
DefaultLessonPageView()
}
}
init(lessonName: String,
lessonPage: (() -> T)? = nil) { // by default no view
self.lessonName = lessonName
self.builder = lessonPage
}
}
struct ButtonPageView<Page: View>: View {
var lesson: Lesson<Page>
var body: some View {
NavigationLink(destination: lesson.lessonPage()) {
Text("")
}
}
}
现在我们可以将它们用作
var body: some View {
// no view, so let compiler know
ButtonPageView<Never>(lesson: Lesson(lessonName: "First"))
// page type is inferred from builder
ButtonPageView(lesson: Lesson(lessonName: "Second", lessonPage: {
Text("Second Lesson")
}))
}
推荐阅读
- javascript - css-loader 3.4.2中通过localsConvention的kebab-case到camelCase不起作用
- python - ModuleNotFoundError:没有名为“_winreg”的模块
- react-native - Expo Android自适应图标未出现
- git - 我的 Gatsby CMS 部署不是我想要的,Google maps gatsby 插件
- javascript - 如何模拟输入文本?Javascript/jQuery, vextab
- windows - 在 IE 中编辑 Word 不打开 Word
- xml - 如何将 MARC21-xml 转换和过滤成 csv?
- ruby-on-rails - Rails 管理员:如何添加助手和使用视图助手?
- javascript - 如何获取任何 subreddit 图片,包括成人图片?不和谐.js
- java - 在 Java 中找不到 REST 服务的 url