本文简介

点赞 + 重视 + 收藏 = 学会了


本文将以前端开发者的视角,和各位工友进入iOS开发的国际。

无论你是想要扩展技能领域,仍是对iOS开发充溢猎奇,花一个下午学习本文都能翻开iOS开发这扇门(画饼)。


学完本文你会掌握一点 swift 根底语法,并且开发出一款iOS运用。


阅览本文前你至少需求掌握一门编程言语,假如你是前端开发者,最好懂一点 typescript,这对学习 swift 根底语法来说有点协助。



预备作业

首要,你需求有一台苹果电脑。

其次,你还需求有一个苹果账号,能够在 苹果官网 恳求。

最终,下载一个 Xcode,在 App Store 能够找到。

跨越边界:从前端切图仔走进iOS开发(Swift版--上集)

尽管评分有点低,但你仍是得用它。



swift根底语法

swift 语法规矩许多,但初学阶段我以为没必要学全。初学阶段更重要的是建立决心,所以**“快”是要害**。

假如一开端就把语法全部啃一遍,学到后边大约率会忘掉前面。

在对iOS开发有必定的了解(能经过cv捣鼓一下)再回头把语法和原理补回去,这样可能会更顺。

正如俗语说的那样,回头是岸。所以学完皮毛后必定要回头!


综上所述,本文不会对 swift 根底语法做深化解说。只跟各位工友粗略过一遍。


学习 swift 语法时,咱们能够创立一个空模板进行练习。

创立空模板的流程:翻开 Xcode -> File -> New -> Playground -> Blank

跨越边界:从前端切图仔走进iOS开发(Swift版--上集)

跨越边界:从前端切图仔走进iOS开发(Swift版--上集)

然后挑选一个方位寄存好就能开端学习了。

跨越边界:从前端切图仔走进iOS开发(Swift版--上集)

Xcode 里运用 Playground 文件模板,能够在最终测的面板直接看到当时代码履行的成果。



注释

在学习新言语的时分,我习气第一时间学会狡赖(注释)。

杰出的注释习气能够让其他开发者更容易了解我的意图。

swift 的注释和 JS 相同,单行用 //,多行用 /**/

// 单行注释
/*
  多行注释
	多行注释
	多行注释
*/


变量

swift 中运用 var 声明变量。

swift 声明变量的语法和 ts 很像,声明变量时最好注明变量类型再赋值(留意,这儿说的是“最好”)。

假如没有清晰写明变量类型,XCode修改器 也会主动推导。

// 声明变量时注明变量类型
var sayHi: String = "雷猴"
// 主动推导变量类型
var sayHello = "带尬猴"

从上面的比方能够看出,假如要手动阐明变量类型的话,在变量名后边运用冒号再加上变量类型即可。

swift 支撑哪些变量类型稍后会说到。


变量的值是能够修正的。

var sayHi: String = "雷猴"
sayHi = "雷猴啊"

变量的类型一旦确认了就不能再修正。以下这种写法会报错(不能将数值型数据赋给字符型变量)。

var sayHi: String = "雷猴"
sayHi = 123

变量不答应重复声明,以下写法会报错。

var sayHi: String = "雷猴啊234"
var sayHi: String = "雷猴"


常量

swift 中运用 let 声明常量。

常量能够在声明时赋值,也能够在声明后再赋值。

// 声明时赋值
let sayHi: String = "雷猴"
// 声明后仿制
let sayHello: String
sayHello = "带尬猴"

常量的值一旦确认了就不能再修正。

// 这种写法会报错!
let sayHi: String = "雷猴"
sayHi = "雷猴啊"


变量、常量命名规矩

简略总结一下变量和常量的命名规矩

  1. 支撑字母、数字、下划线,乃至中文和emoji表情,但不主张运用中文和emoji表情作为变量和常量名。
  2. 不支撑数字最初,但能够用下划线最初。
  3. 不支撑特别字符。
  4. 不主张运用 swift 保留字作为变量名,实在要用就运用两个”`” 包起来。
// 运用保留字作为变量名的用法(日常开发中不主张这么做!)
var `var` = "雷猴"
print(`var`)


打印输出

前面声明过变量和常量,假如需求打印,能够运用 print() 办法。

var sayHi: String = "雷猴"
print(sayHi)

此刻在控制台就会打印出 sayHi 的值。

跨越边界:从前端切图仔走进iOS开发(Swift版--上集)



数据类型

整型、浮点型、布尔行、字符型

元组

数组、调集、字典

整型 Int

整型能够了解为整数,1、2、3、100这些都是整数。在 swift 中运用 Int 表明整型。

var num: Int = 123

浮点型 Float 和 Double

浮点型能够存储带小数点的数值。swift 分 单精度Float 和 双进展 Double

双精度 Double 比 单精度 Float 有更高的精度。在日常开发中一般运用双精度Double

var pi: Double = 3.14

swifthjs 相同,在进行浮点型数值计算时可能会呈现精度丢失问题。

var num1: Double = 0.1
var num2: Double = 0.2
print(num1 + num2) // 输出 0.30000000000000004

字符串 String

swift 里的字符串需求运用双引号包裹着。单引号不行

var str: String = "雷猴"

swift 字符串的概念和 ts 相似,所以在这儿就不过多解说了。接下来首要介绍一下 swift 字符串的常用办法。


判别空字符串 isEmpty

运用 isEmpty 能够判别字符串是否为空,假如是空的话会回来 true,反之回来 false

var str = ""
print(str.isEmpty) // true

获取字符串长度 count

运用 count 能够获取字符串的长度,这个有点像 JS 里的 length

var str = "雷猴"
print(str.count) // 2

其实用 count 也能够判别空字符串,假如回来成果为0便是空字符串,对不对~


拼接字符串 +

JS 相同,拼接字符串能够用加号 + 进行拼接。

var str1 = "hello"
var str2 = "world"
print(str1 + str2) // "helloworld"

在结尾追加字符串

var str = "hello"
str.append(Character("!")) // hello!

除了运用 append 办法外,还能够运用前面的拼接字符串的办法完成。

var str = "hello"
str = str + "!"

字符串的办法暂时先讲到这,开发中遇到实际问题去查一下就行了。


布尔型 Bool

布尔型用 Bool 表明,这个数据类型是用来表明真假的。

布尔型的值只要 truefalse

var isValid1: Bool = true
var isValid2: Bool = false

元组

我第一份编程作业是做前端,触摸的是 JS(当时还没有 TS),一开端对元组是没任何概念的。

后来触摸别的编程言语,开端有元组概念了。元组给我的感觉便是一个“不可变数组”(我是拿 switfJS 的数组对比)。

switf 中,元组能够将不同类型的数据组合在一同,比方保存部分根底信息时也能够用元组。

// 界说部分根底信息,包括部分称号和职工人数
var department:(name: String, numberOfStaff: Int) = ("销售部", 1000)

假如要拜访元组里的元素信息,能够用“点语法”来拜访。

// 界说部分根底信息,包括部分称号和职工人数
var department:(name: String, numberOfStaff: Int) = ("销售部", 1000)
// 获取部分称号
var name = department.name
// 获取部分人数
var number = department.numberOfStaff

上面的写法其实有点像 JS 里的目标,在声明元组的时分拟定了元素的称号,拜访的时分又用了“点语法”。

其实元组还支撑不指定元素称号的写法。假如不指定元素称号,拜访的时分就要用“下标”的办法去拜访了,有点像 JS 的数组,但这也仅仅像,真正要拜访元素的时分仍是会用“点语法”。

// 界说部分根底信息,包括部分称号和职工人数
var department:(String, Int) = ("销售部", 1000)
// 获取部分称号
var name = department.0
// 获取部分人数
var number = department.1

用下表拜访元组内容的这种办法还能够用在指定了元素称号的状况。

// 界说部分根底信息,包括部分称号和职工人数
var department:(name: String, numberOfStaff: Int) = ("销售部", 1000)
// 获取部分称号
var name = department.0
// 获取部分人数
var number = department.1

除了用下标获取没指定称号的元组内容外,还能够用解构的办法去获取元组里的内容。

var department:(String, Int) = ("销售部", 1000)
var (name, numberOfStaff) = department
print(name)
print(numberOfStaff)

这儿需求留意的是,解构时次序和元组的元素次序是一一对应的,便是要求解构时的变量数量要和元组数量相同。


有没有可能,我只需求获取元组中其间一个元素?有!

这时能够请 _ 出来帮忙(下划线)。

var department:(String, Int, String) = ("销售部", 1000, "这是销售部,卖东西贼凶猛")
// 只获取部分人数
var (_, number, _) = department
print(number)

swift 中,_ 表明匿名的意思,在一些特别场景会用到它。


数组 Array

数组是 swift 的其间一种调集类型。

数组是有序的,数组的每个元素都有一个数字下标,经过下标能够拜访数组指定元素。

数组能够寄存恣意数据类型,但在 swift 中,数组寄存的数据类型有必要统一。

比方说,整型数组里的每个元素都有必要是整形。


创立数组

界说数组的语法:

var 变量名:[数组类型]
// 举例
var arr:[Int]

又或许能够这样写

var 变量名:Array<数组类型>
// 举例
var arr:Array<String>

创立数组的写法

// 创立空数组
var arr1:[Int] = []
var arr2 = Array()
// 创立字符串数组
var arr3 = ["雷", "猴"] // XCode会自行推导数组类型
var arr4:[String] = ["雷", "猴"]
var arr5:Array<String> = ["雷", "猴"]
// 还能够这样写
var arr6 = Array(arrayLiteral: "雷", "猴")

填充数组

假如数组的元素相同,在 JS 中能够用 fill() 办法快速填充数组。在 swift 中也有相似的办法。

// 快速填充10个“猴”字
var arr1 = Array(repeating: "猴", count: 10)
// 还能够注明数组元素类型
var arr2 = [String](repeating: "猴", count: 10)

拜访/修正数组元素

数组元素能够用下标进行拜访,下标从0开端。和 JS 相同,经过 [下标] 来拜访数组元素。

需求留意:能够拜访 varlet 声明的数组,但不答应修正 let 声明的数组!!!

var arr = ["雷", "猴"]
// 拜访数组元素
print(arr[0]) // 雷
print(arr[1]) // 猴
// 修正数组元素
arr[0] = "带尬"
print(arr) // ["带尬", "猴"]

获取/修正数组区间

经过 [起始下标...完毕下标] 的办法能够获取数组区间,并回来一个新的数组。

var arr = ["h", "e", "l", "l", "o"]
// 拜访数组区间,并回来一个新的数组
print(arr[1...3]) // ["e", "l", "l"]
print(arr) // ["h", "e", "l", "l", "o"]
// 修正数组区间
arr[1...3] = ["a", "a", "a"]
print(arr) // ["h", "a", "a", "a", "o"]

假如修正区间时元素数量和原本的数量对不上也是没问题的。比方

// 少于原有数量
var arr1 = ["h", "e", "l", "l", "o"]
arr1[1...3] = ["a"]
print(arr1) // ["h", "a", "o"]
// 大于原有数量
var arr2 = ["h", "e", "l", "l", "o"]
arr2[1...3] = ["a", "a", "a", "a", "a", "a", "a", "a"]
print(arr2) // ["h", "a", "a", "a", "a", "a", "a", "a", "a", "o"]

依据这个特性,假如咱们想把 ["h", "e", "l", "l", "o"] 里的两个 l 删掉的话能够这样写

var arr = ["h", "e", "l", "l", "o"]
arr[2...3] = []
print(arr) // ["h", "e", "o"]

修正数组区间 replaceSubrange

除了上面说的办法,还能够运用 replaceSubrange() 办法修正数组指定区间的元素。

var arr = ["h", "e", "l", "l", "o"]
arr.replaceSubrange(1...3, with: ["a", "a", "a"])
print(arr) // ["h", "a", "a", "a", "o"]

数组是否为空 isEmpty

运用 isEmpty 能够判别数组是否为空,为空回来 true,否则回来 false

var arr1 = [1, 2, 3]
var arr2:[Int] = []
print(arr1.isEmpty) // false
print(arr2.isEmpty) // true

获取数组元素数量 count

运用 count 能够获取数组元素数量,当 count 回来 0 时也能够以为该数组为空。和 JSlength 差不多。

var arr1 = [1, 2, 3]
var arr2:[Int] = []
print(arr1.count) // 3
print(arr2.count) // 0

获取数组第一个元素 first

运用 first 能够获得数组的第一个元素。

var arr = ["h", "e", "l", "l", "o"]
print(arr.first) // "he"

获取数组最终一个元素 last

运用 last 能够获得数组的最终一个元素。

var arr = ["h", "e", "l", "l", "o"]
print(arr.last) // "o"

判别数组是否包括某个元素 contains

运用数组的 contains() 办法能够判别数组中是否包括某个元素,假如包括就回来 true,否则回来 false

var arr = ["h", "e", "l", "l", "o"]
print(arr.contains("e")) // true
print(arr.contains("a")) // false

追加元素 append

向数组结尾追加一个元素能够运用 append() 办法,直接传入一个元素即可。

留意:append只能修正 var 声明的数组,不能修正 let 声明的数组!!!

var arr = ["h", "e", "l", "l", "o"]
arr.append("!")
print(arr) // ["h", "e", "l", "l", "o", "!"]

假如需求追加一组元素,还需求合作 contentsOf 一同运用。

var arr = ["h", "e", "l", "l", "o"]
arr.append(contentsOf: [" ", "w", "o", "r", "l", "d"])
print(arr) // ["h", "e", "l", "l", "o", " ", "w", "o", "r", "l", "d"]

移除首个或前几个元素 removeFirst

运用 removeFirst() 办法能够移除数组的首个元素。

var arr = ["h", "e", "l", "l", "o"]
arr.removeFirst()
print(arr) // ["e", "l", "l", "o"]

留意:假如数组为空时运用 removeFirst() 会报错!所以运用移除操作前有必要判别数组是否为空!接下来讲到的其他数组的移除办法都要遵从这个规矩。


removeFirst() 还能够穿入一个整型参数,用来指定要移除的元素个数。

比方我想移除数组的前2位就能够传个 2 进去。

var arr = ["h", "e", "l", "l", "o"]
arr.removeFirst(2)
print(arr) // ["l", "l", "o"]

留意:传入的数不能大于数组的长度,否则会报错!


移除结尾1个或多位元素 removeLast

运用 removeLast() 能够移除数组结尾一个或多个元素。

var arr = ["h", "e", "l", "l", "o"]
arr.removeLast() // 移除数组结尾一个元素
print(arr) // ["h", "e", "l", "l"]

假如要移除数组结尾多个元素能够传入一个整数,但这个数不能大于数组的长度。

var arr = ["h", "e", "l", "l", "o"]
arr.removeLast(3) // 移除数组结尾3个元素
print(arr) // ["h", "e"]

移除指定规模内的元素 removeSubrange

运用 removeSubrange() 办法能够移除指定规模内的元素。

比方我要移除下标1~3的元素能够这样写:

var arr = ["h", "e", "l", "l", "o"]
arr.removeSubrange(1...3) // 移除1~3的元素
print(arr) // ["h", "o"]

清空数组 removeAll

运用 removeAll 能够清空数组。

var arr = ["h", "e", "l", "l", "o"]
arr.removeAll()
print(arr) // []

这样操作数组会报错!!!

能够运用 varlet 声明数组,依据前面说到的知识咱们知道运用 var 是声明变量,运用 let 是声明常量。

假如拜访数组(查询操作)的话是能够不差异 varlet 的。

但要修正数组(增、删、改)的话,只能操作 var 声明的数组。一旦操作 let 声明的数组就会报错!

以下操作都会报错!

// 过错
let arr1 = ["h", "e", "l", "l", "o"]
arr1[0] = "雷"
// 过错
let arr2 = ["h", "e", "l", "l", "o"]
arr2[0, 3] = []
// 过错
let arr3 = ["h", "e", "l", "l", "o"]
arr3.append("!")
// 过错
let arr4 = ["h", "e", "l", "l", "o"]
arr4.append(contentsOf: [" ", "w", "o", "r", "l", "d"])
// 过错
let arr5 = ["h", "e", "l", "l", "o"]
arr5.removeFirst()
// 过错
let arr6 = ["h", "e", "l", "l", "o"]
arr6.removeLast()
// 过错
let arr7 = ["h", "e", "l", "l", "o"]
arr7.removeSubrange(1...3)
// 过错
let arr8 = ["h", "e", "l", "l", "o"]
arr8.replaceSubrange(1...3, with: [])
// 过错
let arr9 = ["h", "e", "l", "l", "o"]
arr9.removeAll()

再次提醒,在运用移除操作前先判别数组是否为空!数组为空时运用移除操作会报错!!!


本文关于 swift 数组的办法先讲到这,入门阶段不打算讲太多,以后需求用到哪些办法再查就行。

后边讲 swift 遍历的时分还会用到数组来举例。


调集

调集是一组无序且不重复的数据。


创立调集

调集的类型叫 Set ,创立调集时能够用 Set 给变量声明类型。也能够经过 Set() 办法创立调集,然后由 XCode 自行揣度这个变量的类型。

var set1: Set<Int> = [1, 2, 3, 2, 1]
print(set1) // [1, 2, 3]

也能够这样创立

var set = Set(arrayLiteral: 1, 2, 3, 2, 1)
print(set) // [2, 3, 1]

由于调集是无序的,所以打印调集时可能每次输出的次序都不相同。


获取调集元素数量 count

和数组相同,调集运用 count 能够获取元素数量。

var set: Set<Int> = [1, 2, 3, 4, 5, 6]
print(set.count) // 6

调集是否为空 isEmpty

运用 isEmpty 能够判别调集是否为空,假如为空会回来 true ,有元素会回来 false

var set1: Set<Int> = [1, 2, 3, 4, 5, 6]
print(set1.isEmpty) // false
var set2: Set<Int> = []
print(set2.isEmpty) // true

是否包括指个元素 contains

运用 contains() 办法能够判别调集是否包括指定元素,需求传入元素的值。

var set1: Set<Int> = [1, 2, 3, 4, 5, 6]
print(set1.contains(4)) // true

增加元素 insert

运用 insert() 办法能够向调集刺进数据。

var set1: Set<Int> = [1, 2, 3, 4, 5, 6]
set1.insert(7)
print(set1) // [3, 1, 5, 2, 6, 7, 4]

删去元素 remove

运用 remove() 办法能够删去调集中指定的元素。假如要删去的元素不在调集里也不会报错。

var set1: Set<Int> = [1, 2, 3, 4, 5, 6]
set1.remove(2)
print(set1)

清空调集 removeAll

运用 removeAll() 办法能够清空调集,该办法不能传入参数。

var set1: Set<Int> = [1, 2, 3, 4, 5, 6]
set1.removeAll()
print(set1)

字典

字典能够了解为 JS 里的目标,便是一个键值对的数据类型。能够经过键(索引)找到对应的值。

由于字典是经过键来找到值的,所以键是不能重复的。就像实在国际的查字典那样。


创立字典

swift 中声明字典时是能够标明键和值的类型(不标明的话 XCode 也会自行揣度)。

var dic: [String: String] = ["name": "雷猴"]

这儿声明里键和值的类型都是字符串。

也能够运用这种办法创立字典:

var dic:Dictionary<Int, String> = [1: "雷猴"]
// 或许

假如你不显式声明类型,XCode 是能够自行揣度的。

var dic = ["name": "雷猴"]

假如想创立空字典能够这样写:

var dic:[Int:Int] = [:]
// 也能够这样写
var dic:Dictionary<Int, Int> = Dictionary()

需求留意的是,创立空字典时必定要声明键值的类型,否则会报错。

// 过错
var dic = [:]
// 过错
var dic = Dictionary()

获取值

要获取字典中某个值也很简略,能够用中括号 [] 的办法拜访键名 key

var dic = ["name": "雷猴"]
print(dic["name"]) // "雷猴"

假如键 key 不存在会回来 nil


修正值

能够经过上面取值的办法获取值,后边加个等号就能够重新赋值了。

var dic = ["name": "雷猴"]
dic["name"] = "鲨鱼辣椒"
print(dic) // ["name": "鲨鱼辣椒"]

更新值 updateValue

针对上面的“获取值”和“修正值”的操作,swift 还提供了另一种办法:updateValue()

updageValue() 接受2个参数,参数1是值的内容;参数2是 key,参数2需求运用 forKey 指明键名。

var dic = ["name": "雷猴"]
dic.updateValue("鲨鱼辣椒", forKey: "name")
print(dic) // ["name": "鲨鱼辣椒"]

假如 key 不存在就会新增元素。

var dic = ["name": "雷猴"]
dic.updateValue("鲨鱼辣椒", forKey: "name2")
print(dic) // ["name": "雷猴", "name2": "鲨鱼辣椒"]

增加新元素

经过直接赋值的办法能够给字典增加新元素,但假如字典中原本就有那个元素,直接赋值就会将本来的值给覆盖掉。

var dic = ["name": "雷猴"]
dic["job"] = "保安"
print(dic) // ["name": "雷猴", "job": "保安"]

其实修正元素和新增元素的操作都是相同的,这个过程能够了解为:假如键存在就更新值,假如键不存在就创立元素。


字典是否为空 isEmpty

运用 isEmpty 能够判别字典是否为空。字典为空回来 true,否则回来 false

var dic1 = ["name": "雷猴"]
print(dic1.isEmpty) // false
var dic2:[Int:Int] = [:]
print(dic2.isEmpty) // true

获取字典元素个数 count

运用 count 能够获取字典元素个数。

var dic = ["name": "雷猴"]
print(dic.count) // 1

删去元素 removeValue

能够运用 removeValue() 办法删去字典的元素

var dic = ["name": "雷猴", "job": "保安"]
dic.removeValue(forKey: "job")
print(dic) // ["name": "雷猴"]

清空字典 removeAll

运用 removeAll() 办法能够清空字典。

var dic = ["name": "雷猴", "job": "保安"]
dic.removeAll()
print(dic) // [:]


查看变量类型 type(of:)

js 里能够经过 typeof() 查看变量类型,在 swift 里也有相似的办法:type(of: )

var a = "雷猴"
print(type(of: a)) // String
var b = ["雷猴", "鲨鱼辣椒", "甲由恶霸", "蜘蛛侦察", "蝎子莱莱"]
print(type(of: b)) // Array<String>

大家能够自己试试输出其他数据类型。



运算符

运算符便是用来运算的,比方加减乘除。

swift 的运算符和 JS 的相似,在这儿就不深化解说了,我罗列出来记载一下,大家知道大约知道常用的有哪些运算符就行。


赋值运算符

赋值运算符便是一个 = 号,将右边的值赋给左边。

前面在讲变量常量的时分就现已用过了,这儿不再多讲。


管用运算符

常用的管用运算符有加减乘除、取余,在这根底上还有“加等”、“减等”之类的运算符,这儿简略罗列一下。

管用运算符 阐明
+
*
/
% 取余
+= 加等
-= 减等
*= 乘等
/= 除等
%= 余等

swift 里要重视一下取余 %,它只支撑整数类型的运算,不支撑浮点型!

// 过错
var num = 11.1 // 浮点型
print(num % 3)

需求留意的是,在新版的 swift 里撤销了自增 ++ 和自减 -- 这两种运算符。

我查到的材料说是从 swift 2.2版本之后撤销的。听说是为了进步可读性,削减代码的歧义。


逻辑运算

逻辑运算符便是“与”、“或”、“非”,用来判别真假和取反的。

运算符 阐明
&&
||
!

swift 的逻辑运算只支撑比较布尔类型的值,这点和 JS 是不相同的。

var t1 = true
var t2 = false
print(t1 && t2) // false
print(t1 || t2) // true
print(!t1) // false

JS 里支撑 !! 这种写法,在 swift 里是不支撑的。

// JS代码
var t1 = false
console.log(!!t1) // false
// swift
var t1 = false
print(!!t1) // 报错!!!

比较运算符

比较运算符首要用来比巨细或许看看两个变量是否持平,成果是回来 true 或许 false

常用的比较运算符有以下这些

比较运算符 阐明
== 比较两个值是否持平。
!= 不等于。
大于
>= 大于且等于
< 小于
<= 小于且等于

比较运算符的用法比较简略,和大多数干流的编程言语也没什么差异。这儿我就不举例了。


条件运算符

条件运算符也叫“三元运算符”,也是用来比较的。

条件运算符能够简化 if...else 的操作,但不主张在杂乱场景中运用。

条件运算符的用法是:

a ? b : c

假如 a 为真,履行或许回来 b ,否则履行或许回来 c

var a = true
print(a ? "雷猴" : "鲨鱼辣椒") // 回来
a ? print("雷猴") : print("鲨鱼辣椒") // 履行

区间运算符

区间运算符是 swift 里一个比较特别的运算符,它一般会和if-else判别或许 for-in 循环一同运用。

区间运算符有 .....< ,分别表明闭区间和半开区间。

// >=0 且 <=10
var a = 0...10
// >=0 且 <10
var b = 0..<10

swift..<pythonrange 有点像。


和区间运算符合作的另一个符号叫 ~=,它能够检测某个数是否存在区间内。

var a = 0..<10
print(a ~= 2) // true
print(a ~= 11) // false

区间运算符的运用会在接下来的循环中解说。



条件判别

if

swift 的条件判别运用 if 或许 if-else

用法如下:

var a = 10
// 单个if
if a < 11 {
  print(a)
}
// if-else
if a > 100 {
  print("a大过100")
} else {
  print("a小雨等于100")
}

这个用法比较简略,假如了解了前面的三元运算符就不难了解 if-else


swiftif 后边跟着的条件不需求用括号包起来,这点和 js 有点差异。


switch

假如匹配规矩比较多的时分,能够运用 switch-case 来处理。

根底用法

比方将职工的绩效考核转成中文输出:

var grade = "B"
switch grade {
case "A":
    print("优秀")
case "B":
    print("杰出")
case "C":
    print("合格")
default:
    print("不合格")
}

需求留意的是:

  • case 不需求运用 break 合作跳出。
  • 需求写上 default 那段。

一个case匹配多个条件

swiftswitchJS 的更强壮,它能够一个 case 匹配多个条件。

var grade = "B"
switch grade {
case "A", "B", "C", "D":
    print("英文字母")
case "0", "1", "2", "3":
    print("数字")
default:
    print("其他")
}


循环

假如需求履行一些重复性的操作,能够运用循环。

swift 常用的循环有 for-inwhilerepeat-while


for-in

for-in 循环的用法很简略,有一点点编程根底的工友看代码就能直接看懂的~

for i in 0...3 {
    print(i)
}
// 输出 0、1、2、3

上面这个比方结合了前面讲到的区间运算符。

for-in 除了能循环区间,还能循环字符串、数组等其他类型。

// 循环字符串
for i in "hello" {
    print(i) // 输出 h、e、l、l、o
}
// 循环数组
// 循环时获取到的是数组的每一个元素,不是下标!
var arr1 = ["a", "b", "c", "d"]
for i in arr1 {
    print(i) // 输出 a、b、c、d
}
// 循环数组
// 循环时获取到的是数组下标,需求合作 indices 一同运用
var arr2 = ["a", "b", "c", "d", "e"]
for index in arr2.indices {
    print(index) // 输出 0、1、2、3、4
}

字典的循环会略微特别一点。

直接循环字典

var dic = ["name": "雷猴", "age": "18"]
for item in dic {
    print(item)
}
/*
	输出:
	(key: "name", value: "雷猴")
	(key: "age", value: "18")
*/

能够经过 item.keyitem.value 拜访键和值

var dic = ["name": "雷猴", "age": "18"]
for item in dic {
    print(item.key)
    print(item.value)
}

假如循环时只需获取每次循环的键或许值,能够这样写:

var dic = ["name": "雷猴", "age": "18"]
// 直接获取键
for key in dic.keys {
    print(key)
}
// 直接获取值
for value in dic.values {
  print(value)
}

还有一种办法:

var dic = ["name": "雷猴", "age": "18"]
for (key, value) in dic {
    print(key)
    print(value)
}

while

while 循环经过一个逻辑判别作为循环条件,当条件为真时继续循环。

var arr = ["a", "b", "c", "d"]
var i = 0
while i < arr.count {
    print(arr[i])
    i += 1
}

需求留意,一般在循环体内需求对循环条件做修正,以免死循环。


repeat-while

swiftrepeat-whileJSdo...while 差不多。

repeat-whilewhile 的差异是:repeat-while 不管循环条件是否建立,它至少会履行一次。

var arr = ["a", "b", "c", "d"]
var i = 0
repeat {
    print(arr[i])
} while arr.count > 10
// 输出:a

这个比方中,循环条件是必定不建立的,但循环体仍是履行了一次。



函数

简略来说,函数的作用是将一堆代码整理打包到一同,并给这个函数起个名字,下次想运用这段代码的时分直接“喊”这个函数名就行了。当然,还有匿名函数,这个迟点再讲。

一句话总结:函数便是特定功能的代码块。

swift 中,函数是有类型的,这取决于它的参数和回来值,这点和 TypeScript 相似。


函数的创立和调用

创立函数

swift 中运用 func 要害字来声明函数。

创立函数的语法格局如下:

func 函数名(参数1: 参数类型, 参数2: 参数类型, ...) -> 回来值的类型 {
  代码块
}

举个比方,判别一个学生成绩是否大于60分。

func isQualified(score: Int) -> Bool {
    return score >= 60
}
isQualified(score: 90) // true
isQualified(score: 59) // false

函数的参数、回来值其实都能够不指定。

// 不需求参数
func fn1() -> String {
    return "雷猴"
}
print(fn1()) // 输出:雷猴
// 不需求回来值
func fn2() {
    print("雷猴")
}
fn2() // 输出:雷猴

回来多个值

函数还能够回来多个值(以元组的办法),这个在异步恳求的时分经常会这样写。

比方咱们经过文章id去查询文章概况。

func fetchArticleDetails(id: String) ->(status: Bool, data: String) {
  	// 模仿恳求的回来值
    let status = true
    let data = "文章内容"
    return (status, data)
}
// 当恳求成果的 status 为 true 时再履行输出。
if fetchArticleDetails(id: "100").status {
    print(fetchArticleDetails(id: "100").data)
}

外部参数名

函数还支撑外部参数名。

语法格局如下:

func 函数名(外部参数名 内部参数名: 参数类型) {
  代码块
}

这样做的优点是函数内部能够用一些名字更为精约的参数的一起能给外部起一个语义更强的参数名。

func fn(out1 p1: Int, out2 p2: Int) {
    print(p1, p2)
}
fn(out1: 1, out2: 2)

不传参数名(匿名参数)

能够运用匿名参数的办法,让调用函数传参时无需写明参数名。

func fn(_ p1: Int, _ p2: Int) {
    print(p1, p2)
}
fn(1, 2)

下划线 _匿名变量标识符


默许参数

默许参数的意思是:调用函数时能够传参也能够不传,传参的话就运用外部传进来的值,不传的话就运用默许值。

func fn(p1: Int, p2: Int = 10) {
    print(p1, p2)
}
fn(p1: 1, p2: 2) // 1 2
fn(p1: 3) // 1 10

在创立函数时能够给参数赋值,这种操作就时给参数指定一个默许值。


需求留意的是,假如运用匿名参数的办法创立函数,默许参数最好放在一切参数的后边,否则就有点失掉默许参数的含义了。

比方下面这段代码:

func fn(_ p1: Int = 10, _ p2: Int) {
    print(p1, p2)
}
fn(1, 2)
fn(3) // 会报错的!

不定参

有些状况是函数参数的数量不确认,比方 print() 办法能够传入1个参数,也能够传入多个参数。

这种状况就能够运用 不定参 的办法创立函数了,在参数后边加上 ... 能够让这个参数变成不定参。

func fn(param: String...) {
    print(param)
}
fn(param: "雷猴")
fn(param: "鲨鱼辣椒", "甲由恶霸")

留意参数类型后边的三个点。

不定参是一个数组,能够经过 [index] 的办法拜访数组的内容。

func fn(param: String...) {
    print(param[0])
}
fn(param: "鲨鱼辣椒", "甲由恶霸") // 打印:"鲨鱼辣椒"

假如和其他参数合作,需求指明参数名

func fn(param1: String..., param2: Int) {
    print(param1)
    print(param2)
}
fn(param1: "雷猴", "鲨鱼辣椒", "甲由恶霸", param2: 123)
/*
	输出:
	["雷猴", "鲨鱼辣椒", "甲由恶霸"]
	123
*/

假如运用匿名参数和不定参合作,这时分就只能运用一个不定参。

func fn(_ param1: Int, _ param2: String...) {
    print(param1)
    print(param2)
}
fn( 123, "雷猴", "鲨鱼辣椒", "甲由恶霸")

函数参数到底能不能修正?

JS 中,函数参数的值是能够修正的,但在 swift 里默许是不答应修正。

下面这种写法在 swift 里是过错的:

func fn1(a: Int) {
    a = 10
}
fn1(a: 1)

假如你便是要修正函数参数,能够这样写:

func fn1(a: inout Int) -> Int {
    a = 1
    return a
}
var para = 10
var b = fn1(a: &para)
print(b) // 1

先把参数在外部界说,调用函数传参时,在参数变量前面加上 &


将函数作为参数传入

某些状况需求将函数作为参数传入到另一个函数里,比方回调函数。

将函数作为参数传入另一个函数里,能够这样写:

func addFu(p1:Int, p2:Int) -> Int {
   return p1 + p2
}
func fn1(param:(Int,Int) -> Int) {
   print(param(10, 20))
}
fn1(param: addFu)

闭包

在了解闭包前,首要要知道 swift 的函数时能够嵌套的,比方这样:

func outerFn() -> Void {
    func innerFn() -> Void {
        print("雷猴")
    }
    innerFn()
}
outerFn()

outerFn 函数体里又创立一个函数(innerFn),然后履行 innerFn

这种写法便是函数的嵌套。


闭包有点像是一个自包括的函数,它能够在需求的时分被调用。它能够捕获并记住其地点的上下文中的变量和常量。

举个比方:

func outerFn() -> () -> Void {
    var counter = 0
    func innerFn() {
        counter += 1
        print("Counter: \(counter)")
    }
    return innerFn
}
let myFn = outerFn()
myFn()  // 输出 "Counter: 1"
myFn()  // 输出 "Counter: 2"

咱们在外部是无法直接拜访变量 counter 的,由于它是在 outerFn 里创立,在 innerFn 里被运用。

在履行 outerFn 后将 innerFn 回来出去给了 myFn,而 innerFn 的作用域内存在 counter 这个变量,所以 counter 也算是被 outerFn 一起回来出去了,但这个 counter 只能被同一个作用域的成员调用。所以在外层是无法直接运用 counter 的,但 counter 又没有被释放掉,所以在上面的代码中,每次调用 myFn 时都会履行 counter += 1counter 会在之前的值的根底上运算。

这便是闭包。


最终还需求弥补一下闭包的另一种写法。

前面说到函数的嵌套,其实还有另一种写法:

// 界说函数类型
var addFn: (Int, Int) -> Int
// 赋值
addFn = {(p1: Int, p2: Int) in return p1 + p2}
// 调用
addFn(1, 2) // 回来:3

上面的代码从语法上来看是这样的结构:

{(参数1, 参数2, ...) -> 回来值类型 in 闭包体}

in 是要害字,in 的左边是闭包结构的参数和回来值的类型,语法和声明一般函数相同;in 的右边是闭包体,是具体功能代码。


枚举

swift 中运用 enum 要害字创立枚举类型数据。

创立和运用枚举的办法如下:

enum Role: String {
    case L = "雷猴"
    case S = "鲨鱼辣椒"
    case X = "蝎子莱莱"
}
var protagonist: Role = Role.L
print(protagonist) // 输出:L
print(protagonist.rawValue) // 输出:雷猴

rawValue 能够获取枚举的原始值。

枚举一般会和 switch 一同运用,在后边的实战案例中用到会解说。



结构体

swift 中有结构体这两种数据结构,它们都能够界说物体的特点和行为,单它们的完成机制有着本质上的差异。

咱们先简略了解一下结构体

swift 中运用 struct 要害字界说结构体。在结构体内能够创立变量、常量和函数。

举个比方

struct Monkey {
    // 名字
    var name: String
    // 喜爱的食物
    var favoriteFood: String
    // 毛遂自荐
    mutating func introduce() {
        print("我叫\(name),我最喜爱的食物是\(favoriteFood)")
    }
}
var leihou = Monkey(name: "雷猴", favoriteFood: "黄焖鸡米饭")
leihou.introduce() // 我叫雷猴,我最喜爱的食物是黄焖鸡米饭


swift 中运用 class 声明类。

class Monkey {
    // 名字
    var name: String
    // 喜爱的食物
    var favoriteFood: String
    // 结构办法
    init(name: String, favoriteFood: String) {
        self.name = name
        self.favoriteFood = favoriteFood
    }
    // 毛遂自荐
    func introduce() {
        print("我叫\(name),我最喜爱的食物是\(favoriteFood)")
    }
}
var leihou = Monkey(name: "雷猴", favoriteFood: "黄焖鸡米饭")
leihou.introduce()

能够看出,类和结构体的语法看上去是差不多的,但类需求运用 init 结构函数给自己的特点赋值;而结构体并不需求这步操作。



结构体和类的差异

**结构体(struct)**和 类(class) 最大的差异是:类归于引证类型,结构体归于值类型。

在数据传递的时分,值类型会仿制一份出来再赋值给新变量,而引证类型是把值的地址赋值给新变量。

本文的起点是从前端切图仔转型iOS开发,我先拿 JS 阐明一下值类型和引证类型的差异。

// 以下是JS代码
// 值类型
var a = 1
var b = a
b = 2
console.log(a) // 1
console.log(b) // 2
// 引证类型
var c = {name: '雷猴'}
var d = c
d.name = "鲨鱼辣椒"
console.log(c.name) // 鲨鱼辣椒
console.log(d.name) // 鲨鱼辣椒

这个比方中,ab 归于值类型,就算写了 var b = a ,后边 b 修正了自己的值并不会影响 a

cd 的关系是它们手里都握着同一个房间的钥匙,d 挪动了房间里的物品后,c 也会受到影响。

大约便是这么一个关系。


回到 swift结构体(struct)类(class),结构体是值类型,类是引证类型。

值类型仿制给另一个变量时,本身的内容不会受到影响。

// 结构体 struct
struct Role {
    var name: String
}
var a = Role(name: "雷猴")
var b = a
b.name = "鲨鱼辣椒"
print(a.name) // 雷猴
print(b.name) // 鲨鱼辣椒

类是引证类型,仿制给其他变量时,仿制的是“翻开房间的钥匙”,也便是把存储值的内存地址仿制给另一个变量。

class Role {
    var name: String
    init(name: String) {
        self.name = name
    }
}
var a = Role(name: "雷猴")
var b = a
b.name = "鲨鱼辣椒"
print(a.name) // 鲨鱼辣椒
print(b.name) // 鲨鱼辣椒

结构体和类其实还有许多知识点,比方类的承继。在iOS初学阶段我主张是尽可能快的学会界面开发,能快速建立决心。

更多的知识点在学完本文后能够再去网上查查。



iOS开发

创立项目

1、翻开 Xcode,挑选 Create a new Xcode project。

跨越边界:从前端切图仔走进iOS开发(Swift版--上集)

2、挑选 App,然后点击 Next。

跨越边界:从前端切图仔走进iOS开发(Swift版--上集)

3、依据自己的需求填写好项目的基本信息。

跨越边界:从前端切图仔走进iOS开发(Swift版--上集)

其间,Interface可选 Storyboard 和 SwiftUI。

Storyboard 是传统的界面开发办法,SwiftUI只支撑Swift言语。

我这儿运用的是 Storyboard。SwiftUI 稍后再介绍。


填写完根底信息后点击 Next ,再挑选项目的寄存方位就能创立一个新的项目了。


运转项目

首要看看项目目录结构。

跨越边界:从前端切图仔走进iOS开发(Swift版--上集)

  • AppDelegate:运用程序入口。
  • SceneDelegate:多场景运用管理。
  • SceneDelegate:默许创立的视图控制器。
  • Main:可视化开发文件。
  • Assets:寄存静态资源的文件夹,比方寄存图片。
  • LaunchScreen:闪屏(App启动时的页面)。
  • Info:项目装备文件。

在大约了解了项目目录结构后,咱们先试着运转项目。

在箭头所指的区域挑选要运转的设备,然后点击左边的三角形按钮就能够运转项目了,iOS Simulators里的选项是你本机安装过的iOS模仿器。

跨越边界:从前端切图仔走进iOS开发(Swift版--上集)

我这儿用的是模仿器运转,假如要真机运转需求用数据线将你的iPhone接到电脑上,然后点击左边的三角形按钮即可。

跨越边界:从前端切图仔走进iOS开发(Swift版--上集)

但真机运转需求恳求证书,这个后边再讲。在初学阶段先用模仿器运转就行了。

接下来了解一下iOS开发中的常用页面元素。


根底控件

标签 UILabel

在学 HTML + CSS 时会学一堆标签和一些根底的款式设置。

iOS开发也能够用这套流程来学习。在初学阶段先了解一下如安在页面渲染。

关于款式部分的用法初学者能够先不深究,这和咱们刚学习 CSS 时是差不多的,用多几次就了解了。


根底用法

好,先来第一个比方。

我要在页面渲染“雷猴”两个字,要求如下:

  1. 字号:60
  2. 文本色彩:蓝色
  3. 文本暗影:绿色,有点偏移

出来的作用长这姿态:

跨越边界:从前端切图仔走进iOS开发(Swift版--上集)

在这个比方中运用到标签 UILabel 控件。

XCode 依据前面的过程创立一个项目,翻开 ViewController ,在这个文件里编写代码。

跨越边界:从前端切图仔走进iOS开发(Swift版--上集)

import UIKit
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // 将布景设置成白色
        view.backgroundColor = UIColor.white
        // 创立UILabel控件
        let label = UILabel(frame: CGRect(x: 0, y: 100, width: 200, height: 60))
        // 设置文本内容
        label.text = "雷猴"
        // 设置文本字号巨细
        label.font = UIFont.systemFont(ofSize: 60)
        // 设置文本色彩
        label.textColor = UIColor.blue
        // 设置文本暗影色彩
        label.shadowColor = UIColor.green
        // 设置文本暗影的方位偏移
        label.shadowOffset = CGSize(width: 4, height: 4)
        // 将label控件增加到当时视图上
        self.view.addSubview(label)
    }
}

上面这段代码,有一部分是在创立项目时就现已帮咱们写好的:

import UIKit
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
    }
}

override 表明重写父类的办法。

viewDidLoad 是生命周期,在这个办法内写的代码会在视图控制器加载时调用。

所以咱们会将创立元素的操作写在 viewDidLoad 里。


按照咱们开发网页的习气,页面布景默许是白色的。所以我运用 view.backgroundColor = UIColor.white 将页面布景设置成白色。

之后运用 let label = UILabel(frame: CGRect(x: 0, y: 100, width: 200, height: 60)) 创立一个 label 控件,这个控件能够了解为 HTML 里的 <div> ,但用法和 <div> 不同。

这句代码能够这样了解:

  • UILabel():创立Label控件
  • frame: CGRect():界说这个控件为矩形。
  • CGRect(x: 0, y: 100, width: 200, height: 60):设置这个控件的方位和宽高。

之后设置文本款式能够看上面的那段代码,关于什么是 UIFont.systemFont,什么是 CGSize 等东西暂时不用深究,初学阶段真的先死记硬背一下,深究对初学阶段没什么优点。


在设置好款式后,运用 self.view.addSubview(label) 将标签控件增加到页面。


需求留意的是,字号假如大于label的高度 或许 文本内容超出label宽度,文本都会显现不完整。

跨越边界:从前端切图仔走进iOS开发(Swift版--上集)

// 省掉部分代码
let label = UILabel(frame: CGRect(x: 0, y: 100, width: 200, height: 30))
label.text = "雷猴"
label.font = UIFont.systemFont(ofSize: 60)

此刻 label 的高度是30,字号是60。


同理,假如文字内容超出label的宽度,也会显现不完整

跨越边界:从前端切图仔走进iOS开发(Swift版--上集)

// 省掉部分代码
let label = UILabel(frame: CGRect(x: 0, y: 100, width: 200, height: 30))
label.text = "雷猴,鲨鱼辣椒,蝎子莱莱,甲由恶霸,金龟次郎,卡布达,翱翔机器人,铁甲小宝"
label.font = UIFont.systemFont(ofSize: 30)

本文的内容远远超过 label 的宽度,此刻会呈现省掉号的状况(假如还能放得下省掉号的话)。


多行文本

假如希望内容能换行展现,能够给 label 设置行数 numberOfLine

跨越边界:从前端切图仔走进iOS开发(Swift版--上集)

// 省掉部分代码
let label = UILabel(frame: CGRect(x: 0, y: 100, width: 300, height: 80))
label.text = "雷猴,鲨鱼辣椒,蝎子莱莱,甲由恶霸,金龟次郎,卡布达,翱翔机器人,铁甲小宝"
// 设置行数
label.numberOfLines = 6
label.font = UIFont.systemFont(ofSize: 20)

这儿需求留意的是,label 的高度也要有满足的方位支撑换行,否则仍是会呈现省掉号,把超出的部分隐藏起来。


多行文本这儿还有一个小技巧:将 numberOfLines 设为 0 能够主动换行,但条件是 label 的高度足以包容一切文本。

// 省掉部分代码
let label = UILabel(frame: CGRect(x: 0, y: 100, width: 300, height: 80))
label.text = "雷猴,鲨鱼辣椒,蝎子莱莱,甲由恶霸,金龟次郎,卡布达,翱翔机器人,铁甲小宝"
// 设置行数为0,表明不限制显现行数。
label.numberOfLines = 0
label.font = UIFont.systemFont(ofSize: 20)

运用 label 的多行文本需求留意几个点:

  • label的高度 height
  • 行数 numberOfLines
  • 字号 UIFont.systemFont(ofSize: 字号的值)

当高度小于字号,会把文字裁切掉一部分。

当高度大于字号,且高度小于可换行的量,会用省掉号替换掉超出的文本内容。

工友们自己动手试试看会更容易了解。


特别款式

假如想高亮一段文本的某几个字,能够合作 NSMutableAttributedString 一同运用。

比方这样,高亮了“鲨鱼辣椒”。

跨越边界:从前端切图仔走进iOS开发(Swift版--上集)

完成过程:

  1. 创立 label 控件。
  2. 运用 NSMutableAttributedString 创立一段文字。
  3. 经过 addAttribute 设置指定文本的款式。
  4. 将文本增加到页面里。

// 省掉部分代码
// 创立UILabel控件目标
let label = UILabel(frame: CGRect(x: 0, y: 100, width: 300, height: 200))
// 设置行数
label.numberOfLines = 0
// 创立特别文本
let attri = NSMutableAttributedString(string: "雷猴,鲨鱼辣椒,蝎子莱莱,甲由恶霸,金龟次郎,卡布达,翱翔机器人,铁甲小宝")
// 设置指定文本的款式
attri.addAttribute(
	NSAttributedString.Key.foregroundColor, // 要设置的款式,这句代码表明要设置文本色彩
	value: UIColor.systemRed, // 要设置款式的值,这儿表明赤色,意思便是让文本变成赤色。
	range: NSRange(location: 3, length: 4) // 要修正的规模,从下标为3的字开端修正,修正规模是4,也便是要修正下表为 3、4、5、6 这几个字的款式。下标是从0开端数起的。
)
label.attributedText = attri
self.view.addSubview(label)

addAttribute 需求传入3个参数,第1个参数是要设置的款式名;第2个参数是款式的值;第3个参数是修正规模。

概况请看上面的代码。


假如需求一起设置多个参数,能够将 addAttribute 改为 addAttributes 。留意看,仅仅多了个 s

addAttributes 需求传入2个参数,第1个参数是字典,字典里写名要修正的款式和值;第2个参数是修正规模。

跨越边界:从前端切图仔走进iOS开发(Swift版--上集)

// 省掉部分代码
let label = UILabel(frame: CGRect(x: 0, y: 100, width: 300, height: 200))
label.numberOfLines = 0
let attri = NSMutableAttributedString(string: "雷猴,鲨鱼辣椒,蝎子莱莱,甲由恶霸,金龟次郎,卡布达,翱翔机器人,铁甲小宝")
// 下划线
let underlineStyle: NSUnderlineStyle = .single
// 设置一堆款式(下标为 3、4、5、6 的字)
attri.addAttributes(
    [
        NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 20), // 字号
        NSAttributedString.Key.foregroundColor: UIColor.red, // 文本色彩
        NSAttributedString.Key.backgroundColor: UIColor.black, // 文本布景色
        NSAttributedString.Key.underlineStyle: underlineStyle.rawValue, // 下划线
        NSAttributedString.Key.underlineColor: UIColor.yellow, // 下划线色彩
    ],
    range: NSRange(location: 3, length: 4)
)
// 创立一个暗影作用
let shadow = NSShadow()
shadow.shadowColor = UIColor.systemYellow // 暗影色彩
shadow.shadowOffset = CGSize(width: 2, height: 2) // 暗影偏移方位
shadow.shadowBlurRadius = 3 // 暗影的模糊度
// 设置一堆款式(下标为 8、9、10、11 的字)
attri.addAttributes(
    [
        NSAttributedString.Key.font:UIFont.systemFont(ofSize: 30), // 字号
        NSAttributedString.Key.foregroundColor: UIColor.blue, // 文本色彩
        NSAttributedString.Key.shadow: shadow // 暗影作用
    ],
    range: NSRange(location: 8, length: 4)
)
label.attributedText = attri
self.view.addSubview(label)


按钮 UIButton

按钮是最根底的交互控件,它一般和点击操作相关。

swift 中运用 UIButton 创立按钮。

创立按钮一般需求做以下几步操作:

  1. 创立UIButton实例。
  2. 设置按钮方位和尺度。
  3. 设置按钮文本内容。
  4. 将按钮增加到视图。

跨越边界:从前端切图仔走进iOS开发(Swift版--上集)

import UIKit
class ViewController: UIViewController {
  override func viewDidLoad() {
    super.viewDidLoad()
    // 将布景设置成白色
    view.backgroundColor = UIColor.white
    // 创立UIButton实例
    let btn = UIButton(type: UIButton.ButtonType.system)
    // 设置按钮方位与尺度
    btn.frame = CGRect(x: 20, y: 100, width: 100, height: 30)
    // 设置按钮标题
    btn.setTitle("雷猴", for: .normal)
    // 增加到当时视图
    self.view.addSubview(btn)
  }
}

先看看 UIButton(type: UIButton.ButtonType.system) 这句,这个比方运用了 UIButton.ButtonType.system 这种类型,创立的是默许的体系按钮。

除了 system 类型外,swift 还提供了其他类型:

概况类型

  • detailDisclosure
  • infoLight
  • infoDark

跨越边界:从前端切图仔走进iOS开发(Swift版--上集)

// 省掉部分代码
let btn = UIButton(type: UIButton.ButtonType.detailDisclosure)

增加按钮(带加号)

  • contactAdd

跨越边界:从前端切图仔走进iOS开发(Swift版--上集)

// 省掉部分代码
let btn = UIButton(type: UIButton.ButtonType.contactAdd)

关闭按钮

  • close

跨越边界:从前端切图仔走进iOS开发(Swift版--上集)

import UIKit
class ViewController: UIViewController {
  override func viewDidLoad() {
    super.viewDidLoad()
    // 将布景设置成白色
    view.backgroundColor = UIColor.white
    // 创立UIButton实例
    let btn = UIButton(type: UIButton.ButtonType.close)
    // 设置按钮方位与尺度
    btn.frame = CGRect(x: 20, y: 100, width: 30, height: 30)
    // 增加到当时视图
    self.view.addSubview(btn)
  }
}

自界说按钮

  • custom

自界说按钮比较能够自界说更多装备,比方点击时文本的色彩能够自己装备。这个装备在 system 类型的按钮是不收效的,只要在 custom 才起作用。

跨越边界:从前端切图仔走进iOS开发(Swift版--上集)

import UIKit
class ViewController: UIViewController {
  override func viewDidLoad() {
    super.viewDidLoad()
    // 将布景设置成白色
    view.backgroundColor = UIColor.white
    // 创立UIButton实例【自界说按钮】
    let btn = UIButton(type: UIButton.ButtonType.custom)
    // 也能够这样写
    // let btn = UIButton(type: .custom)
    // 设置按钮方位与尺度
    btn.frame = CGRect(x: 20, y: 100, width: 100, height: 30)
    // 设置按钮的布景色
    btn.backgroundColor = UIColor.blue
    // 设置按钮标题
    btn.setTitle("雷猴", for: .normal)
    // 按钮点击时的款式(要设置 custom)
    btn.setTitleColor(UIColor.systemPink, for: .highlighted)
    // 增加到当时视图
    self.view.addSubview(btn)
  }
}

在这个比方中,经过 setTitleColor 设置点击时按钮文本色彩。


图片按钮

假如要设置按钮的图片或许布景图,也需求运用自界说按钮 custom

要运用图片作为按钮内容有2个办法:setImagesetBackgroundImage

首要需求将图片增加到 Assets 文件夹中,能够把图片拖拽进去,也能够在空白处右键,挑选 Import 进行导入。

跨越边界:从前端切图仔走进iOS开发(Swift版--上集)

我这儿导入了一张 car 的图片。

然后在代码中能够这样写:

跨越边界:从前端切图仔走进iOS开发(Swift版--上集)

// 省掉部分代码
let btn = UIButton(type: .custom)
btn.frame = CGRect(x: 20, y: 100, width: 100, height: 30)
// 设置按钮图片内容
btn.setImage(UIImage(named: "car"), for: .normal)
// 或许 设置按钮布景图
btn.setBackgroundImage(UIImage(named: "car"), for: .normal)

UIImage(named: "car") 里的 named 要填写图片文件称号。


点击事情

作为一个按钮,它的本质作业便是被人点击。

所以理所当然要监听一下点击事情啦。

// 省掉部分代码
override func viewDidLoad() {
  super.viewDidLoad()
  let btn = UIButton(type: UIButton.ButtonType.system)
  // 绑定一个点击事情:buttonTapped
  btn.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
  // 也能够这样写
  // btn.addTarget(self, action: #selector(touchBegin), for: UIControl.Event.touchUpInside)
}
// 点击事情
@objc func buttonTapped() {
  print("点击了")
}

addTarget() 办法的作用是给控件增加一个事情,需求传入3个参数:

  • 参数1: 要触发事情的目标,传入 self 便是当时控件的意思。
  • 参数2: 传入一个办法挑选器 selector ,这个挑选器决定要履行哪个办法。
  • 参数3: 触发办法的条件。


图片

本来打算把图片、视频音频放在往后一点的章节连着一同讲,它们都归于媒体控件。但在解说按钮部分现已用过图片了,而且图片也是非常常用的控件,那就先放在这儿解说吧~


根底用法

要在视图上展现图片需求做以下几步:

  1. 把图片增加到 Assets 目录里。
  2. 运用 UIImage 控件加载图片素材。
  3. 运用 UIImageView 控件展现图片。
  4. UIImageView 控件增加到视图里。

仍是拿回前面的汽车图片做比方

跨越边界:从前端切图仔走进iOS开发(Swift版--上集)

import UIKit
class ViewController: UIViewController {
  override func viewDidLoad() {
    super.viewDidLoad()
    // 将布景设置成白色
    view.backgroundColor = UIColor.white
    // 【过程2】创立图片控件
    let img = UIImage(named: "car")
    // 【过程3】创立展现图片的控件
    let imgView = UIImageView(image: img)
    // 设置UIImageView控件的方位和尺度
    imgView.frame = CGRect(x: 30, y: 100, width: 292, height: 146)
    // 【过程4】将控件增加到视图上
    self.view.addSubview(imgView)
  }
}

获取图片尺度

上面这个比方中我是怎么知道图片的宽高深292*146呢?(这句代码: CGRect(x: 30, y: 100, width: 292, height: 146) )

办法1便是手动查看图片文件信息。

办法2能够运用 img?.size 获取。

运转项目后,控制台就会输出当时图片的尺度。

// 省掉部分代码
let img = UIImage(named: "car")
let size = img?.size
print(size)

假如图片实在尺度与控件设置的尺度不一致,图片的宽高比就会被改变。



输入框 UITextField

根底用法

输入框也是比较常见的控件。创立输入框要用到 UITextField 控件,一般会做以下2步:

  1. 创立输入框控件(UITextField)。
  2. 设置输入框边框风格。
  3. 将输入框增加到视图。

跨越边界:从前端切图仔走进iOS开发(Swift版--上集)

import UIKit
class ViewController: UIViewController {
  override func viewDidLoad() {
    super.viewDidLoad()
    // 将布景设置成白色
    view.backgroundColor = UIColor.white
    // 创立输入框实例
    let textField = UITextField(frame: CGRect(x: 20, y: 100, width: 200, height: 30))
    // 设置输入框边框风格
    textField.borderStyle = UITextField.BorderStyle.roundedRect
    // 将控件增加到视图上
    self.view.addSubview(textField)
  }
}

在这个比方中设置边框风格时我用了 roundedRect 圆角矩形,除了这个之外还有其他风格:

  • none: 无边框
  • line: 直线边框
  • bezel: 贝塞尔风格边框
  • roundedRect: 圆角边框

这些风格工友们在自己的工程上试试就行,我这儿就不展现了。


设置款式

简略的款式我就直接给代码了,要设置杂乱点的款式再详尽解说。


设置本文色彩

跨越边界:从前端切图仔走进iOS开发(Swift版--上集)

// 省掉部分代码
// 设置为蓝色
textField.textColor = UIColor.blue

文本对齐办法

跨越边界:从前端切图仔走进iOS开发(Swift版--上集)

// 省掉部分代码
// 居中对齐
textField.textAlignment = NSTextAlignment.center

placeholder

跨越边界:从前端切图仔走进iOS开发(Swift版--上集)

// 省掉部分代码
textField.placeholder = "随意输入点东西吧"

自界说边框款式

要自界说边框款式,首要需求将默许的边框去掉。

假如没装备过 borderStyle 那默许便是没边框了。

假如要写明不需求边框能够这样写:textField.borderStyle = .none

之后就能够用以下办法装备边框款式了。

跨越边界:从前端切图仔走进iOS开发(Swift版--上集)

// 省掉部分代码
// 设置边框色彩
textField.layer.borderColor = UIColor.blue.cgColor
// 设置边框宽度
textField.layer.borderWidth = 4
// 设置边框圆角
textField.layer.cornerRadius = 10.0

内边距

要设置输入框的内边距(内边距是指文本与边框之间的距离),能够运用 UITextFieldeditingRect(forBounds:) 办法来自界说文本区域的方位和巨细。

跨越边界:从前端切图仔走进iOS开发(Swift版--上集)

import UIKit
class ViewController: UIViewController {
  override func viewDidLoad() {
    super.viewDidLoad()
    // 将布景设置成白色
    view.backgroundColor = UIColor.white
    let textField = PaddedTextField(frame: CGRect(x: 50, y: 100, width: 200, height: 30))
    textField.borderStyle = .line
    view.addSubview(textField)
  }
}
class PaddedTextField: UITextField {
  override func editingRect(forBounds bounds: CGRect) -> CGRect {
    return bounds.insetBy(dx: 20, dy: 2) // 设置内边距
  }
}

在这个比方中我创立了 PaddedTextField 子类,它承继了 UITextField。在 PaddedTextField 中重写了 editingRect(forBornds:) 办法,并回来了调整过文本区域的方位的 CGRect

insetBy(dx:dy:) 办法用来设置文本区域相对于边框的内边距。


前置元素和后置元素

能够经过 leftView 装备输入框的前置元素,经过 rightView 装备后置元素。

先看看图

跨越边界:从前端切图仔走进iOS开发(Swift版--上集)

import UIKit
class ViewController: UIViewController {
  override func viewDidLoad() {
    super.viewDidLoad()
    // 将布景设置成白色
    view.backgroundColor = UIColor.white
    // 创立输入框实例
    let textField = UITextField(frame: CGRect(x: 20, y: 100, width: 200, height: 30))
    // 设置输入框边框风格
    textField.borderStyle = .line
    // 设置前置元素
    let label1 = UILabel(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
    // 前置元素内容
    label1.text = "https://"
    // 将前置元素增加到输入框里
    textField.leftView = label1
    // 设置元素的显现形式
    textField.leftViewMode = UITextField.ViewMode.always
    // 设置后置元素
    let label2 = UILabel(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
    // 后置元素内容
    label2.text = ".com"
    // 后置元素字号
    label2.font = UIFont.systemFont(ofSize: 20)
    // 后置元素文本色彩
    label2.textColor = UIColor.blue
    // 将后置元素增加到输入框里
    textField.rightView = label2
    // 设置元素的显现形式
    textField.rightViewMode = UITextField.ViewMode.always
    self.view.addSubview(textField)
  }
}

除了能够设置文本外,还能够运用图片作为输入框的前置或许后置元素。


获取输入框内容

本例经过点击按钮获取输入框的内容。

跨越边界:从前端切图仔走进iOS开发(Swift版--上集)

import UIKit
class ViewController: UIViewController {
  override func viewDidLoad() {
    super.viewDidLoad()
    // 将布景设置成白色
    view.backgroundColor = UIColor.white
    // 创立输入框实例
    let textField = UITextField(frame: CGRect(x: 20, y: 100, width: 200, height: 30))
    // 设置输入框边框风格
    textField.borderStyle = .line
    self.view.addSubview(textField)
    // 按钮
    let button = UIButton(type: .system)
    button.setTitle("获取文本", for: .normal)
    button.addTarget(self, action: #selector(getText), for: .touchUpInside)
    button.frame = CGRect(x: 50, y: 150, width: 200, height: 30)
    self.view.addSubview(button)
  }
  @objc func getText() {
    if let textField = view.subviews.first(where: { $0 is UITextField }) as? UITextField {
      if let text = textField.text {
        print("输入的文本内容是:\(text)")
      }
    }
  }
}

getText() 办法中,首要经过 view.subviews.first(where:) 办法找到界面中的 UITextField 实例。然后,经过 textField.text 特点获取输入框的文本内容。

运用 text 特点能够获取用户在输入框中输入的文本内容。


事情托付

除了前面运用的办法获取到文本框输入到内容外,还能够运用事情托付去监听输入框的一些事情。

import UIKit
class ViewController: UIViewController,UITextFieldDelegate {
  override func viewDidLoad() {
    super.viewDidLoad()
    // 将布景设置成白色
    view.backgroundColor = UIColor.white
    // 创立输入框实例
    let textField = UITextField(frame: CGRect(x: 20, y: 100, width: 200, height: 30))
    // 设置输入框边框风格
    textField.borderStyle = .line
    textField.delegate = self
    self.view.addSubview(textField)
  }
  // 在输入框行将进入修改状况时调用
  func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
    print("预备开端~")
    return true
  }
  // 在输入框现已开端修改时调用
  func textFieldDidBeginEditing(_ textField: UITextField) {
    print("正在修改")
  }
  // 在输入框行将完毕修改时被调用
  func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
    print("行将完毕修改")
    return true
  }
  // 在输入框现已完毕修改时调用
  func textFieldDidEndEditing(_ textField: UITextField) {
    print("现已完毕修改")
  }
  // 在输入框中的文本发生变化时调用
  func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    // 发生变化的方位
    print(range, range)
    // 输入的内容
    print(string)
    // 回来true表明答应当时的输入操作
    return true
  }
}

能够经过 textField() 监听输入的内容,假如内容不符合要求回来 false 就能够制止当时的输入了。



引荐阅览

本文现已有点长了,下一篇再继续水吧~

下一篇会讲怎么打包发布运用。


《p5.js 光速入门》

《StreamSaver.js入门教程:高雅处理前端下载文件的难题》

《Annotorious.js 入门教程:图片注释工具》


点赞 + 重视 + 收藏 = 学会了