SwiftUI 6.0(iOS 18)新容器视图修改器漫谈

2024-06-16 23:36

本文主要是介绍SwiftUI 6.0(iOS 18)新容器视图修改器漫谈,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在这里插入图片描述

概览

本届 WWDC 2024 观影正如火如荼的进行中,一片鸟语花香、枝繁叶茂的苹果树上不时结出几颗令人垂涎欲滴的美味苹果让秃头码农们欲罢不能。

在这里插入图片描述

如您所愿,在界面布局“利器” SwiftUI 这根蔓藤也长出不少喜人的果实,其中在 iOS 18.0 中新添加的容器视图修改器大家一定不能错过。

在本篇博文中,您将学到如下内容:

  • 概览
  • 1. 探囊取物:获取容器子视图
  • 2. 聚沙成塔:重新组织容器子视图
  • 总结

SwiftUI 6.0 新容器视图修改器让我们得以分解原本“铁板一块”的“黑箱”视图,打开无限可能。

无需等待,让我们马上开始探寻之旅吧!

Let’s go!!!😉


本文对应的视频课在此,欢迎小伙伴们恣意观赏

SwiftUI 6.0(iOS 18)新容器视图修改器漫谈


1. 探囊取物:获取容器子视图

在 SwiftUI 6.0(iOS 18)之前,如果我们希望让自定义容器视图处理布局排版的细节则需要知道数据集,并根据数据集中每个单独元素构建对应的容器子视图:

import SwiftUIstruct MyContainerView<Content: View>: View {var items: [Int]@ViewBuilder var itemView: (Int) -> Contentvar body: some View {List {ForEach(items, id: \.self) { item initemView(item)}}}
}struct ContentView: View {var body: some View {MyContainerView(items: Array(1...10)) { item inText("Item \(item)").font(.title).padding()}}
}

如上代码所示,我们将容器数据集合 items 和单个数据对应的子视图闭包 itemView() 从父视图传入到了 MyContainerView 中。

在这里插入图片描述

不过在某些情况下,我们希望在父视图中更灵活的创建容器子视图,比如以静态与动态相结合的方式:

struct ContentView: View {var body: some View {MyContainerView {Text("Item Header")Text("Item Subheader")ForEach(1...10, id: \.self) { item inText("Item \(item)")}Text("Item Tail")}}
}

如上代码所示,我们试图将 3 个静态和 10 个动态产生的子视图和睦融洽的一起融入到容器视图 MyContainerView 中。但不幸的是,这在 SwiftUI 6.0 之前几乎是不可能完成的任务。


当然,如果我们巧妙运用一些 Swift Mirror “黑魔法”的话也不是绝对不可能。想要进一步了解 Mirror 黑魔法解决之道的小伙伴们,请移步如下链接观赏精彩的内容:

  • SwiftUI 打造一款收缩自如的 HStack(三):“魔镜魔镜,我爱你”

究其原因则是因为:在 SwiftUI 6.0 之前我们无法探查一个 View 的内部结构,它对我们来说就是一个彻头彻尾的“黑盒”视图。

不过从 SwiftUI 6.0(iOS 18)开始情况有了改观,苹果新增了若干容器视图修改器为我们排愁解忧。其中 ForEach(subviewOf:) 修改器方法就是这里我们所需要的那个“救世主”。

在这里插入图片描述

利用 ForEach(subviewOf:) 方法我们可以将 MyContainerView 容器视图修改为如下模样:

struct MyContainerView<Content: View>: View {@ViewBuilder var content: Contentvar body: some View {List {ForEach(subviewOf: content) {subview insubview.padding().frame(maxWidth: .infinity).background(.green.gradient)}}}
}

从上面修改后的代码中可以看到:现在我们只需专注于子视图本身,而无需再操心对应的子元素 Item 了。

在这里插入图片描述

除了 ForEach(subviewOf:) 以外,SwiftUI 6.0 还新增了一个类似的 ForEach(sectionOf: ) 修改器方法,如果小伙伴们希望自己的容器支持 Section 布局则会寻求它的鼎力相助哦。

2. 聚沙成塔:重新组织容器子视图

在聊完了将一整块黑盒视图从布局上分解为各个独立的子视图后,我们再来看看容器视图的另一种操作:将容器子视图重新“恣意”组合在一起。

假如我们希望自己的容器视图能够进一步根据子视图的数量或其它特定条件来布局界面,那么新的 Group(subviewsOf:) 修改器你绝对不能错过:

在这里插入图片描述

Group(subviewsOf: content) 方法让我们可以从整个容器的所有子视图而不是单个子视图来考虑布局大计:

struct HyListView<Content: View>: View {@ViewBuilder var content: Contentvar body: some View {VStack {Group(subviewsOf: content) { subviews inif subviews.isEmpty {Text("🐼No\nContent").font(.system(size: 100)).padding()} else {if let first = subviews.first {first.font(.largeTitle.weight(.heavy)).background(Circle().foregroundStyle(.blue.gradient).frame(width: 150, height: 150))}if subviews.count >= 3 {HStack {subviews[1]subviews[2]}.font(.title).foregroundStyle(.white).padding().background(.green)if subviews.count > 3 {List {subviews[3...].frame(maxWidth: .infinity).padding().background(.yellow.gradient)}.listStyle(.plain).font(.title3.weight(.black)).foregroundStyle(.red).padding()}}}}.transition(.slide)}}
}struct ContentView: View {@State var count = 10.0var items: [Int] {if count == 0 {[]} else {Array(0...Int(count))}}var body: some View {VStack {HyListView {ForEach(items, id: \.self) { i inText("Item \(i)")}}.animation(.bouncy, value: count)Spacer()HStack {Text("\(Int(count))").fontWeight(.heavy)Slider(value: $count, in: 0...20.0, label: {}, minimumValueLabel: {Text("0")}, maximumValueLabel: {Text("20")}).foregroundStyle(.gray)}.padding()}}
}

在上面代码中,我们创建了自己的 HyListView 容器视图,并且根据实际子视图的数量利用 Group(subviewsOf: content) 修改器方法来决定到底如何将它们“浑然天成”的组合在一起。

在这里插入图片描述

从实际运行效果可以看到,我们动态的根据容器内部的子视图来决定到底如何布局容器本身,再辅以动画整个效果简直 Nice 的不要不要的:

在这里插入图片描述

现在小伙伴们手握 SwiftUI 6.0 中新的容器视图修改“利器”,在 App 的开发中是不是愈发感觉神采奕奕、容光焕发了呢?棒棒哒!

总结

在本篇博文中,我们讨论了 WWDC24 里 SwiftUI 6.0(iOS 18)中最新的容器视图修改器,并用简单的示例代码让小伙伴们豁然开朗!

感谢观赏,再会!😎

这篇关于SwiftUI 6.0(iOS 18)新容器视图修改器漫谈的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1067868

相关文章

LeetCode11. 盛最多水的容器题解

LeetCode11. 盛最多水的容器题解 题目链接: https://leetcode.cn/problems/container-with-most-water 示例 思路 暴力解法 定住一个柱子不动,然后用其他柱子与其围住面积,取最大值。 代码如下: public int maxArea1(int[] height) {int n = height.length;int

iOS HTTPS证书不受信任解决办法

之前开发App的时候服务端使用的是自签名的证书,导致iOS开发过程中调用HTTPS接口时,证书不被信任 - (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAu

亮相WOT全球技术创新大会,揭秘火山引擎边缘容器技术在泛CDN场景的应用与实践

2024年6月21日-22日,51CTO“WOT全球技术创新大会2024”在北京举办。火山引擎边缘计算架构师李志明受邀参与,以“边缘容器技术在泛CDN场景的应用和实践”为主题,与多位行业资深专家,共同探讨泛CDN行业技术架构以及云原生与边缘计算的发展和展望。 火山引擎边缘计算架构师李志明表示:为更好地解决传统泛CDN类业务运行中的问题,火山引擎边缘容器团队参考行业做法,结合实践经验,打造火山

MySQL数据库(四):视图和索引

在数据库管理中,视图和索引是两种关键工具,它们各自发挥独特的作用以优化数据查询和管理。视图通过简化复杂查询、提高数据安全性和提供数据抽象,帮助用户轻松访问数据。而索引则通过加速查询、确保数据唯一性以及优化排序和分组操作,显著提升数据库性能。理解和合理运用这两者,对数据库系统的高效运行至关重要。 目录 一、视图概念(面试) 二、视图的作用(面试) 三、视图的创建和使用 3.1

IOS 数组去重的几种方式

本来只知道NSSet和KeyValues的。今天又新学了几种方式 还有就是和同事学的一种方式 外层循环从0开始遍历,内层从最后一个元素开始遍历 for(int i=0;i<index;i++){  for(int j=index-1;j>i;j-- ){ } }

iOS Assertion failure in -[UITableView _classicHeightForRowAtIndexPath:]

iOS Assertion failure in -[UITableView _classicHeightForRowAtIndexPath:]  2015-04-24 11:40  956人阅读  评论(0)  收藏  举报   分类:   iOS 基础篇(208)  版权声明:本文为博主原创文章,未经博主允许不得转载。 Assertion

iOS:编译时出现no such file or directory:xxx以及use twice...filenames are used to distinguish private dec

简    注册  登录   添加关注 作者  婉卿容若 2016.04.29 11:22 写了21870字,被16人关注,获得了14个喜欢 iOS:编译时出现"no such file or directory:xxx"以及"use twice...filenames are used to distinguish private

iOS 到处 ipa包的时候 会有四个选项分别代表什么

如图 在 iOS 到处 ipa包的时候 会有四个选项  1.Save for iOS App Store Deployment 保存到本地 准备上传App Store 或者在越狱的iOS设备上使用 2.Save for Ad Hoc Deployment 保存到本地 准备在账号添加的可使用设备上使用(具体为在开发者账户下添加可用设备的udid),该app包是发布证书编

iOS 7适配上存在的各种问题

谈谈项目中遇到的各种iOS7适配问题 由于我的项目要适配到iOS7.1, 而现在已经是9时代了,在实际工作中我也是遇到了各种奇葩的坑,所以我想尽快把遇到的iOS7适配问题和解决方案分享出来,以后这些东西可能就用处不大了。   1.字体问题 iOS7中的字体适配恐怕是最麻烦的坑了,原因是iOS7以上的许多字体在7都是不存在的,甚至包括一些system-字体。比如system-

一二三应用开发平台应用开发示例(4)——视图类型介绍以及新增、修改、查看视图配置

调整上级属性类型 前面为了快速展示平台的低代码配置功能,将实体文件夹的数据模型上级属性的数据类型暂时配置为文本类型,现在我们调整下,将其数据类型调整为实体,如下图所示: 数据类型需要选择实体,并在实体选择框中选择自身“文件夹” 这时候,再点击生成代码,平台会报错,提示“实体【文件夹】未设置主参照视图”。这是因为文件夹选择的功能页面,同样是基于配置产生的,因为视图我们还没有配置,所以会报错。