前提回忆

在上一章中,咱们创立了CardView构件,运用了构件编程办法树立视图。运用构件的好处是当咱们要整体修正构件内容时,就能够只修正构件的结构体,而无需每个卡片视图都修正。

示例,在上一章中咱们设置了渠道图标图片,但因为渠道图标款式的不统一性,看起来有些不协调。这时分,咱们能够给CardView构件中的Image控件设置为圆形,让其愈加漂亮些,如下图所示:

实战教程元宇宙来了,准备好你的电子名片了吗?(二)

关于树立好的构件,只需求修正CardView构件自身,就能够在引证此构件的一切地方统一修正其款式。

是不是很便利?接下来让咱们持续完结下面的内容。

结构化编程:树立数据模型

运用构件创立身份卡片视图后,咱们发现如果每次要新增一个卡片,就需求在卡片视图中需求复制CardView构件并赋值。当咱们需求创立很多身份卡片时,就会需求很多一样的代码,这不够高雅。

有没有办法像树立CardView构件一样,只树立一个结构然后填充数据,让结构自动“遍历”出内容?

SwiftUI声明式语言中,能够运用List列表组件循环遍历内容,在此之前咱们需求界说好数据模型。咱们创立一个新的Swift文件,命名为Model,如下图所示:

实战教程元宇宙来了,准备好你的电子名片了吗?(二)

Model文件作为咱们树立数据模型的文件,界说数据需求声明的变量。首要咱们引证SwiftUI,如下代码所示:

import SwiftUI

接下来树立数据模型,如下代码所示:

struct Model: Identifiable {
    var id = UUID()
    var platformIcon: String
    var title: String
    var platformName: String
    var indexURL: String
}

实战教程元宇宙来了,准备好你的电子名片了吗?(二)

数据模型能够运用Class类或者Struct结构体声明,这里咱们运用Struct结构体声明晰一个数据模型Model,遵从Identifiable协议。“Identifiable可辨认”协议能够经过id区分不同的数据,当咱们创立的数据中有两条一模一样的数据时,因为“Identifiable可辨认”协议,体系将赋予不同的id,完结出现两条数据内容的作用。

运用Identifiable协议除了声明需求的参数变量外,还需求在数据模型中声明一个id,并复制为UUID。该数据模型中的需求运用的变量参数,咱们能够直接运用之前在CardView身份卡片构件声明的参数。

声明好参数后,咱们为展现数据,能够创立一个数据数组作为示例数据,如下代码所示:

// MARK: 示例数据
var models = [
    Model(platformIcon: "icon_juejin", title: "移动端签约作者", platformName: "稀土技能社区", indexURL: "https:///user/3897092103223517"),
    Model(platformIcon: "icon_csdn", title: "iOS创作者", platformName: "CSDN博客", indexURL: ""),
    Model(platformIcon: "icon_aliyun", title: "专家博主", platformName: "阿里云社区", indexURL: ""),
    Model(platformIcon: "icon_huaweiyun", title: "专家博主", platformName: "华为云社区", indexURL: ""),
]

实战教程元宇宙来了,准备好你的电子名片了吗?(二)

如此便完结了数据模型的树立。

卡片视图:List列表和ForEach循环

咱们回到ContentView视图中,删去原有的身份卡片视图的代码。卡片视图咱们能够看作一个列表,每张身份卡片就是一行行出现的数据,列表的数据源则来源于上述创立好的数组models,如下图所示:

List {
    ForEach(models) { item in
		CardView(platformIcon: item.platformIcon, title: item.title, platformName: item.platformName, indexURL: item.indexURL)
	}
    .listRowBackground(Color.clear)
    .listRowSeparator(.hidden)
}

实战教程元宇宙来了,准备好你的电子名片了吗?(二)

上述代码中,咱们运用List列表和ForEach循环结构,遍历models数组中界说好的数据内容,并在调用CardView身份卡片构件的时分赋值为循环后item的一条条数据。

因为演示的iPhonex模拟器,因而为了出现更好的列表款式作用,运用listRowBackground列表项背景修饰符,将列表背景色彩修饰为通明。并运用listRowSeparator列表分割线修饰符,躲藏List自带的分割线。完结这些操作后后,就能够完结展现身份卡片构件的款式内容。

在模拟器中预览的作用中,身份卡片左右边距太宽了,咱们能够直接修正CardView构件的代码,去掉最终的padding边距,如下图所示:

实战教程元宇宙来了,准备好你的电子名片了吗?(二)

导航菜单:标题和新建卡片进口

卡片视图完善之后,咱们来树立顶部导航菜单。SwiftUI提供了NavigationView导航视图控件便利咱们快速树立运用的顶部导航菜单。从视图层级来看,顶部导航菜单是“包裹”整个页面视图的,因而NavigationView导航视图控件需求在ContentView的body视图最外层,如下代码所示:

NavigationStack {
    //视图内容
    .navigationBarTitle("文如秋雨",displayMode: .inline)
}

实战教程元宇宙来了,准备好你的电子名片了吗?(二)

在iOS16版别,运用NavigationStack导航视图控件树立顶部导航菜单,iOS16版别以下的机型运用NavigationView导航。

树立好顶部导航栏后,咱们创立一个新的按钮,作为创立身份卡片的进口。能够运用navigationBarItems导航栏按钮修饰符创立导航菜单上的按钮进口,不过在此之前,咱们需求树立好按钮的视图,再将按钮赋予navigationBarItems导航栏按钮修饰符。如下代码所示:

func addBtn() -> some View {
        Button(action: {
        }) {
            Image(systemName: "plus.circle.fill")
                .font(.system(size: 17))
                .foregroundColor(.blue)
        }
    }

上述代码中,咱们完结了一个按钮视图addBtn。一般在编程过程中,若视图中除款式代码外还有交互操作,通常会将其抽离出来作为一个独自的视图进行构建,然后再在修饰符或者其他视图中运用,这是SwiftUI开发中经常会遇到的事情。

完结按钮视图的构建后,咱们将按钮视图加到顶部导航菜单中,如下代码所示:

.navigationBarItems(trailing: addBtn())

实战教程元宇宙来了,准备好你的电子名片了吗?(二)

模态弹窗:翻开一个新页面

个人主页部分根本已经完结了,下面咱们来完结点击顶部导航菜单的“增加”按钮,翻开“新建身份卡”页面。

首要咱们先创立一个新的SwiftUI文件,命名为NewView,如下图所示:

实战教程元宇宙来了,准备好你的电子名片了吗?(二)

回到ContentView视图中,运用Sheet模态弹窗控件,创立翻开弹窗的款式,如下代码所示:

.sheet(isPresented:Is Presented) {
	 Content
 }

实战教程元宇宙来了,准备好你的电子名片了吗?(二)

上述代码中,咱们运用sheet修饰符控件树立翻开模态弹窗作用,但需求运用sheet修饰符控件,需求提早声明好触发翻开动作的变量,如下代码所示:

 @State var showNewView:Bool = false

并将声明好的触发变量绑定到sheet修饰符控件中,以及设置Content跳转的页面目标为NewView。如下代码所示:

.sheet(isPresented: $showNewView) {
	NewView()
}

最终在点击addBtn按钮视图时,切换showNewView翻开视图的变量状态,便可完结点击“增加按钮”翻开模态弹窗,如下代码所示:

self.showNewView.toggle()

实战教程元宇宙来了,准备好你的电子名片了吗?(二)

封闭弹窗的办法也很类似,咱们来到NewView视图,给NewView视图的内容增加顶部导航菜单,并也创立一个封闭弹窗的按钮,如下代码所示:

struct NewView: View {
    var body: some View {
        NavigationStack {
            Text("Hello, World!")
                .navigationBarTitle("增加身份卡", displayMode: .inline)
                .navigationBarItems(trailing: closeBtn())
        }
    }
    func closeBtn() -> some View {
        Button(action: {
        }) {
            Image(systemName: "xmark.circle.fill")
                .font(.system(size: 17))
                .foregroundColor(.gray)
        }
    }
}

实战教程元宇宙来了,准备好你的电子名片了吗?(二)

上述代码中,咱们运用的办法和个人主页的内容根本一致,运用NavigationStack导航菜单控件创立导航菜单,并运用navigationBarTitle顶部导航标题控件创立标题。独自创立封闭按钮视图closeBtn,并将它赋予导航菜单中的navigationBarItems导航菜单栏目修饰符,以创立导航菜单上的按钮。

封闭弹窗:双向绑定或全局变量

完结翻开模态弹窗后,咱们来完结封闭模态弹窗,下面咱们来介绍两种封闭模态弹窗的办法:双向绑定、全局变量。

因为咱们在ContentView个人主页声明晰一个变量showNewView来翻开模态弹窗,当点击addBtn按钮时更新其状态。因而咱们也能够在NewView页面中也声明一个双向绑定的变量showNewView,并在点击closeBtn时更新其状态,完结封闭弹窗的交互。

首要先声明一个双向绑定的变量showNewView如下图所示:

@Binding var showNewView:Bool

然后在点击closeBtn封闭按钮时更新其状态,如下代码所示:

self.showNewView.toggle()

因为运用@Binding声明变量,因而在NewView视图中声明的变量缺少赋值,将或许导致无法预览,因而咱们在预览时需求给NewView视图赋予默认值,如下代码所示:

NewView(showNewView: .constant(false))

实战教程元宇宙来了,准备好你的电子名片了吗?(二)

树立双向绑定的视图,在一切页面也都需求进行@Binding声明变量的绑定,因而咱们回到ContentView视图中,绑定showNewView变量,如下代码所示:

NewView(showNewView: $showNewView)

实战教程元宇宙来了,准备好你的电子名片了吗?(二)

完结后,能够在模拟器中操作翻开模态弹窗和封闭模态弹窗的交互。

另一种封闭模态弹窗的办法是声明一个全局变量,完结封闭弹窗的作用,如下代码所示:

//声明环境变量
@Environment(.presentationMode) var presentationMode
//调用
self.presentationMode.wrappedValue.dismiss()

实战教程元宇宙来了,准备好你的电子名片了吗?(二)

上述代码中,咱们声明晰一个全局变量presentationMode,在点击closeBtn封闭按钮的时分调用presentationMode全局变量的wrappedValue.dismiss办法完结封闭弹窗作用。

两种办法在实际开发过程中均有运用,除模态弹窗外,在页面之间运用入栈出栈的办法进行切换页面也经常会用到。

在模态弹窗交互逻辑中更经常运用全局变量封闭弹窗的办法,无需进行双向绑定已经给视图增加默认值,也就无需示例在其他页面缺少绑定参数的费事。

本章小结

在本章中,咱们主要完结了运用数据模型和List列表来构建身份卡片视图的内容,在减少代码量的同时,其实也是为了之后对身份卡片进行新增、编辑、删去做前期准备。

在SwiftUI中,复杂的具有相似结构的界面设计,通常会运用List列表和ForEach来完结,常见的类似Todo待办事项App中的卡片列表、信息流App的信息列表、短视频渠道的视频封面卡片视图等等。

别的咱们还学习了运用NavigationStack导航菜单控件(iOS16版别及以上机型运用,低于此版别机型运用NavigationView,Apple经常会在新控件完善后弃用旧控件,这点有点烦)及其标题、导航按钮修饰符的运用,并进一步了解了运用sheet模态弹窗修饰符翻开弹窗。封闭弹窗部分,咱们介绍了两种办法完结封闭弹窗,并简略介绍了其运用特色。

鄙人面的章节中,咱们将持续完结“增加身份卡”页面的相关操作,请保持期待吧~

版权声明

本文为稀土技能社区首发签约文章,14天内制止转载,14天后未获授权制止转载,侵权必究!