最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Swift 入门教程之:简单基本语法
时间:2022-06-25 23:35:13 编辑:袖梨 来源:一聚教程网
一.基础语法:
Swift 是 iOS 和 OS X 应用开发的一门新语言。然而,如果你有 C 或者 Objective-C 开发经验的话,你会发现 Swift 的很多内容都是你熟悉的。
Swift 的类型是在 C 和 Objective-C 的基础上提出的,Int是整型;Double和Float是浮点型;Bool是布尔型;String是字符串。Swift 还有两个有用的集合类型,Array和Dictionary,请参考集合类型。
就像 C 语言一样,Swift 使用变量来进行存储并通过变量名来关联值。在 Swift 中,值不可变的变量有着广泛的应用,它们就是常量,而且比 C 语言的常量更强大。在 Swift 中,如果你要处理的值不需要改变,那使用常量可以让你的代码更加安全并且更好地表达你的意图。
除了我们熟悉的类型,Swift 还增加了 Objective-C 中没有的类型比如元组(Tuple)。元组可以让你创建或者传递一组数据,比如作为函数的返回值时,你可以用一个元组可以返回多个值。
Swift 还增加了可选(Optional)类型,用于处理值缺失的情况。可选表示“那儿有一个值,并且它等于 x ”或者“那儿没有值”。可选有点像在 Objective-C 中使用nil,但是它可以用在任何类型上,不仅仅是类。可选类型比 Objective-C 中的nil指针更加安全也更具表现力,它是 Swift 许多强大特性的重要组成部分。
Swift 是一个类型安全的语言,可选就是一个很好的例子。Swift 可以让你清楚地知道值的类型。如果你的代码期望得到一个String,类型安全会阻止你不小心传入一个Int。你可以在开发阶段尽早发现并修正错误。
变量和常量:
常量和变量把一个名字(比如maximumNumberOfLoginAttempts或者welcomeMessage)和一个指定类型的值(比如数字10或者字符串"Hello")关联起来。常量的值一旦设定就不能改变,而变量的值可以随意更改。
声明常量和变量:
常量和变量必须在使用前声明,用let来声明常量,用var来声明变量。下面的例子展示了如何用常量和变量来记录用户尝试登录的次数:
--------------------------------------------------------------------------------
let maximumNumberOfLoginAttempts = 10
var currentLoginAttempt = 0
--------------------------------------------------------------------------------
数值型字面量:
整数字面量可以被写作:
一个十进制数,没有前缀
一个二进制数,前缀是0b
一个八进制数,前缀是0o
一个十六进制数,前缀是0x
下面的所有整数字面量的十进制值都是17:
let decimalInteger = 17
let binaryInteger = 0b10001 // 二进制的17
let octalInteger = 0o21 // 八进制的17
let hexadecimalInteger = 0x11 // 十六进制的17
浮点字面量可以是十进制(没有前缀)或者是十六进制(前缀是0x)。小数点两边必须有至少一个十进制数字(或者是十六进制的数字)。浮点字面量还有一个可选的指数(exponent),在十进制浮点数中通过大写或者小写的e来指定,在十六进制浮点数中通过大写或者小写的p来指定。
如果一个十进制数的指数为exp,那这个数相当于基数和$10^{exp}$的乘积:
1.25e2 表示 $1.25 × 10^{2}$,等于 125.0。
1.25e-2 表示 $1.25 × 10^{-2}$,等于 0.0125。
如果一个十六进制数的指数为exp,那这个数相当于基数和$2^{exp}$的乘积:
0xFp2 表示 $15 × 2^{2}$,等于 60.0。
0xFp-2 表示 $15 × 2^{-2}$,等于 3.75。
下面的这些浮点字面量都等于十进制的12.1875:
let decimalDouble = 12.1875
let exponentDouble = 1.21875e1
let hexadecimalDouble = 0xC.3p0
数值类字面量可以包括额外的格式来增强可读性。整数和浮点数都可以添加额外的零并且包含下划线,并不会影响字面量:
--------------------------------------------------------------------------------
let paddedDouble = 000123.456
let oneMillion = 1_000_000
let justOverOneMillion = 1_000_000.000_000_1
--------------------------------------------------------------------------------
元组
元组(tuples)把多个值组合成一个复合值。元组内的值可以使任意类型,并不要求是相同类型。
下面这个例子中,(404, "Not Found")是一个描述 HTTP 状态码(HTTP status code)的元组。HTTP 状态码是当你请求网页的时候 web 服务器返回的一个特殊值。如果你请求的网页不存在就会返回一个404 Not Found状态码。
let http404Error = (404, "Not Found") // http404Error 的类型是 (Int, String),值是 (404, "Not Found")
(404, "Not Found")元组把一个Int值和一个String值组合起来表示 HTTP 状态码的两个部分:一个数字和一个人类可读的描述。这个元组可以被描述为“一个类型为(Int, String)的元组”。
你可以把任意顺序的类型组合成一个元组,这个元组可以包含所有类型。只要你想,你可以创建一个类型为(Int, Int, Int)或者(String, Bool)或者其他任何你想要的组合的元组。
你可以将一个元组的内容分解(decompose)成单独的常量和变量,然后你就可以正常使用它们了:
let (statusCode, statusMessage) = http404Error
println("The status code is (statusCode)")
// 输出 "The status code is 404"
println("The status message is (statusMessage)")
// 输出 "The status message is Not Found"
如果你只需要一部分元组值,分解的时候可以把要忽略的部分用下划线(_)标记:
let (justTheStatusCode, _) = http404Error
println("The status code is (justTheStatusCode)")
// 输出 "The status code is 404"
此外,你还可以通过下标来访问元组中的单个元素,下标从零开始:
println("The status code is (http404Error.0)") // 输出 "The status code is 404"
println("The status message is (http404Error.1)") // 输出 "The status message is Not Found"
你可以在定义元组的时候给单个元素命名:
let http200Status = (statusCode: 200, description: "OK")
给元组中的元素命名后,你可以通过名字来获取这些元素的值:
println("The status code is (http200Status.statusCode)") // 输出 "The status code is 200"
println("The status message is (http200Status.description)") // 输出 "The status message is OK"
作为函数返回值时,元组非常有用。一个用来获取网页的函数可能会返回一个(Int, String)元组来描述是否获取成功。和只能返回一个类型的值比较起来,一个包含两个不同类型值的元组可以让函数的返回信息更有用。请参考[函数参数与返回值(06_Functions.html#Function_Parameters_and_Return_Values)。
注意:元组在临时组织值的时候很有用,但是并不适合创建复杂的数据结构。如果你的数据结构并不是临时使用,请使用类或者结构体而不是元组。请参考类和结构体。
二 ,swif运算符
一.循环
常见的循环有:for/while/do while
1.for循环
1.1 OC中的for循环写法
for (int i = 0; i < 10; i++) {
}
1.2 swift中的写法
// 区间遍历 0..<10 0...9
for i in 0..<10 {
print(i)
}
for i in 0...9 {
print(i)
}
// 如果一个标识符不需要使用, 那么可以通过 _ 来代替
for _ in 0..<10 {
print("hello world")
}
2.while循环
2.1 OC中的写法
int a = 20
while (a) {
}
2.2 swift中的写法
2.2.1while后面的()可以省略
2.2.2没有非0(nil)即真
var i = 10
while i > 0 {
print(i)
i -= 1
}
3.do while循环
// 区别: 不再使用do while --> repeat while
var m = 0
repeat {
print(m)
m += 1
} while m < 10
二.字符串
1.字符串的介绍
1.1字符串在任何的开发中使用都是非常频繁的
1.2OC和Swift中字符串的区别
在OC中字符串类型时NSString,在Swift中字符串类型是String
OC中字符串@"",Swift中字符串""
1.3使用 String 的原因
String 是一个结构体,性能更高
NSString 是一个 OC 对象,性能略差
String 支持直接遍历
String 提供了 String 和 NSString之间的无缝转换
2.字符串的定义
2.1定义不可变字符串
let str = "hello swift"
2.2定义可变字符串
var strM = "hello world"
strM = "hello china"
3.获取字符串的长度
先获取字符集合,再获取集合的count属性
let length = str.characters.count
4.遍历字符串
for c in str.characters {
print(c)
}
5.字符串的拼接
5.1字符串之间的拼接
let str1 = "Hello"
let str2 = "World"
let str3 = str1 + str2
5.2字符串和其它标识符间的拼接
let name = "lgp"
let age = 18
let .98
let infoStr = "my name is (name), age is (age), height is (height)"
5.3字符串格式化
比如时间:03:04 如果显示 3 : 4 就不好.所以需要格式化
let min = 3
let second = 4
let timeStr = String(format: "%02d:%02d", arguments: [min, second])
6.字符串的截取
6.1简单的方式是将String转成NSString来使用
在标识符后加:as NSString即可
// 1.方式一: 将String类型转成NSString类型, 再进行截取
// (urlString as NSString) --> NSString
let header = (urlString as NSString).substringToIndex(3)
let footer = (urlString as NSString).substringFromIndex(10)
let range = NSMakeRange(4, 5)
let middle = (urlString as NSString).substringWithRange(range)
6.2Swift中提供了特殊的截取方式
该方式非常麻烦
Index创建较为麻烦
// 2.方式二: Swift原生方式进行截取
let headerIndex = urlString.startIndex.advancedBy(3)
let header1 = urlString.substringToIndex(headerIndex)
let footerIndex = urlString.endIndex.advancedBy(-3)
let footer1 = urlString.substringFromIndex(footerIndex)
let range1 = headerIndex.advancedBy(1)..
三.数组的使用
1.数组的介绍
1.1 数组(Array)是一串有序的由相同类型元素构成的集合
1.2 数组中的集合元素是有序的,可以重复出现
1.3 Swift中的数组
swift数组类型是Array,是一个泛型集合
2.数组的初始化
2.1 定义不可变数组,使用let修饰
注意:不可变数组要在定义的同时初始化,否则没有意义
let array = ["why", "yz"]
2.2 定义可变数组,使用var修饰
注意:数组是泛型集合,必须制定该数组中存放元素的类型
基本写法
var arrayM = Array
简单写法
var arrayM = [String]()
3.对可变数组的基本操作(增删改查)
3.1 添加元素
arrayM.append("ljp")
3.2 删除元素
let removeItem = arrayM.removeAtIndex(1) 返回值为删除的元素
arrayM.removeAll()
3.3 修改元素
arrayM[0] = "why"
3.4 查找元素(根据下标获取元素)
let item = arrayM[0]
4.数组的遍历
4.1 遍历下标值
for i in 0..
}
4.2遍历元素
for name in array {
print(name)
}
4.3遍历下标值和元素
for (index, name) in array.enumerate() {
print(index)
print(name)
}
5.数组的合并
相同类型的数组可以相加进行合并
可变数组和不可变的数组也能合并
let array1 = ["why", "yz"]
let array2 = ["lmj", "lnj"]
let resultArray = array1 + array2
四.字典的使用
1.字典的介绍
1.1字典允许按照某个键来访问元素
1.2字典是由两部分集合构成的,一个是键(key)集合,一个是值(value)集合
1.3键集合是不能有重复元素的,而值集合是可以重复的,键和值是成对出现的
1.4Swift中的字典
Swift字典类型是Dictionary,也是一个泛型集合
2.字典的初始化
2.1 定义不可变字典,使用let修饰
注意:不可变字典要在定义的同时初始化,否则没有意义
系统会根据[]中存放的是键值对,还是一个个元素,来判断该[]是一个数组还是字典
let dict = ["name" : "why", "age" : 18, "height" : 1.88]
2.2 定义可变字典,使用var修饰
注意:字典是泛型集合,必须制定该数组中存放元素的类型
基本写法
var dictM = Dictionary
简单写法
var dictM = [String : NSObject]() // 常见
3.对可变字典的基本操作(增删改查)
3.1 添加元素
dictM.updateValue("why", forKey: "name")
3.2 删除元素
dictM.removeValueForKey("age")
3.3 修改元素
//如果原有没有对应的key/value, 那么就添加键值对
// 如果原有已经有对应的key/value, 那么直接修改
dictM.updateValue("1.77", forKey: "height")
dictM["name"] = "why"
3.4 查找元素(获取元素)
let item = dictM["name"]
4.字典的遍历
4.1 遍历字典中所有的key
for key in dict.keys {
print(key)
}
4.2 遍历字典中所有的value
for value in dict.values {
print(value)
}
4.3 遍历字典中所有的key / value
for (key, value) in dict {
print(key)
print(value)
}
5.字典的合并
相同类型的字典也不可以相加进行合并
可以把其中一个字典改为可变的,遍历不可变得字典,把元素一个一个的添加到另一个不可变字典中
let dict1 = ["name" : "why", "age" : 18]
var dict2 = ["height" : 1.88, "phoneNum" : "+86 110"]
for (key, value) in dict1 {
dict2[key] = value
}
五.元组的使用
1.元组的介绍
1.1元组是Swift中特有的,OC中并没有相关类型
1.2它是什么呢?
1.2.1 它是一种数据结构,在数学中应用广泛
1.2.2 类似于数组或者字典
1.2.3 可以用于定义一组数据
1.2.4 组成元组类型的数据可以称为“元素”
2.为什么使用元组?
如果字典或数组保存多种数据类型,那么从字典会数组取出来的数据类型是NSObject,我们使用的时候很不方便,要先转换为真实类型
元组保存多种数据类型,取出来就是该数据的真实类型,不需要转换就能直接使用
3.元组的定义
let infoTuple = ("why", 18, 1.88, "+86 110")
// 使用元组描述一个人的信息
("1001", "张三", 30, 90)
// 给元素加上元素名称,之后可以通过元素名称访问元素
(id:"1001", name:"张三", english_score:30, chinese_score:90)
构造函数基础
构造函数 是一种特殊的函数,主要用来在创建对象时初始化对象,为对象 成员变量 设置初始值,在 OC 中的构造函数是 initWithXXX,在 Swift 中由于支持函数 重载 ,所有的构造函数都是 init
构造函数的作用
分配空间 alloc
设置初始值 init
必选属性
自定义 Person 对象
class Person: NSObject {
/// 姓名
var name: String
/// 年龄
var age: Int
}
提示错误 Class 'Person' has no initializers -> 'Person' 类没有实例化器s
原因:如果一个类中定义了必选属性,必须通过构造函数为这些必选属性分配空间并且设置初始值
重写 父类的构造函数
/// `重写`父类的构造函数
override init() {
}
提示错误 Property 'self.name' not initialized at implicitly generated super.init call -> 属性 'self.name' 没有在隐式生成的 super.init 调用前被初始化
手动添加 super.init() 调用
/// `重写`父类的构造函数
override init() {
super.init()
}
提示错误 Property 'self.name' not initialized at super.init call -> 属性 'self.name' 没有在 super.init 调用前被初始化
为必选属性设置初始值
/// `重写`父类的构造函数
override init() {
name = "张三"
age = 18
super.init()
}
小结
非 Optional 属性,都必须在构造函数中设置初始值,从而保证对象在被实例化的时候,属性都被正确初始化
在调用父类构造函数之前,必须保证本类的属性都已经完成初始化
Swift 中的构造函数不用写 func
子类的构造函数
自定义子类时,需要在构造函数中,首先为本类定义的属性设置初始值
然后再调用父类的构造函数,初始化父类中定义的属性
/// 学生类
class Student: Person {
/// 学号
var no: String
override init() {
no = "001"
super.init()
}
}
小结
先调用本类的构造函数初始化本类的属性
然后调用父类的构造函数初始化父类的属性
Xcode 7 beta 5之后,父类的构造函数会被自动调用,强烈建议写 super.init() ,保持代码执行线索的可读性
super.init() 必须放在本类属性初始化的后面,保证本类属性全部初始化完成
Optional 属性
将对象属性类型设置为 Optional
class Person: NSObject {
/// 姓名
var name: String?
/// 年龄
var age: Int?
}
可选属性 不需要设置初始值,默认初始值都是 nil
可选属性 是在设置数值的时候才分配空间的,是延迟分配空间的,更加符合移动开发中延迟创建的原则
重载构造函数
Swift 中支持函数重载,同样的函数名,不一样的参数类型
/// `重载`构造函数
///
/// - parameter name: 姓名
/// - parameter age: 年龄
///
/// - returns: Person 对象
init(name: String, age: Int) {
self.name = name
self.age = age
super.init()
}
注意事项
如果重载了构造函数,但是没有实现默认的构造函数 init() ,则系统不再提供默认的构造函数
原因,在实例化对象时,必须通过构造函数为对象属性分配空间和设置初始值,对于存在必选参数的类而言,默认的 init() 无法完成分配空间和设置初始值的工作
调整子类的构造函数
重写 父类的构造函数
/// `重写`父类构造函数
///
/// - parameter name: 姓名
/// - parameter age: 年龄
///
/// - returns: Student 对象
override init(name: String, age: Int) {
no = "002"
super.init(name: name, age: age)
}
重载 构造函数
/// `重载`构造函数
///
/// - parameter name: 姓名
/// - parameter age: 年龄
/// - parameter no: 学号
///
/// - returns: Student 对象
init(name: String, age: Int, no: String) {
self.no = no
super.init(name: name, age: age)
}
注意:如果是重载的构造函数,必须 super 以完成父类属性的初始化工作
重载 和 重写
重载 ,函数名相同,参数名/参数类型/参数个数不同
重载函数并不仅仅局限于 构造函数
函数重载是面相对象程序设计语言的重要标志
函数重载能够简化程序员的记忆
OC 不支持函数重载,OC 的替代方式是 withXXX...
重写 ,子类需要在父类拥有方法的基础上进行扩展,需要 override 关键字
相关文章
- 王者荣耀侦探能力大测试攻略 王者荣耀侦探能力大测试怎么过 11-22
- 无期迷途主线前瞻兑换码是什么 11-22
- 原神欧洛伦怎么培养 11-22
- 炉石传说网易云音乐联动怎么玩 11-22
- 永劫无间手游确幸转盘怎么样 11-22
- 无期迷途主线前瞻兑换码是什么 无期迷途主线前瞻直播兑换码介绍 11-22