SwiftUI极简教程06:代码优雅复用

简介: SwiftUI极简教程06:代码优雅复用

在本章中,你将学会如何处理可以复用的代码块。

在定价方案视图中,可以看到3个定价方案的样式还有代码是极其相似的。

image.png


和设计的逻辑一样,代码的逻辑也是是“复制”第一个定价方案的视图的代码,然后再修改颜色、字体、或者加多一些文字。

但他们的主体结构是一样的。

那么我们是不是可以只需要写一次代码,然后把文字什么的再复用重定义。

这样可以大大减少代码量,且代码阅读起来更加清晰,做到“优雅写代码”的目的。


//定价方案子视图
struct pricingView: View {
    var body: some View {
        HStack {
            // 连续包月
            ZStack {
                VStack {
                    Text("连续包月")
                        .fontWeight(.bold)
                        .font(.system(size: 17))
                        .foregroundColor(Color(red: 190 / 255, green: 188 / 255, blue: 184 / 255))
                    Text("¥18")
                        .fontWeight(.bold)
                        .font(.system(size: 30))
                        .foregroundColor(Color(red: 239 / 255, green: 129 / 255, blue: 112 / 255))
                }
                .frame(minWidth: 0, maxWidth: .infinity, minHeight: 90)
                .padding(20)
                .background(Color("faf7f3"))
                .overlay(RoundedRectangle(cornerRadius: 6)
                            .stroke(Color(red: 202 / 255, green: 169 / 255, blue: 106 / 255), lineWidth: 2))
                // 首月特惠
                Text("首月特惠")
                    .font(.system(size: 14))
                    .fontWeight(.bold)
                    .foregroundColor(.white)
                    .padding(5)
                    .background(Color(red: 202 / 255, green: 169 / 255, blue: 106 / 255))
                    .cornerRadius(4)
                    .offset(x: 0, y: -65)
            }
            // 1个月
            VStack {
                Text("1个月")
                    .fontWeight(.bold)
                    .font(.system(size: 17))
                    .foregroundColor(Color(red: 190 / 255, green: 188 / 255, blue: 184 / 255))
                Text("¥30")
                    .fontWeight(.bold)
                    .font(.system(size: 30))
                    .foregroundColor(Color(red: 239 / 255, green: 129 / 255, blue: 112 / 255))
            }
            .frame(minWidth: 0, maxWidth: .infinity, minHeight: 90)
            .padding(20)
            .background(Color(red: 244 / 255, green: 244 / 255, blue: 245 / 255))
            .cornerRadius(10)
            // 12个月
            VStack {
                Text("12个月")
                    .fontWeight(.bold)
                    .font(.system(size: 17))
                    .foregroundColor(Color(red: 190 / 255, green: 188 / 255, blue: 184 / 255)
                Text("¥228")
                    .fontWeight(.bold)
                    .font(.system(size: 30))
                    .foregroundColor(Color(red: 239 / 255, green: 129 / 255, blue: 112 / 255))
                Text("¥19.00/月")
                    .fontWeight(.bold)
                    .font(.system(size: 17))
                    .foregroundColor(Color(red: 190 / 255, green: 188 / 255, blue: 184 / 255))
            }
            .frame(minWidth: 0, maxWidth: .infinity, minHeight: 90)
            .padding(20)
            .background(Color(red: 244 / 255, green: 244 / 255, blue: 245 / 255))
            .cornerRadius(10)
        } // HStack结束位置
        .padding(.horizontal)
    }
}
复制代码


说干就干!

首先分析下代码的相同点。

Text()下,设置字重、字体、字体颜色,在整个VStack包裹下,设置尺寸、边距、背景颜色、边框圆角。

我们发现,除了定价方案的标题不同(连续包月、1个月、12个月)、不同定价方案的价格不同(¥18、¥30、¥228)、背景颜色不同,其他都一样。

既然这些都可以复用,那么我们可以将可以复用的参数脱离出来。

先定义一个变量,再在代码中设定不同的变量值,就可以达到全部复用的效果。

先定一个标准的定价方案,定义了一个title变量,它是字符串类型,定义了一个价格变量,也是字符串类型,定一个一个背景颜色,它是颜色类型。

然后将定义的变量换到下面的代码中。


//定价方案
struct pricingView: View {
//定义变量
var title: String
var price: String
var bgColor: Color
var body: some View {
    VStack {
        Text(title)    //定义的titie
            .fontWeight(.bold)
            .font(.system(size: 17))
            .foregroundColor(Color(red: 190 / 255, green: 188 / 255, blue: 184 / 255))
        Text(price)    //定义的price
            .fontWeight(.bold)
            .font(.system(size: 30))
            .foregroundColor(Color(red: 239 / 255, green: 129 / 255, blue: 112 / 255))
        }
        .frame(minWidth: 0, maxWidth: .infinity, minHeight: 90)
        .padding(20)
        .background(bgColor)    //定义的背景颜色
    }
复制代码


定义完变量后,我们可以看到系统报错了,不用担心。

这因为我们pricingView子视图中定义了3个变量,但在主视图引用的时候,主视图不知道这3个变量是什么值,只知道它的类型。

所以系统提醒我们需要加上具体的值。

我们可以点击“Fix”,Xcode会自动帮我们加上缺少的值。


image.png

“Fix”后,Xcode将缺少的变量补充了进来。

这时候,我们需要给变量赋予真实的值。

示例:title赋予"连续包月”,price赋予"¥18”,bgColor赋予Color("faf7f3”)。

image.png

// 定价方案
pricingView(title: "连续包月", price: "¥18", bgColor: Color("faf7f3"))

image.png


很好,我们已经创建好了1个定价方案了!

像UI稿一样,我们需要3个定价方案,由于我们已经拆离开可以复用的代码了,那么我们只需要在主视图复制就行了,而无需再额外复制一大段代码。


// 定价方案
    //连续包月
    pricingView(title: "连续包月", price: "¥18", bgColor: Color("faf7f3"))
    //1个月
    pricingView(title: "1个月", price: "¥30", bgColor: Color(red: 244 / 255, green: 244 / 255, blue: 245 / 255))
    //12个月
    pricingView(title: "12个月", price: "¥228", bgColor: Color(red: 244 / 255, green: 2


image.png

由于在主视图中,我们的标题和定价方案是放在一个VStack里面的,而3个定价方案需要横向分布,也就是使用HStack。

那我们只需要在主视图中将3个定价方案放在一个HStack中,这样它们就能横向排列了。

// 定价方案
HStack {
    //连续包月
    pricingView(title: "连续包月", price: "¥18", bgColor: Color("faf7f3"))
    //1个月
    pricingView(title: "1个月", price: "¥30", bgColor: Color(red: 244 / 255, green: 244 / 255, blue: 245 / 255))
    //12个月
    pricingView(title: "12个月", price: "¥228", bgColor: Color(red: 244 / 255, green: 244 / 255, blue: 245 / 255))
}


image.png

下一步,我们修订下样式,我们可以看到第一个定价方案是有圆角边框的,其他两个定价方案是有圆角的。

那么我们需要单独为第一个定价方案加圆角边框,其他两个定价方案加圆角。

image.png

// 定价方案
HStack {
    //连续包月
    pricingView(title: "连续包月", price: "¥18", bgColor: Color("faf7f3”))
        .overlay(RoundedRectangle(cornerRadius: 6).stroke(Color(red: 202 / 255, green: 169 / 255, blue: 106 / 255), lineWidth: 2))
    //1个月
    pricingView(title: "1个月", price: "¥30", bgColor: Color(red: 244 / 255, green: 244 / 255, blue: 245 / 255))
        .cornerRadius(10)
    //12个月
    pricingView(title: "12个月", price: "¥228", bgColor: Color(red: 244 / 255, green: 244 / 255, blue: 245 / 255))
        .cornerRadius(10)
}

image.png

下一步,我们看到UI稿中,第一个定价有【首月特惠】的标识,其他两个定价方案是没有的。

那么我们需要再给第一个定价方案用ZStack包裹,然后再里面添加一个【首月特惠】的标识。

image.png

//连续包月
ZStack {
    // 连续包月
    pricingView(title: "连续包月", price: "¥18", bgColor: Color("faf7f3"))
        .overlay(RoundedRectangle(cornerRadius: 6).stroke(Color(red: 202 / 255, green: 169 / 255, blue: 106 / 255), lineWidth: 2))
    // 首月特惠
    Text("首月特惠")
        .font(.system(size: 14))
        .fontWeight(.bold)
        .foregroundColor(.white)
        .padding(5)
        .background(Color(red: 202 / 255, green: 169 / 255, blue: 106 / 255))
        .cornerRadius(4)
        .offset(x: 0, y: -65)
    }

image.png

这时候,我们会发现样式基本okay了。

但有个问题,主视图的代码好像太多了,不够优雅。

结合上一章所学的代码分组管理,我们可以把【首月特惠】单独抽离出来成为一个子视图。

鼠标移动到ZStack定价方案里的Text()视图,按住command键,点击选择Text()视图,选择Extract SubView。


image.png

image.png


在得到新的子视图后,我们依旧需要重命名。

我们把首月特惠的ExtractedView更名为specialOfferView。

鼠标定位到原来没有命名的ExtractedView位置,点击鼠标右键,选择Refactor,选择Rename。

image.png

image.png

很好!代码优雅多了!

image.png

然后,我们再给HStack加个.padding。

image.png

你以为完成了吗?并不!

我们看到第三个定价方案还有1个Text(“¥19.00/月”),而其他定价方案没有。

image.png

先思考下怎么做。

在pricingView里加一个Text()?先试试吧。

和之前一样,我们定一个perPrice变量,它是String类型。

然后在pricingView中加上Text(perPrice)的代码。


//定价方案子视图
struct pricingView: View {
    // 定义变量
    var title: String
    var price: String
    var perPrice: String
    var bgColor: Color
    var body: some View {
        VStack {
            Text(title)
                .fontWeight(.bold)
                .font(.system(size: 17))
                .foregroundColor(Color(red: 190 / 255, green: 188 / 255, blue: 184 / 255))
            Text(price)
                .fontWeight(.bold)
                .font(.system(size: 30))
                .foregroundColor(Color(red: 239 / 255, green: 129 / 255, blue: 112 / 255))
            Text(perPrice)
                .fontWeight(.bold)
                .font(.system(size: 17))
                .foregroundColor(Color(red: 190 / 255, green: 188 / 255, blue: 184 / 255))
        }
        .frame(minWidth: 0, maxWidth: .infinity, minHeight: 90)
        .padding(20)
        .background(bgColor)
    }
}


image.png


再回到主视图中,补充缺失的变量。

点击“Fix”,Xcode会自动补充缺失的变量。

image.png

补充缺失的变量后,根据定义好的数据类型,完成相对应的数据即可。

image.png

这样,我们就完成了整个定价方案的编程!


// 定价方案
HStack {
    // 连续包月
    ZStack {
        pricingView(title: "连续包月", price: "¥18", perPrice: "", bgColor: Color("faf7f3")
            .overlay(RoundedRectangle(cornerRadius: 6).stroke(Color(red: 202 / 255, green: 169 / 255, blue: 106 / 255), lineWidth: 2))
        // 首月特惠
        specialOfferView()
    }
    // 1个月
    pricingView(title: "1个月", price: "¥30", perPrice: "", bgColor: Color(red: 244 / 255, green: 244 / 255, blue: 245 / 255))
        .cornerRadius(10)
    // 12个月
    pricingView(title: "12个月", price: "¥228", perPrice: "¥19.00/月", bgColor: Color(red: 244 / 255, green: 244 / 255, blue: 245 / 255))
        .cornerRadius(10)
    }
    .padding()


image.png


相关文章
|
8月前
|
存储 vr&ar
大师学SwiftUI第6章 - 声明式用户界面 Part 1
在上一章,我们介绍了SwiftUI的主要特性,声明式语法。借助SwiftUI,我们可以按希望在屏幕上显示的方式声明视图,余下交由系统来创建所需的代码。但声明式语法不只用于组织视图,还可在应用状态发生变化时更新视图。
87 1
|
27天前
|
iOS开发 开发者 MacOS
深入探索iOS开发中的SwiftUI框架
【10月更文挑战第21天】 本文将带领读者深入了解Apple最新推出的SwiftUI框架,这一革命性的用户界面构建工具为iOS开发者提供了一种声明式、高效且直观的方式来创建复杂的用户界面。通过分析SwiftUI的核心概念、主要特性以及在实际项目中的应用示例,我们将展示如何利用SwiftUI简化UI代码,提高开发效率,并保持应用程序的高性能和响应性。无论你是iOS开发的新手还是有经验的开发者,本文都将为你提供宝贵的见解和实用的指导。
120 66
|
8月前
|
编译器 API Swift
【Swift开发专栏】Swift中的SwiftUI框架初探
【4月更文挑战第30天】SwiftUI是苹果2019年推出的界面构建框架,简化iOS应用开发。通过声明式语法和编译器优化,提供直观高效的UI设计。本文将介绍SwiftUI概述、主要特性及实际案例。SwiftUI强调“少即是多”,用少量代码实现复杂界面,提供简洁API、自动布局、双向数据绑定等功能。通过视图组合和实时预览加速开发。案例展示如何用SwiftUI构建用户列表界面,体现其结构清晰、易扩展的优势。SwiftUI在iOS开发中的重要性日益提升。
110 0
|
8月前
|
开发工具 Swift iOS开发
利用SwiftUI构建动态用户界面:iOS开发新范式
【4月更文挑战第3天】 随着苹果不断推进其软件开发工具的边界,SwiftUI作为一种新兴的编程框架,已经逐渐成为iOS开发者的新宠。不同于传统的UIKit,SwiftUI通过声明式语法和强大的功能组合,为创建动态且响应式的用户界面提供了一种更加简洁高效的方式。本文将深入探讨如何利用SwiftUI技术构建具有高度自定义能力和响应性的用户界面,并展示其在现代iOS应用开发中的优势和潜力。
|
8月前
|
API iOS开发 UED
SwiftUI 设计
SwiftUI 设计
83 2
|
8月前
|
存储 Go vr&ar
大师学SwiftUI第6章 - 声明式用户界面 Part 2
控件是交互工具,用户通过交互修改界面状态、选取选项或插入、修改或删除信息。我们实现过其中的一部分,如前例中的Button视图以及TextField视图。要定义一个有用的接口,需要学习有关视图的更多知识以及其它由SwiftUI所提供的控制视图。
61 0
|
8月前
|
存储 安全 vr&ar
大师学SwiftUI第6章 - 声明式用户界面 Part 3
SwiftUI还内置了创建安全文本框的视图。这一视图会把用户输入的字符替换成点以及隐藏敏感信息,比如密码。 •
67 0
|
8月前
|
存储 vr&ar Swift
大师学SwiftUI第6章 - 声明式用户界面 Part 4
Stepper视图创建一个带递增和递减按钮的控件。该结构体提供了多个初始化方法,包含不同的配置参数组合。以下是最常用的一部分。 •
60 0
|
消息中间件 Dart
|
iOS开发
SwiftUI极简教程05:代码分组管理
SwiftUI极简教程05:代码分组管理
451 1
SwiftUI极简教程05:代码分组管理