【Swift】100 Days of SwiftUI笔记(23-25)

笔记

本篇文章记录一下100 Days of SwiftUI第23-25天的笔记内容

为什么 SwiftUI 使用结构体作为视图?

// 性能因素:结构比类更简单、更快
// 迫使我们考虑以一种干净的方式隔离状态,因为类可以自由更改其值,这可能会导致代码更加混乱
// 如果在视图中使用类,可能会发现的代码无法编译或在运行时崩溃,所以使用结构

SwiftUI 主视图背后是什么?

struct ContentView: View {
    var body: some View {
        Text("Hello, world!")
            .padding()
            .background(.red)
    }
}
// 这样并不能实现整个屏幕为红色,因为Text背后没有任何东西,想要整个屏幕为红色应该让Text占据整个屏幕的空间
Text("Hello, world!")
    .frame(maxWidth: .infinity, maxHeight: .infinity)
    .background(.red)

为什么修饰符顺序很重要?

Button("Hello, world!") {
    // do nothing
}    
.background(.red)
.frame(width: 200, height: 200)
// 以上的代码显示效果并不会看到带有“Hello, world!”的200x200红色按钮,而是看到一个200x200的空方块,上面写着“Hello, world!” 位于中间,并在“Hello, world!”周围有一个红色矩形
// 这是因为:每个修饰符都会应用该修饰符创建一个新结构,而不是仅仅在视图上设置属性
print(type(of: self.body))
// 打印ModifiedContent<ModifiedContent<Button<Text>, _BackgroundStyleModifier<Color>>, _FrameLayout>
// 1.每次我们修改视图时,SwiftUI 都会通过使用泛型来应用该修饰符:ModifiedContent<OurThing, OurModifier>。
// 2.当我们应用多个修饰符时,它们只会叠加:ModifiedContent<ModifiedContent<…
// 3.要读取类型是什么,请从最里面的类型开始并逐步解决,每个类型都需要一个要转换的视图以及要进行的实际更改,而不是直接修改视图,所以首先按钮有一些应用了背景颜色的文本,然后给它一个更大的框架

为什么 SwiftUI 使用“some View”作为其视图类型?

// 1.对性能很重要,SwiftUI 需要能够查看我们显示的视图并了解它们如何变化,以便它可以正确更新用户界面
// 2.因为 SwiftUI 使用ModifiedContent,该View协议有一个关联的类型,所以View它本身没有任何意义,我们需要确切地说出它是什么类型的视图

// VStack是如何工作的?
// 使用VStack时SwiftUI会创建一个TupleView,包含VStack中的视图,TupleView只能处理10个视图,也就是为什么SwiftUI 不允许父级内部有超过 10 个视图的原因

// body中创建视图会做什么处理?
// 与VStack原理相同也是创建一个TupleView包含这些视图,并设置给body的@ViewBuilder这个特殊属性

条件修饰符

// 通常希望修饰符仅在满足特定条件时应用,而在 SwiftUI 中,最简单的方法是使用三元条件运算符
struct ContentView: View {
    @State private var useRedText = false

    var body: some View {
        Button("Hello World") {
            // flip the Boolean between true and false
            useRedText.toggle()            
        }
        .foregroundColor(useRedText ? .red : .blue)
    }
}

环境修饰符

// 许多修饰符可以应用于容器,这允许我们同时将相同的修饰符应用于多个视图
VStack {
    Text("Gryffindor")
        .font(.largeTitle) // 子视图中的修饰符任会替换相同的环境修饰符,Gryffindor会具有大标题
    Text("Hufflepuff")
    Text("Ravenclaw")
    Text("Slytherin")
}
.font(.title)
// 由上述特性可以知道font()是一个环境修饰符

VStack {
    Text("Gryffindor")
        .blur(radius: 0)
    Text("Hufflepuff")
    Text("Ravenclaw")
    Text("Slytherin")
}
.blur(radius: 5)
// 而blur()是一个常规修改器,因此应用于子视图的任何模糊都会添加到VStack模糊中,而不是替换它

视图作为属性

// 有很多方法可以让您更轻松地在 SwiftUI 中使用复杂的视图层次结构,其中一种选择是使用属性 
// 创建一个视图作为您自己视图的属性,然后在布局中使用该属性
struct ContentView: View {
    let motto1 = Text("Draco dormiens")
    let motto2 = Text("nunquam titillandus")

    var body: some View {
        VStack {
            motto1
                .foregroundColor(.red)
            motto2
                .foregroundColor(.blue)
        }
    }
}

// Swift 不允许我们创建一个引用其他存储属性的存储属性,因为这会在创建对象时引起问题
// 这意味着尝试创建TextField与本地属性的绑定将会导致问题
// 但是可以创建计算属性
var motto1: some View {
    Text("Draco dormiens")
}

// 但是与body不用,Swift 不会自动@ViewBuilder在此处应用该属性,因此如果想返回多个视图还需要调整,提供一下3种方式
// 1.将视图放在堆栈中
var spells: some View {
    VStack {
        Text("Lumos")
        Text("Obliviate")
    }
}

// 2.返回一个Group
var spells: some View {
    Group {
        Text("Lumos")
        Text("Obliviate")
    }
}

// 3.自己添加@ViewBuilder属性
@ViewBuilder var spells: some View {
    Text("Lumos")
    Text("Obliviate")
}

视图组成

// SwiftUI 允许我们将复杂的视图分解为更小的视图,而不会产生太大的性能影响
struct ContentView: View {
    var body: some View {
        VStack(spacing: 10) {
            Text("First")
                .font(.largeTitle)
                .padding()
                .foregroundColor(.white)
                .background(.blue)
                .clipShape(Capsule())

            Text("Second")
                .font(.largeTitle)
                .padding()
                .foregroundColor(.white)
                .background(.blue)
                .clipShape(Capsule())
        }
    }
}
// 可以修改为:
struct CapsuleText: View {
    var text: String

    var body: some View {
        Text(text)
            .font(.largeTitle)
            .padding()
            .foregroundColor(.white)
            .background(.blue)
            .clipShape(Capsule())
    }
}

struct ContentView: View {
    var body: some View {
        VStack(spacing: 10) {
            CapsuleText(text: "First")
            CapsuleText(text: "Second")
        }
    }
}

自定义修饰符

// SwiftUI允许创建执行特定操作的自定义修饰符
// 创建一个符合ViewModifier协议的新结构,且必须调用body方法接受要使用的内容,并且必须返回some View
struct Title: ViewModifier {
    func body(content: Content) -> some View {
        content
            .font(.largeTitle)
            .foregroundColor(.white)
            .padding()
            .background(.blue)
            .clipShape(RoundedRectangle(cornerRadius: 10))
    }
}

Text("Hello World")
    .modifier(Title())

// 使用自定义修饰符时,j建议创建View扩展使用
extension View {
    func titleStyle() -> some View {
        modifier(Title())
    }
}

Text("Hello World")
    .titleStyle()

// 自定义修饰符还可以根据需要创建新的视图结构
struct Watermark: ViewModifier {
    var text: String

    func body(content: Content) -> some View {
        ZStack(alignment: .bottomTrailing) {
            content
            Text(text)
                .font(.caption)
                .foregroundColor(.white)
                .padding(5)
                .background(.black)
        }
    }
}

extension View {
    func watermarked(with text: String) -> some View {
        modifier(Watermark(text: text))
    }
}

Color.blue
    .frame(width: 300, height: 200)
    .watermarked(with: "Hacking with Swift")
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容