前言


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

           

这两张图相信看过苹果官方SwiftUI介绍文档并且跟着写了一遍代码的同学应该不陌生,当然我们的目的不是说这两篇的代码,这个具体的可以到下面连接去查看,我自己跟着写了一遍之后对SwiftUI也是有了一个基本的认识。我们在后面遇到的一些问题也会回到这个官方文档进行一些验证。

Apple SwiftUI

SwiftUI


在进入项目搭建先说说我自己对SwiftUI的一个基本的认知:

SwiftUI我觉得对iOSer来说最大的是开发UI模式的优化,针对一个需求或者是一个新的项目我们基本上都是从写UI开始的,根据设计图再编造一些假数据来做,只是在写的过程中它的及时效果也都是脑补!SwiftUI我觉得能改变的痛点就是这点,能让我们实时预览自己写的UI效果,保持我们代码和界面的同步性!

声明式UI:关于它的理解往细了说,的确能专门写一篇文章出来,下面这篇文章能很好的帮助理解我们现在使用的命令式和SwiftUI采用的声明式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!

参考文章:

Apple SwiftUI

从 SwiftUI 谈声明式 UI 与类型系统

如何评价 SwiftUI?

项目地址

从用SwiftUI搭建项目说起的更多相关文章

  1. ASP.NET MVC搭建项目后台UI框架—1、后台主框架

    目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...

  2. ASP.NET MVC搭建项目后台UI框架—11、自动加载下拉框查询

    ASP.NET MVC搭建项目后台UI框架—1.后台主框架 需求:在查询记录的时候,输入第一个字,就自动把以这个字开头的相关记录查找出来,输入2个字就过滤以这两个子开头的记录,依次类推. 突然要用到这 ...

  3. ASP.NET MVC搭建项目后台UI框架—2、菜单特效

    目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...

  4. ASP.NET MVC搭建项目后台UI框架—3、面板折叠和展开

    目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...

  5. ASP.NET MVC搭建项目后台UI框架—4、tab多页签支持

    目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...

  6. 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 ...

  7. ASP.NET MVC搭建项目后台UI框架—6、客户管理(添加、修改、查询、分页)

    目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...

  8. ASP.NET MVC搭建项目后台UI框架—7、统计报表

    ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NET M ...

  9. ASP.NET MVC搭建项目后台UI框架—8、将View中选择的数据行中的部分数据传入到Controller中

    目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...

随机推荐

  1. 练习启动各种浏览器的同时加载插件:Firefox, Chrome, IE

    # -*- coding:utf-8 -*-import osimport seleniumfrom selenium import webdriverfrom selenium.webdriver. ...

  2. Math.floor(Math.random() * array.length),splice

    1.Math.floor(Math.random() * array.length) 返回长度内的索引 eg: changeLimit () { function getArrayItems(arr, ...

  3. [转载]Redis 持久化之RDB和AOF

    原文链接:https://www.cnblogs.com/itdragon/p/7906481.html 温馨提示 在正式数据(当然是非生产环境啦)练习以下操作时,一定一定一定记得备份dump.rdb ...

  4. Druid配置和初始化参数 转发地址图片有

    配置数据源 1.添加上 Druid 数据源依赖. <!-- https://mvnrepository.com/artifact/com.alibaba/druid --> <dep ...

  5. 如何使用iMazing编辑iOS设备的备份

    乍一看,编辑iPhone或iPad的备份似乎是一个奇怪的命题,但实际上这样做的原因有很多,例如在备份数据损坏时进行修复,又如合并来自不同设备的数据. iMazing对备份文件编辑的支持非常全面,即使备 ...

  6. 怎么用MindManager制作议论文思维导图

    大家都写过作文吧,做小学到高考到大学,这是谁也摆脱不了的,但是大家写作文会提前把自己的思路整理出来吗?让自己行文更为顺畅,作文更为流利吗?特别是关于议论文,一直是高考写作的一个重点篇目,写好议论文,就 ...

  7. FL studio系列教程(一):什么是FL水果音乐制作软件

    如今,越来越多的音乐人选择使用音乐制作软件来进行音乐的创作,一台电脑.一款软件以及一个外接MIDI就是一个小型的音乐工作站.FL Studio成了音乐界萌新的首选,目前最新的版本为FL Studio2 ...

  8. P2887 [USACO07NOV]Sunscreen G

    将奶牛按照能忍受的阳光强度最大值从小到大排序.对于当前这头奶牛,选取它能抹的最小防晒霜.因为越大的防晒霜后面的奶牛越可能利用,并且抹显然不劣于不抹. 时间复杂度 \(O\left(C\log C+L\ ...

  9. 【抓取】6-DOF GraspNet 论文解读

    [抓取]6-DOF GraspNet 论文解读 [注]:本文地址:[抓取]6-DOF GraspNet 论文解读 若转载请于明显处标明出处. 前言 这篇关于生成抓取姿态的论文出自英伟达.我在读完该篇论 ...

  10. 帆软用工具测试超链接打开弹窗(iframe嵌套),解决js传参带中文传递有乱码问题

    1.新建超链接 随意点击一个单元格右击,选择 超级链接 2.在弹出的窗口中选择JavaScript脚本 如图: 其中红框框出的是几个要点   ,左边的就不讲了,右上角的参数cc是设置了公式remote ...