使用Xcode13进行Swift开发2

本文详细介绍了使用Xcode13进行SwiftUI应用开发的过程,包括UIScreen与systemName的使用,如何创建结构体并利用ScrollView、Padding、ForEach构建列表,以及GeometryReader的运用和结合Combine实现动态数据的列表展示。通过实例代码,展示了在Swift开发中的技巧和注意事项。
摘要由CSDN通过智能技术生成

使用Xcode13进行Swift开发https://blog.csdn.net/gavinliu266/article/details/126407896
Monterey错误已在本博客中修正

1.应用功能

快捷键与SFsymbols请看文首链接。

1.1 UIScreen与systemName

为了方便演示,我将新建一个swift文件
选择一个swift文件,右键-New File-SwiftUI View,命名CardView,并将Targets中的Test_WidgetExtension钩上
创建一个简单的卡片

struct CardView: View {
    var body: some View {
        ZStack {
            Image("Monterey")
                .resizable()
                .frame(width:200,height:200)
                .cornerRadius(20)
                .shadow(color: Color.black.opacity(0.4), radius: 30, x: 0, y: 30)
            VStack {
                Text("Macos12 Monterey")
                    .font(.title)
                    .fontWeight(.bold)
                    .frame(width:200)
                    .foregroundColor(.white)
                Image(systemName: "person.2")
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(width:100,height: 100)
                    .foregroundColor(.white)
            }
        }
    }
}

这里width我们暂时设置200
systemName:
在SFsymbols中找到想要的图标,但是如果在右边栏中显示的系统ios版本比你的Xcode所支持的版本要高,那么你也不能使用它。例如我的Xcode13.4.1对于请添加图片描述是可以支持的,但是对于请添加图片描述由于需要iOS 16.0+,所以不能支持

接下来Command 点击ZStack,嵌入一个HStack,然后提取子视图,命名为Card

现在效果:在这里插入图片描述

接下来我可以把

.frame(width:200,height:200)

替换成

.frame(width:UIScreen.main.bounds.width / 1.5,height:200)

并且把

.frame(width:100,height: 100)

替换成

.frame(width:UIScreen.main.bounds.width / 3,height: 100)

还有

.frame(width:200)

替换成

.frame(width:UIScreen.main.bounds.width / 1.5)

当然还有更好的方法,但是我们先用这个
在这里插入图片描述

1.2 struct,ScrollView,padding,ForEach和创建列表

现在我们只有一个,那么如果有多个的话,我不想创建多个Card程序,所以我需要把一些值用参数传进来
在Card中

var body: some View{...}

之前,我们添加

var image: String
var text: String
var systemImage: String

然后将两个图像和一个文本用参数代替

struct Card: View {
    var image: String
    var text: String
    var systemImage: String
    var body: some View {
        ZStack {
            Image(image)
                .resizable()
                .frame(width:UIScreen.main.bounds.width / 1.5,height:200)
                .cornerRadius(20)
                .shadow(color: Color.black.opacity(0.4), radius: 30, x: 0, y: 30)
            VStack {
                Text(text)
                    .font(.title)
                    .fontWeight(.bold)
                    .frame(width:UIScreen.main.bounds.width / 1.5)
                    .foregroundColor(.white)
                Image(systemName: systemImage)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(width:UIScreen.main.bounds.width / 3,height: 100)
                    .foregroundColor(.white)
            }
        }
    }
}

然后在调用的地方改成

Card(image: "Monterey", text: "Macos12 Monterey", systemImage: "person.2")

然后在HStack前面加上
ScrollView:滚动视图,
.horizontal:横向滚动,
.showIndicators: false:不显示滚动条
.padding默认给全方位添加默认值填充,第一个参数用于设置填充方向,第二个参数用于设置填充大小

ScrollView(.horizontal ,showsIndicators: false) {

后面补上

   .padding(.horizontal,20)
   .padding(.bottom,80)
}

全选,Ctrl + I调整缩进

在这里插入图片描述

好了,让我们开始创建一个结构体
在这里插入图片描述

然后创建一个列表

var CardViewList = [
    CardList(image: "Monterey", text: "Macos12 Monterey", systemName: "person.3"),
    CardList(image: "BigSur", text: "Macos11 Big Sur", systemName: "person.2"),
    CardList(image: "Catalina", text: "Macos10.15 Catalina", systemName: "person")
]

回到Card中,删掉var image等三个,换成

var cardviewlist: CardList

将以下代码

Image(image)

换成

Image(cardviewlist.image)

将以下代码

Text(text)

换成

Text(cardviewlist.text)

将以下代码

Image(systemName: systemImage)

换成

Image(systemName: cardviewlist.systemName)

到Card(…),Command+单击,选择Repeat
改以下代码

ForEach(0 ..< 5)

ForEach:循环

ForEach(CardViewList.indices,id: \.self)

并将以下代码

Card(image: "Monterey", text: "Macos12 Monterey", systemImage: "person.2")

换成

Card(cardviewlist: CardViewList[index])

然后给HStack加一个间距
现在是

ScrollView(.horizontal ,showsIndicators: false) {
   HStack(spacing:70) {
      ForEach(CardViewList.indices,id: \.self) { index in
         Card(cardviewlist: CardViewList[index])
      }
   }
   .padding(.horizontal,20)
   .padding(.bottom,80)
}

很好
在这里插入图片描述

1.3 GeometryReader

关于UIScreen.main.bounds不是最好的解决方案上文提到过了,如下,当改变了屏幕的宽度或高度时,它不会自动调整请添加图片描述
所以这个时候我们就需要用到GeometryReader了
首先,将HStack嵌入几何阅读器,并添加bounds in请添加图片描述
然后在Card里面添加一个变量

var bounds: GeometryProxy

就可以替换以下代码了

UIScreen.main.bound

换成

bounds.size

并且在调用时添加变量

Card(
   cardviewlist: CardViewList[index],
   bounds: bounds)

完美
请添加图片描述

由于UIScreen是静态的,所以没有办法在变更时对其值进行更改,但GeometryReader是动态的,所以当我们变换布局时,它的值也会变动,因此卡片的大小也就跟着变动了

1.4 list,combine

当我们使用app时,经常会看见列表
请添加图片描述
图片来源于网络

首先要想要实现的话,我们首先要创建列表

创建一个swiftUI类型的文件,命名为MacosList,

然后在创建一个swiftUI类型文件,命名为MacosListStore
进入MacosListStore,删除全部代码,然后粘贴以下代码用于编辑

import SwiftUI
import Combine
class ListStore : ObservableObject {
    @Published var list : [CardList] = CardViewList
}

接着在MacosList中的var body: some View {…}之前加入

@ObservedObject var store = ListStore()
    func addList(){
        store.lists.append(CardList(image: "Monterey", text: "Macos12 Monterey", systemName: "person.3"))
    }

然后var body: some View中加入

GeometryReader { bounds in
   NavigationView{
      List {
          ForEach(store.lists.indices,id: \.self) { index in
              NavigationLink(destination: Card(cardviewlist: store.lists[index], bounds: bounds)) {
                  HStack {
                      Image(store.lists[index].image)
                          .resizable()
                          .aspectRatio(contentMode: .fit)
                          .frame(width: 80, height: 80)
                          .background(Color.black)
                          .cornerRadius(20)
                          .padding(.trailing,4)
                          VStack(alignment: .leading, spacing: 8.0) {
                             Text(store.lists[index].text)
                                .font(.headline)
                                .fontWeight(.bold)
                                .lineLimit(2)
                                .foregroundColor(Color.black)
                             Image(systemName: store.lists[index].systemName)
                                .foregroundColor(.black)
                          }
                        }
                        .padding(.vertical,8)
                     }
                  }
                  .onDelete{ index in
                     self.store.lists.remove(at: index.first!)
                  }
                  .onMove{(source: IndexSet,destination: Int) in
                      self.store.lists.move(fromOffsets: source,
                                            toOffset: destination)
                  }
              }
              .navigationBarTitle(Text("Updates"))
              .navigationBarItems(leading: Button(action: addList) {
                  Text("Add Update")
              } ,trailing: EditButton())
          }
      }

上面的代码由于比较多,所以我就不一一解释了,就是把列表中的静态数据转换成动态数据,然后输出。通过onDelete和onMove来进行移动和删除操作。

另外名字之所以取为MacosList而不去为List,是因为如果取为List的话会报错,因为与List同名

最后回到ContentView,删除<-50的判断,然后在sheet里面换成MacosList

在这里插入图片描述
效果很好

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值