一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

Swift 入门教程之:简单基本语法

时间:2016-08-15 编辑:简简单单 来源:一聚教程网


一.基础语法:

 

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).. let middle1 = urlString.substringWithRange(range1)
三.数组的使用
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..     print(array[i])
}
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  关键字

 

热门栏目