实战教程·元宇宙来了,准备好你的电子名片了吗?(七)
前提回顾
不知不觉已经到了第七章了,在过往每一个章节中,我们都增加和完成项目的一些功能,让Linkwirld这款产品越来越接近完成品。
一款以用户操作为核心功能的产品,需要包含增删改查4部分功能,在之前的章节中我们已经完成了查看、新增、删除的功能,还缺少对于身份卡进行编辑的功能。编辑操作为用户对于之前创建的内容的调整或者更新,在ToDo、Note等应用当中很是常见。
那么在本章中,我们来完成后编辑相关的操作。
功能分析:新增和编辑页面的区别
很多时候都会有一个疑惑,现在页面和编辑页面到底有没有区别?开发人员究竟只需要维护一个页面还是要维护两个页面?
一般情况下,由于页面样式的相似性,新增和编辑操作在开发的角度上是需要做到共用的。但新增和编辑页面除了数据绑定外没有太大的样式区分时,我们建议可以将样式或者组件抽离出来,然后再单独应用。
视图复用:创建单独的构件
在新增和编辑页面中,我们会发现有几部分视图内容是可以复用的:titleInputView平台输入框、platformPicker平台选择器、indexURLView链接地址。如下图所示:
因此对于这三部分,我们可以将其抽离出来搭建单独的构件,如此便可以在新增页面和编辑页面都可以引用。而且如果需要修改样式,也只需要修改构件的样式,新增和编辑页面的样式就可以统一变化。
我们创建一个新的文件夹,命名为Artifacts,并且创建3个SwiftUI文件,并为其命名为TitleInputView、PlatformPicker、IndexURLView,如下图所示:
我们先来到TitleInputView文件,将原来NewView中的titleInputView视图代码复制过来,如下代码所示:
import SwiftUI struct TitleInputView: View { @Binding var title: String var body: some View { TextField("请输入头衔", text: $title) .padding() .background(Color(.systemGray6)) .cornerRadius(8) .padding(.horizontal) .disableAutocorrection(true) .autocapitalization(.none) } } struct TitleInputView_Previews: PreviewProvider { static var previews: some View { TitleInputView(title: .constant("")) } }
上述代码中,除了TextField输入框相关代码复制过来,我们还需要完善相关的绑定参数。声明一个用于双向绑定输入框的参数title,并且在TitleInputView预览时给参数赋予默认值。
紧接着来到PlatformPicker视图,将原来NewView中的platformPicker视图代码复制过来,如下代码所示:
import SwiftUI struct PlatformPicker: View { @Binding var platformIcon: String @Binding var platformName: String let platforms = [ ("稀土掘金技术社区", "icon_juejin"), ("CSDN博客", "icon_csdn"), ("阿里云社区", "icon_aliyun"), ("华为云社区", "icon_huaweiyun"), ] var gridItemLayout = [GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible())] var body: some View { ScrollView { LazyVGrid(columns: gridItemLayout, spacing: 10) { ForEach(0 ..< platforms.count, id: .self) { item in if platforms[item].0 == platformName { Image(platforms[item].1) .resizable() .aspectRatio(contentMode: .fit) .frame(width: 48, height: 48) .clipShape(Circle()) .overlay( Circle() .stroke(Color.green, lineWidth: 4) ) } else { Image(platforms[item].1) .resizable() .aspectRatio(contentMode: .fit) .frame(width: 48, height: 48) .clipShape(Circle()) .onTapGesture { platformIcon = platforms[item].1 platformName = platforms[item].0 } } } } } .padding() .background(Color(.systemGray6)) .cornerRadius(8) .padding(.horizontal) .frame(maxHeight: 140) } } struct PlatformPicker_Previews: PreviewProvider { static var previews: some View { PlatformPicker(platformIcon: .constant("icon_juejin"), platformName: .constant("稀土掘金技术社区")) } }
上述代码中,我们仍旧讲需要声明双向绑定的变量,如:platformIcon平台图标、platformName平台名称,值得注意的是,原有我们声明的selectedItem完全可以换成判断platformName是否等于点击的名称,减少一个参数。如下代码所示:
platforms[item].0 == platformName