从用SwiftUI搭建项目说起
前言
后续这个SwiftUI分类的文章全部都是针对SwiftUI的日常学习和理解写的,自己利用Swift写的第二个项目也顺利上线后续的需求也不是特着急,最近正好有空就利用这段时间补一下自己对SwiftUI的理解,这个过程当中正好把整个学习过程记录下来,方便自己查阅,也希望能给需要的同学一点点的帮助。由于自己还欠着RxSwift的帐,这次也是想着先放弃别的账务(欠的的确挺多的)先全心全意的把这两块的帐给补补,希望补上这笔账之后自己对Swift的理解也能上一个台阶,对Siwft的理解自认为还是感觉欠缺的,不算是真的深入的掌握,我对SwiftUI也是在学习当中,现在能查阅的关于SwiftUI的资料很多是需要收费的,遇到问题只能想办法努力解决,有写的不钟意的地方,希望多加指正!

这两张图相信看过苹果官方SwiftUI介绍文档并且跟着写了一遍代码的同学应该不陌生,当然我们的目的不是说这两篇的代码,这个具体的可以到下面连接去查看,我自己跟着写了一遍之后对SwiftUI也是有了一个基本的认识。我们在后面遇到的一些问题也会回到这个官方文档进行一些验证。
SwiftUI
在进入项目搭建先说说我自己对SwiftUI的一个基本的认知:
SwiftUI我觉得对iOSer来说最大的是开发UI模式的优化,针对一个需求或者是一个新的项目我们基本上都是从写UI开始的,根据设计图再编造一些假数据来做,只是在写的过程中它的及时效果也都是脑补!SwiftUI我觉得能改变的痛点就是这点,能让我们实时预览自己写的UI效果,保持我们代码和界面的同步性!
声明式UI:关于它的理解往细了说,的确能专门写一篇文章出来,下面这篇文章能很好的帮助理解我们现在使用的命令式和SwiftUI采用的声明式UI之间的区别。
跨平台: 在最新的swiftUI 5.1中,我们创建一个MultilPlatform App有了下面这些区别:
·Before
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
// Create the SwiftUI view that provides the window contents.
let contentView = BaseTabbarView()
// Use a UIHostingController as window root view controller.
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
window.makeKeyAndVisible()
}
}
·After
import SwiftUI @main
struct MultiPlatformApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
SwiftUI 将整个原有的苹果平台差异部分抽象为 App 和 Scene 部分,可以看到Swift5.1之后在完全无需引入UIKit 的情况下我们就创建了一个多平台的App工程,代码也从原本的基于 UI/NS HostViewController 变成了基于 App的声明式描述。这意味着我们后续在UI布局系统上可以逐渐摆脱对传统命令式 UI 编程的依赖。达到真正的平台无关!
下面开始我们最常见的项目场景的搭建,一点点的学习一下SwiftUI里面的一些知识。
实时预览:
这个画布的显示控制是在下图标注的地方,当然当你创建一个SwiftUIView的时候它是默认创建展示的,要是不见了就在下面去找:

画布的代码控制是在你每个View 的最后面的遵循了PreviewProvider协议的结构体里面的,就像下面我们要说的基本的Tab的预览:
struct BaseTabbarView_Previews: PreviewProvider {
/// 预览视图,你试着在这里多添加两个看看效果呀
static var previews: some View {
BaseTabbarView()
}
}
从最常见的场景搭建开始
在我们的日常开发中,标签(TabBar)+ 导航(Na)形式的模式是随处可见的,我们这次的目的是利用SwiftUI搭建这样一个场景构建一个基本的应用,包括登录和数据处理以及iOS常见控件在SwiftUI中的一些具体的使用,这个项目会随着学习进度慢慢的把所有的内容都基本的补齐,下面是最基本的导航+标签的git效果。

View
我自己觉得,要想从UIKit转换到SwiftUI,需要我们最先转变的概念就是 Controller -> View 的一个改变,在使用SiwftUI写UI的过程中,基本上是不在需要我们向UIkit那样去创建Controller来管理View,在SwiftUI中最常见的就是View。
在UIKit中我们的导航、标签都是通过控制器来管理,但是在SwiftUI中他们分别是通过NavigationView+TabView管理的,我们得在认识上有一个基本的转变,从Controller到View的认识转变。
认识一下NavigationView,先看看下面的代码:
NavigationView{
NavigationLink.init(
destination: Text("Destination"),
label: {
Text("Navigate")
})
.navigationTitle(title)
/// 留意下这个显示模式 displayMode 分三种,具体的可以点进去看看
/// inline 就是我们常见的模式
/// .navigationBarTitle(title,displayMode: .inline)
}
大概解析一下上面代码的 NavigationLink,它是用来控制View之间的跳转的:
destination:是跳转的目标View,我们在做一些数据传递的时候一般都是在这里说明的。
label:对它的理解简单点就是下个View的内容
再认识一下TabView,下面代码是SwiftUI对它的基本定义和描述:
/// A view that switches between multiple child views using interactive user
/// interface elements.
///
/// To create a user interface with tabs, place views in a `TabView` and apply
/// the ``View/tabItem(_:)`` modifier to the contents of each tab. The following
/// creates a tab view with three tabs:
///
/// TabView {
/// Text("The First Tab")
/// .tabItem {
/// Image(systemName: "1.square.fill")
/// Text("First")
/// }
/// Text("Another Tab")
/// .tabItem {
/// Image(systemName: "2.square.fill")
/// Text("Second")
/// }
/// Text("The Last Tab")
/// .tabItem {
/// Image(systemName: "3.square.fill")
/// Text("Third")
/// }
/// }
/// .font(.headline)
///
/// Tab views only support tab items of type ``Text``, ``Image``, or an image
/// followed by text. Passing any other type of view results in a visible but
/// empty tab item.
@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 7.0, *)
public struct TabView<SelectionValue, Content> : View where SelectionValue : Hashable, Content : View { /// Creates an instance that selects from content associated with
/// `Selection` values.
public init(selection: Binding<SelectionValue>?, @ViewBuilder content: () -> Content) /// The content and behavior of the view.
public var body: some View { get } /// The type of view representing the body of this view.
///
/// When you create a custom view, Swift infers this type from your
/// implementation of the required `body` property.
public typealias Body = some View
}
关于这个TabView在定义的上面苹果是给出了一个使用的基本的示例的,要和我们项目中经常使用的模式要绑定在一起的的话就是结合他的初始化方法绑定一个@State变量使用的,具体的我们会在后面的代码中说的,关于这个@State我在项目Demo中有具体的解释,包括像@bind类型或者是@EnvironmentObject这些关键字我们肯定是得需要学习的,就像我们从OC转到Swift一样。
简单看看Na+Tb的代码
从SceneDelegate开始, 根控制器就是 UIHostingController,我们需要做的第一步就是设置它的根视图 rootView
// Create the SwiftUI view that provides the window contents.
let contentView = BaseTabbarView() // Use a UIHostingController as window root view controller.
if let windowScene = scene as? UIWindowScene { let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
window.makeKeyAndVisible()
}
接下来是TabView的代码,需要注意的是我们点击item的时候视图切换的绑定状态,基本上在代码注释中我说的比较清楚了,应该能理解的。
import SwiftUI
struct BaseTabbarView: View {
/// 理解State这个属性 https://www.cnblogs.com/xiaoniuzai/p/11417123.html
/*
通过使用 @State 修饰器我们可以关联出 View 的状态. SwiftUI 将会把使用过 @State 修饰器的属性存储到一个特殊的内存区域,并且这个区域和 View struct 是隔离的. 当 @State 装饰过的属性发生了变化,SwiftUI 会根据新的属性值重新创建视图
*/
@State private var selectedTab = 0
var body: some View {
/// public init(selection: Binding<SelectionValue>?, @ViewBuilder content: () -> Content)
TabView(selection: $selectedTab){
HomeView(title: "首页")
.tabItem {
Image(selectedTab == 0 ? "icon_home_selected" : "icon_home")
Text("首页")
}
.onTapGesture {
selectedTab = 0
}
.tag(0)
ServiceView(title: "周边")
.tabItem {
Image(selectedTab == 1 ? "icon_around_selected" : "icon_around")
Text("周边")
}
.onTapGesture {
selectedTab = 1
}
.tag(1)
AroundView(title: "服务")
.tabItem {
Image(selectedTab == 2 ? "icon_service_selected" : "icon_service")
Text("服务")
}
.onTapGesture {
selectedTab = 2
}
.tag(2)
MineView(title: "我的").environmentObject(NavigationAction())
.tabItem {
Image(selectedTab == 3 ? "icon_mine_selected" : "icon_mine")
Text("我的")
}
.onTapGesture {
selectedTab = 3
}
.tag(3)
/// 这个着重颜色设置可以设置tabbaritem字体的颜色
}.accentColor(.blue)
}
}
struct BaseTabbarView_Previews: PreviewProvider {
/// 预览视图,你试着在这里多添加两个看看效果呀
static var previews: some View {
BaseTabbarView()
}
}
在上面的代码中,点击的切换我们是通过View的onTapGesture方法通过改变selectedTab 来进行控制的,然后item具体是要显示那种风格的图片也是通过selectedTab经过三目运算符控制,具体得我们这里不多解释了废话了,看代码我相信都能理解。
下面的参考文章相信能帮助我们更好的理解一下,SwiftUI!
参考文章:
从用SwiftUI搭建项目说起的更多相关文章
- ASP.NET MVC搭建项目后台UI框架—1、后台主框架
目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...
- ASP.NET MVC搭建项目后台UI框架—11、自动加载下拉框查询
ASP.NET MVC搭建项目后台UI框架—1.后台主框架 需求:在查询记录的时候,输入第一个字,就自动把以这个字开头的相关记录查找出来,输入2个字就过滤以这两个子开头的记录,依次类推. 突然要用到这 ...
- ASP.NET MVC搭建项目后台UI框架—2、菜单特效
目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...
- ASP.NET MVC搭建项目后台UI框架—3、面板折叠和展开
目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...
- ASP.NET MVC搭建项目后台UI框架—4、tab多页签支持
目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...
- ASP.NET MVC搭建项目后台UI框架—5、Demo演示Controller和View的交互
目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...
- ASP.NET MVC搭建项目后台UI框架—6、客户管理(添加、修改、查询、分页)
目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...
- ASP.NET MVC搭建项目后台UI框架—7、统计报表
ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NET M ...
- ASP.NET MVC搭建项目后台UI框架—8、将View中选择的数据行中的部分数据传入到Controller中
目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...
随机推荐
- python + selenium 搭建环境步骤
介绍在windows下,selenium python的安装以及配置.1.首先要下载必要的安装工具. 下载python,我安装的python3.0版本,根据你自己的需要安装 下载setuptools ...
- Django启动服务的流程
我晕,启动个服务浪费快一个小时的时间,记录下步骤吧. 1.D:\django\newworld>python manage.py runserver Performing system chec ...
- 说说基于网络的五种IO模型
# django不是一个异步框架 # tornado是异步的web框架 # 处理每秒大量的请求 # 个人理解的IO:就是应用层与内核驱动层的交互,这个过程无论从应用层到内核中,还是驱动层等待硬件层的数 ...
- 【开源】.net微服务开发引擎Anno开源啦
1.Anno是什么? Anno是一个微服务框架引擎.入门简单.安全.稳定.高可用.全平台可监控.依赖第三方框架少.底层通讯RPC(Remote Procedure Call)采用稳定可靠经过无数成功项 ...
- ISITDTU CTF 2020 部分Web题目Writeup
周末,跟着m3w师傅打ISITDTUCTF,m3w师傅带弟弟上分,Tql! Web1 给了源码: <?php class Read{ public $flag; public function ...
- vue中使用transition和animate.css动画效果
一.单个动画中,使用div中引用animate动画 1.下载依赖 npm install animate.css –save 2.main.js中全局引用 import animate from 'a ...
- MathType可以和哪些Microsoft Office版本一起使用?
Office类软件可能是我们碰到电脑后,最先接触到的电脑软件了.尤记得,当初的微机课一开始就会讲word和excel的使用,一开始可能学不太明白,但后来越来越频繁的使用office软件,不说offic ...
- Win搭建JAVA环境
一:下载JDK 下载链接:https://www.oracle.com/java/technologies/javase-downloads.html 选择你的系统环境进行下载 二:安装JDK 直接运 ...
- Grakn Forces 2020 ABCDE题解
看到老外评论区中说,这场的难度估计是\(div.1\)和\(div.1.5\)的合并 A. Circle Coloring #构造 题目链接 题意 给定三个长度为\(n\)数组\(a,b,c\),要你 ...
- Gin + 七牛云对象存储
配置七牛云存储 创建存储空间 拿到密钥 安装七牛云对象存储SDK 推荐go.mod安装 // 将下面地址复制到go.mod,然后执行go mod download github.com/qiniu/a ...