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

相关文章

安卓链接正常显示,ios#符被转义%23导致链接访问404

原因分析: url中含有特殊字符 中文未编码 都有可能导致URL转换失败,所以需要对url编码处理  如下: guard let allowUrl = webUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {return} 后面发现当url中有#号时,会被误伤转义为%23,导致链接无法访问

K8S(Kubernetes)开源的容器编排平台安装步骤详解

K8S(Kubernetes)是一个开源的容器编排平台,用于自动化部署、扩展和管理容器化应用程序。以下是K8S容器编排平台的安装步骤、使用方式及特点的概述: 安装步骤: 安装Docker:K8S需要基于Docker来运行容器化应用程序。首先要在所有节点上安装Docker引擎。 安装Kubernetes Master:在集群中选择一台主机作为Master节点,安装K8S的控制平面组件,如AP

Spring框架5 - 容器的扩展功能 (ApplicationContext)

private static ApplicationContext applicationContext;static {applicationContext = new ClassPathXmlApplicationContext("bean.xml");} BeanFactory的功能扩展类ApplicationContext进行深度的分析。ApplicationConext与 BeanF

数据视图(AngularJS)

<!DOCTYPE html><html ng-app="home.controller"><head><meta charset="utf-8"><title>数据视图</title><link href="page/common/css/bootstrap.min.css" rel="stylesheet"><script src="page/common/js/angular.js"></

容器编排平台Kubernetes简介

目录 什么是K8s 为什么需要K8s 什么是容器(Contianer) K8s能做什么? K8s的架构原理  控制平面(Control plane)         kube-apiserver         etcd         kube-scheduler         kube-controller-manager         cloud-controlle

【iOS】MVC模式

MVC模式 MVC模式MVC模式demo MVC模式 MVC模式全称为model(模型)view(视图)controller(控制器),他分为三个不同的层分别负责不同的职责。 View:该层用于存放视图,该层中我们可以对页面及控件进行布局。Model:模型一般都拥有很好的可复用性,在该层中,我们可以统一管理一些数据。Controlller:该层充当一个CPU的功能,即该应用程序

react笔记 8-18 事件 方法 定义方法 获取/改变数据 传值

1、定义方法并绑定 class News extends React.Component {constructor(props) {super(props)this.state = {msg:'home组件'}}run(){alert("我是一个run") //方法写在类中}render() {return (<div><h2>{this.state.msg}</h2><button onCli

12C 新特性,MOVE DATAFILE 在线移动 包括system, 附带改名 NID ,cdb_data_files视图坏了

ALTER DATABASE MOVE DATAFILE  可以改名 可以move file,全部一个命令。 resue 可以重用,keep好像不生效!!! system照移动不误-------- SQL> select file_name, status, online_status from dba_data_files where tablespace_name='SYSTEM'

漫谈设计模式 [12]:模板方法模式

引导性开场 菜鸟:老大,我最近在做一个项目,遇到了点麻烦。我们有很多相似的操作流程,但每个流程的细节又有些不同。我写了很多重复的代码,感觉很乱。你有啥好办法吗? 老鸟:嗯,听起来你遇到了典型的代码复用和维护问题。你有没有听说过“模板方法模式”? 菜鸟:模板方法模式?没听过。这是什么? 老鸟:简单来说,模板方法模式让你在一个方法中定义一个算法的骨架,而将一些步骤的实现延迟到子类中。这样,你可

漫谈设计模式 [9]:外观模式

引导性开场 菜鸟:老鸟,我最近在做一个项目,感觉代码越来越复杂,我都快看不懂了。尤其是有好几个子系统,它们之间的调用关系让我头疼。 老鸟:复杂的代码确实让人头疼。你有没有考虑过使用设计模式来简化你的代码结构? 菜鸟:设计模式?我听说过一些,但不太了解。你觉得我应该用哪个模式呢? 老鸟:听起来你的问题可能适合用**外观模式(Facade Pattern)**来解决。我们可以一起探讨一下。