SwiftUI(五)- ForEach循环创建视图&尺寸类&安全区域

引言

SwiftUI为开发者提供了丰富的工具,用于构建灵活而动态的界面布局。在本篇博客中,我们将重点讨论三个核心功能:ForEach的循环视图创建、尺寸类的动态适配,以及安全区域的布局控制。通过ForEach,可以轻松地为数据集合生成视图,适配不同屏幕的尺寸类则允许我们更灵活地调整布局。本篇博客将为大家展开这词儿功能在实际开发中的具体应用,助力SwiftUI项目更加流畅和高效。

ForEach循环创建视图

在实际开发场景中我们经常会需要使用一个循环来创建视图,在SwiftUI中,这个可以通过ForEach来实现。

需要注意的是ForEach虽然看起来和Swift的forEach()方法同名,但是在SwiftUI中ForEach表示的是一个独立的视图结构。我们甚至可以直接从视图中返回它。而在使用时,我们需要为它提供一个数组,并且明确的告诉SwiftUI如何唯一地识别每一个条目,以便让它知道如何更新它们。另外我们需要再闭包中来为每个循环创建一个视图。

循环简单类型数组

对于简单的的范围循环,我们直接将范围传递给ForEach。比如从10倒数到1,然后在最后添加一个文案,实现如下:

Swift 复制代码
        VStack(alignment: .leading) {
            // 循环10-1
            ForEach((1...10).reversed(), id: \.self) {
                Text("\($0)")
            }

            Text("Hello, world!").padding()
        }

对于简单类型的数组,比如整数、字符串、颜色等等,我们都可以通过这种方式遍历(id:\.self),让SwiftUI使用这些值本身作为标识符。

下面我们使用ForEach来循环遍历一个包含3个颜色的数组,并使用每种颜色的名称和颜色来创建文本视图:

Swift 复制代码
            // 循环颜色
            let colors: [Color] = [.red, .green, .blue]
            ForEach(colors, id: \.self) { color in
                Text(color.description.capitalized)
                    .padding()
                    .background(color)
            }

循环自定义类型数组

如果数组中有自定义类型,那么我们就需要主动指定我们自定义类型的中能够唯一标识它的属性,比如有这么一个自定义结构体:

Swift 复制代码
struct Cat {
    
    init(id: UUID = UUID(), name: String) {
        self.id = id
        self.name = name
    }
    /// 标识
    var id = UUID()
    /// 名称
    var name: String = ""
}

该结构体具有一个UUID类型的属性id,那么这就意味着它就是唯一的,非常适合作为标识。如果我们想要循环遍历这样的一个数字,创建一个文本视图显示每个小猫咪的名称放在VStack中,那么我们可以这样来实现:

Swift 复制代码
        // 自定义对象数组
        let cats = [
            Cat(name: "Kitty"),
            Cat(name: "Tom"),
            Cat(name: "Jerry")
        ]
        VStack(alignment: .leading) {
            ForEach(cats, id: \.id) { cat in
                Text(cat.name)
            }
        }

这会告诉SwiftUI可以通过查看每个视图的id属性来区分ForEach内部的视图。

如果我们让Cat结构体遵循Identifiable协议,那我们可以直接使用ForEach。遵循这个协议之后意味着需要添加一个唯一标识每个对象的id属性。但我们已经为它创建了该属性。

Swift 复制代码
struct Cat:Identifiable {
    
    init(id: UUID = UUID(), name: String) {
        self.id = id
        self.name = name
    }
    /// 标识
    var id = UUID()
    /// 名称
    var name: String = ""
}
Swift 复制代码
        // 自定义对象数组
        let cats = [
            Cat(name: "Kitty"),
            Cat(name: "Tom"),
            Cat(name: "Jerry")
        ]
        VStack(alignment: .leading) {
            
            ForEach(cats) { cat in
                Text(cat.name)
            }
        }

尺寸类

SwiftUI提供了对尺寸类别的支持,可以帮助我们根据设备的屏幕尺寸动态调整布局。这是通过读取环境中的尺寸类信息来实现的。在SwiftUI中,尺寸类可以被读取为.horizontalSizeClass和.verticalSizeClass,它们可以用来判断当前视图的宽度或者是高度是紧凑型(compact)还是常规型(regular)。

要使用尺寸类信息,首选需要定义一个@Environment属性,SwiftUI会自动从环境中读取该信息并赋值给它,代码如下:

Swift 复制代码
import SwiftUI

struct ContentView: View {
    // 从环境中读取尺寸类
    @Environment(\.horizontalSizeClass) var horizontalSizeClass
    @Environment(\.verticalSizeClass) var verticalSizeClass

    var body: some View {
        if horizontalSizeClass == .compact {
            Text("紧凑型横向尺寸")
        } else {
            Text("常规型横向尺寸")
        }
    }
}

尺寸类的检测在视频不同屏幕比如iPhone和iPad或者不同设备方向比如横向和竖屏时非常有用。

安全区域

默认情况下,SwiftUI的视图大多会保持在安全区域内,它会延伸到屏幕底部,但不会靠近设备底部的刘海。

如果我们想要实现真正的全屏,那就意味着视图会有一部分内容被刘海或者是灵动岛遮盖起来,那么我们可以使用edgeslgnoringSafeArea()修饰符。

例如我们创建一个红色的文本视图,并要求填满所有可用的空间,然后设置它忽略任何安全区域。

Swift 复制代码
        Text("Hello World")
            .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
            .background(Color.red)
            .edgesIgnoringSafeArea(.all)

结语

在 SwiftUI 中,ForEach 循环、尺寸类适配和安全区域设置为我们提供了更高效的开发方式,使得界面布局的实现变得简单直观。ForEach 的循环视图创建提升了数据驱动视图的构建效率,尺寸类适配帮助我们针对不同屏幕动态调整布局,而安全区域的灵活设置则确保了内容在各设备上的正确展示。掌握这些功能不仅能让我们的代码更简洁,还能增强应用的用户体验。希望这篇文章的讲解能够为你的 SwiftUI 开发之路提供一些有用的启发和帮助!

相关推荐
我有一个object16 小时前
uniapp的IOS证书申请(测试和正式环境)及UDID配置流程
javascript·ios·uni-app·vue
AirDroid_cn17 小时前
iQOO手机怎样将屏幕投射到MacBook?可以同步音频吗?
ios·智能手机·音视频·iphone·ipad·投屏·手机投屏
HH思️️无邪17 小时前
iOS AVAudioSession 详解【音乐播放器的配置】
ios·音频·swift
今天也想MK代码1 天前
基于swiftui 实现3D loading 动画效果
ios·swiftui·swift
pk_xz1234561 天前
Swift 是一种由苹果公司开发的强大而直观的编程语言,主要用于开发 iOS、macOS、watchOS 和 tvOS 等苹果平台的应用程序。
macos·ios·swift
Adam.com1 天前
#Swift The difference between Parameter and Agrument
服务器·ssh·swift
zuguorui1 天前
XCode16中c++头文件找不到解决办法
开发语言·c++·xcode·swift
_可乐无糖1 天前
使用libimobiledevice+ifuse访问iOS沙盒目录
ios
OKXLIN1 天前
ios 项目升级极光SDK
ios·jpush·极光推送
concisedistinct1 天前
在macOS的多任务处理环境中,如何平衡应用的性能与用户体验?这是否是一个复杂的优化问题?如何优化用户体验|多任务处理|用户体验|应用设计
macos·swift