Giter VIP home page Giter VIP logo

learningswiftui's People

Watchers

 avatar  avatar

learningswiftui's Issues

SwiftUI中的数据流工具

SwiftUI中特有的包裹器有:@State, @binding, @ObservedObject及@EnvironmentObject,这些包裹器会声明一个某个视图与这个变量表示的数据之间的依赖。每个不同的包裹器表示不同的数据来源:
@State声明的变量会被其声明的视图所持有;
@binding声明了一种对由其他视图持有的@State var之间的依赖;
@ObservedObject声明了一种对遵守ObservableObject协议的引用类型之间的依赖。ObservableObject协议实现了objectWillChange属性,这个属性会将数据的变更发送出去。
@EnvironmentObject声明了对某些共享数据的依赖,这些数据是对app中的所有视图可获取的。这是一种比较便捷的传输数据的方式。

通常我们不会在可复用的视图中使用@State变量,而是使用@binding或者@ObservedObject。如果某个视图拥有自己的数据的话,那么我们应该创建一个private 类型的@State var

SwiftUI中的状态管理和数据流

SwiftUI几点优势

  1. 声明式:我们声明界面样式,而不是实现界面样式;
  2. 函数式:用同样的状态渲染的话,渲染出来的UI结果也是一样的。换句话说,UI是状态函数
  3. 响应式:当状态发生变更时,SwiftUI会自动更新UI

SwiftUI会管理所有我们声明为state属性的存储。当state的值发生变更时,视图当前的外观会失效并且会对其body进行重新渲染。使用state来作为指定视图的唯一数据来源

@State var number: Int = 1var _number = State<Int>(initialValue: 1)之间的异同
当我们使用@State声明属性时,编译器会自动生成一个State类型的属性_number。

在SwiftUI中,组件并不拥有数据,而是持有存储这个数据的引用。这可以让SwiftUI在数据发生变更时自动更新界面。由于它知道是哪些组件引用了这个model,所以当model发生变更时,它可以计算出是界面的哪部分需要更新。为了达到这一点,它使用了binding,这是一个比较复杂的处理引用的方式。

binding

binding是存储数据的属性和展示及修改数据的视图之间的双向连接。binding并不直接存储数据

唯一的数据来源

唯一数据来源的意思是:数据应该只被单个实体拥有,而其他的实体获取改数据而不是复制该数据。这和引用类型有点相似,所以我们可以将single source of truth看做是拥有附加行为的引用类型。

为了让一个类可以被监听,我们需要让其遵守ObservableObject协议,遵守了这个协议之后,这个类就变成了一个发布者(publisher)。ObservableObject协议只定义了一个objectWillChange属性,并且这个属性是自动合成的。所以我们不需要实现它,编译器会帮我们实现。

通过environment来共享数据

这个模式分为以下两步:

  1. 使用environmentObject(_:)修饰符将对象注入到environment中去;
  2. 使用@EnvironmentObejct 来获取environment中的对象,并将其存储到属性中

当我们将某个对象注入到environment中的时候,它只能被该视图或者该视图的子视图获取到,在它父视图或者层级更高的视图上是无法被获取到的。

当向environment中注入对象时,我们只能注入一个实例,如果注入多个的话,会使用最后那个

创建自定义的environment属性

创建一个自定义的environment属性需要以下两步:

  1. 创建一个遵守EnvironmentKey协议的结构体类型,这个结构体的名称将会作为属性的key
  2. 在EnvironmentValues扩展中添加一个计算属性,这个属性将会以下标的形式来读取或者设置值

SwiftUI中的布局

SwiftUI根据以下几个规则来确定父视图和子视图的大小:

  1. 父视图决定可以使用的frame
  2. 父视图向子视图建议一个尺寸
  3. 基于父视图提供的尺寸,子视图会选择自己的尺寸
  4. 父视图会修改自己的尺寸以至于可以包含子视图

通常来讲,组件总是会尝试将父视图建议的尺寸填充满。如果空间不足以它填充满的话,它将使用适用于该组件类型的规则,并且会严格依赖于这个规则。
它强化了这样一个观念,在SwiftUI中,每个视图选择自己的尺寸。它有限考虑父视图建议的尺寸,并且尽自己所能来对这个尺寸进行适配。但是这取决于视图组件的类型。

到最后我们发现,父视图并不能强制限制子视图的尺寸。父视图能做的就是提供一个大概的尺寸,将子视图的尺寸约束在这个frame中,但是它并不能干预子视图选择一个更大或者更小的尺寸的能力

像Text这类组件,它们会尝试对父视图提供的尺寸进行适配,但是最终渲染文本的尺寸还是肉眼可见的。但是一些其他的组件,像Image,它们会直接忽视这个建议尺寸。

容器视图的布局

对于一个容器视图,也就是包含两个及以上子视图的视图,它决定子视图尺寸的规则如下:

  1. 容器视图根据父视图提供的尺寸来决定它可以处理使用的

SwiftUI中的手势交互

手势结合

SwiftUI为

@GestureState 这个修饰符可以让手势的状态被存储和读取,这样我们可以在视图绘制过程中查看手势可能造成的影响

编写SwiftUI的小技巧

Command+控件,选择Show SwiftUI Inspector,我们可以对文案,字体,颜色等属性进行更改;

如果我们声明的变量和UI视图相关联,那么在声明变量的时候,我们要使用@State。 当一个被@State标记的变量发生变更时,相关视图会失效,并且会对其body进行重新计算.

ForEach的使用
传递的数据的类型需要遵守Identifiable协议,如果没有遵守这个协议的话,ForEach还需要另外一个参数id,这个id是用来标识这个数据在数组中是唯一的。
在Swift5.1中,遵守Identifiable协议的话,需要我们提供一个叫做id的属性,它的类型必须要支持Hashable

SwiftUI 图形绘制的性能问题

默认情况下,SwiftUI使用CoreGraphics来对图表和动画进行渲染。SwiftUI会在需要的时候对屏幕上的每个视图进行单独绘制。在大多数情况下,

Xcode相关快捷键

使用Option+Command+P快捷键可以让我们对SwiftUI视图进行预览

按住Option点击Library(+)可以让Library保持常开

Command+Shift+L 打开Library

Option+Command+ [ 将当前代码向上移动
Option+Command+ ] 将当前代码向下移动

option+点击Live Preview可以切换到Debug preview

Option+Command+return 打开/关闭 canvas界面

在canvas的实时预览视图中,使用command+点击控件,会弹出选项框,其中Show Swift Inspector可以对控件的样式进行修改
或者也可以选中控件,然后使用Option+Command+4会展开属性展示界面
Option+Command+ 左右箭头,即可对代码进行折叠或打开

Modifier-修饰器

修饰器是视图的实例方法,它对视图进行拷贝,并且在拷贝的视图上进行修改,然后将修改后的视图返回.

SwiftUI 提供了两种类型的修饰器:

  1. 修饰器和View protocol绑定在一起,所有的视图都可以使用;
  2. 特定类型才有的修饰器

可以通过查看View的文档来浏览SwiftUI提供的所有修饰器
除此之外,如果我们忘记了某个修饰器的名字或者想要查找某个修饰器是否存在,我们可以在Library-Modifier中查找。

修饰器的效率怎么样?

由于每个修饰器都会返回一个新的视图,所以我们可能会好奇是否这是效率最高的一种方式。每次当我们调用修饰器的时候,SwiftUI会将视图嵌入到一个新的视图中。生成栈视图的过程是一个递归的过程
image

直观上看,这是一种资源的浪费,但实际上,SwiftUI将这个栈扁平化为一个有效的数据结构来用于实际的视图渲染。因此我们可以放开手脚是使用我们需要的修饰器,而不需要担心对视图的渲染造成影响。

修饰器的顺序

实际上,修饰器的调用顺序很重要

如果想要修改图片的尺寸,那么必须要先使用resizable修饰器。只有这个修饰器会改变图片的尺寸,
如果不使用resizable修饰器,图片一直保持它的原始尺寸不变。如果使用修饰器直接或间接改变image的尺寸的话,最终改变的是修饰符作用的视图的尺寸,而不是图片本身,图片还是会保持原始尺寸

有一个容器视图,如果我们想要对其所有的子视图使用一个或多个修饰器,那么直接将这个修饰器作用到这个容器视图上就好。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.