欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Swift基础

程序员文章站 2022-03-01 17:01:26
...

swift与objective-C的重大区别

  1. swift不分.h和.m文件 ,一个类只有.swift一个文件,所以整体的文件数量比起OC有一定减少。
  2. swift句尾不需要分号 ,除非你想在一行中写三行代码就加分号隔开。
  3. swift数据类型都会自动判断 , 只区分变量var 和常量let
  4. 强制类型转换格式不同 OC强转:(int)a Swift强转:Int(a)
  5. 关于BOOL类型更加严格 ,Swift 中没有 C 语言中的非零即真概念,而是true才是真false才是假 (关于objective-C 中BOOL 的若干陷阱)
  6. swift的 循环语句中必须加{} 就算只有一行代码也必须要加
  7. swift的switch语句后面可以跟各种数据类型了 ,如Int、字符串都行,并且里面不用写break(OC不能字符串)
  8. swift if后的括号可以省略: if a>b {},而OC里 if后面必须写括号。
  9. swift打印 用print("") 打印变量时可以 print("(value)"),不用像OC那样记很多%@,d%等。
  10. Swift3的【Any】可以代表任何类型的值,无论是类、枚举、结构体还是任何其他Swift类型,这个对应OC中的【id】类型。

Swift的访问权限

访问权限 **由大到小 **依次为:open,public,internal(默认),fileprivate,private

注:方法的使用权限不能大于类的使用权限
  • open:可以被任何人使用,包括override和继承。
  • public:可以被任何人访问,但其他module中不可以被override和继承,而在本module内可以被override和继承。
  • internal是系统默认访问级别,internal修饰符可写可不写。internal访问级别所修饰的属性或方法在源代码所在的整个模块都可以访问。
    如果是框架或者库代码,则在整个框架内部都可以访问,框架由外部代码所引用时,则不可以访问。如果是App代码,也是在整个App代码,也是在整个App内部可以访问。
  • fileprivate:访问权限为文件内私有。
  • private:离开了这个类或者结构体的作用域外面就无法访问。

常量和变量

let 定义常量,一经赋值不允许再修改
var 定义变量,赋值之后仍然可以修改

// 定义常量 let / 变量 var
// 格式: let/var 变量名: 类型 = 值
// 提示: Swift 提供了自动推导,如果使用默认的数据类型,`: 类型` 可以省略
// 格式: let/var 变量名 = 值,变量类型会根据右侧的结果`自动推导`
// 定义常量并且直接设置数值
let x: Int = 10
// 常量数值一经设置,不能修改,以下代码会报错
// x = 30
// 使用 `: 类型`,仅仅只定义类型,而没有设置数值
let y: Int
// 常量有一次设置数值的机会,以下代码没有问题,因为 `y` 还没有被设置数值
y = 10
// 一旦设置了数值之后,则不能再次修改,以下代码会报错,因为 `y` 已经被设置了数值
// y = 50print(x + y)
// 变量设置数值之后,可以继续修改数值
var z: Int
z = 100
z = 200
print(x + y + z)

Option + Click 可以查看变量的类型

没有隐式转换

Swift 对数据类型要求异常严格。在任何时候,都不会做隐式转换,如果要对不同类型的数据进行计算,必须要显式的转换。

  let x = 100
 //swfit 会自动推导 x 为整型
let y = 10.5 
//swfit 会自动推导 y 为浮点型
let num = Double(x) + y
let num1 = x + Int(y)
什么是可选值

可选值(Optional) 是 Swift 的一大特色,也是 Swift 初学者最容易困惑(痛不欲生)的问题
所谓可选值(optional),就是指一个变量或常量,可能有值,也可能没有值。
场景举例:用一个值保存网络请求的数据;如果请求成功,则有值;如果请求失败,就没有值。

可选值的定义
定义常量/变量时,在类型后面加一个?表示该变量是可选的。
可选值必须提定类型
定义一个可选变量时,表示该变量可以有一个指定类型的值,也可以是 nil;变量可选项的默认值是 nil
常量可选项没有默认值,主要用于在构造函数中给常量设置初始数值

let x: Optional = 10
let y: Optional<Int>
let a: Int? 
//a默认没有值
var b: String? 
//b的默认值为 nil
let aa: Int? = 10
//aa let bb: String? = "hello, world"

可选值解包

如果 Optional 值是 nil,不允许参与计算, 只有解包(unwrap)后才能参与计算

在变量后添加一个 !,可以强行解包, 告诉编译器一定有值,如果没有值,则会报错(袜子的图)

注意:必须要确保解包后的值不是 nil,否则会报错

常见错误

unexpectedly found nil while unwrapping an Optional value 翻译 在对可选项[解包]时发现 nil

可选绑定

由于可选项的内容可能为 nil,而一旦为 nil 则不允许参与计算。因此在实际开发中,经常需要判断可选项的内容是否为 nil

单个可选项判断

let url = NSURL(string: "http://www.baidu.com")
//: 方法1: 强行解包 - 缺陷,如果 url 为空,运行时会崩溃
let request = NSURLRequest(URL: url!)
//: 方法2: 首先判断 - 代码中仍然需要使用 `!` 强行解包
if url != nil {   
 let request = NSURLRequest(URL: url!)
}
//: 方法3: 使用 `if let`,这种方式,表明一旦进入 if 分支,u 就不在是可选项
if let u = url where u.host == "www.baidu.com" {  
 let request = NSURLRequest(URL: u)
}

可选项条件判断

//: 1> 初学 swift 一不小心就会让 if 的嵌套层次很深,让代码变得很丑陋
if let u = url {   
 if u.host == "www.baidu.com" {        
let request = NSURLRequest(URL: u)
    }
}
//: 2> 使用 where 关键字,
if let u = url where u.host == "www.baidu.com" {    
let request = NSURLRequest(URL: u)
}

小结 if let 不能与使用 &&、|| 等条件判断 如果要增加条件,可以使用 where 子句 注意:where 子句没有智能提示

多个可选项判断

//: 3> 可以使用 `,` 同时判断多个可选项是否为空
let oName: String? = "张三"let oNo: Int? = 100if let name = oName {    
  if let no = oNo {       
     print("姓名:" + name + " 学号: " + String(no))
    }
}if let name = oName, let no = oNo {    
    print("姓名:" + name + " 学号: " + String(no))
}

判断之后对变量需要修改

let oName: String? = "张三"let oNum: Int? = 18if var name = oName, num = oNum {

    name = "李四"
    num = 1

    print(name, num)
}

guard

guard 是与 if let 相反的语法,Swift 2.0 推出的

let oName: String? = "张三"

let oNum: Int? = 18guard let name = oName else {    print("name 为空")    return}

guard let num = oNum else {    print("num 为空")    return}

// 代码执行至此,name & num 都是有值的print(name)print(num)
在程序编写时,条件检测之后的代码相对是比较复杂的,在判断的层次比较多的时候,使用 guard,而是减少嵌套的层次

if条件判断

在逻辑判断时必须显示地指明具体的判断条件 true / false
if 语句条件的 () 可以省略
但是 {} 不能省略

let num = 200if num < 10 {  
  print("比 10 小")
} else if num > 100 {   
 print("比 100 大")
} else {   
 print("10 ~ 100 之间的数字")
}

三目运算

Swift 中的 三目 运算保持了和 OC 一致的风格

x > 20 ? print("大了") : print("小了")
/**
    `()` 表示执行
*/
x > 20 ? print("真的大了") : ()

适当地运用三目,能够让代码写得更加简洁

判断可选值是否为 nil

让变量/常量强行解包参与运算会有风险,如果没有值,则会崩溃,所以在使用可选值时,最好先判断 可选值是否为 nil

var a: Int? = 10var b = 10if a != nil {  
  print("有值为\(a!+b)")
}else{    
  print("没有值")        
}

?? 空合运算符

?? 运算符可以用于判断 变量/常量 的数值是否是 nil,如果是则使用后面的值替代

在使用 Swift 开发时,?? 能够简化代码的编写

var a: Int? = 10var b = 10if (a ! = nil) {
    a = 0
}
let c = a + blet d = (a ?? 0) + b

注意:?? 的优先级低,在使用时,应该注意使用 ()

var str: String? = "老王"

// 注意 ?? 的优先级低,在使用时,应该注意使用 ()

print((str ?? "无名") + " 你好")print(str ?? "无名" + " 你好")
switch

switch 不再局限于整数

switch 可以针对任意数据类型进行判断

不再需要 break

每一个 case后面必须有可以执行的语句

要保证处理所有可能的情况,不然编译器直接报错,不处理的条件可以放在 default 分支中

每一个 case 中定义的变量仅在当前 case 中有效,而 OC 中需要使用 {}

引入了绑定和where增强了条件判断功能

switch score {

case "优":    let name = "学生"
    print(name + "80~100分")
case "良": print("70~80分")

case "中": print("60~70分")

case "差": print("不及格")default: break}
switch 中同样能够赋值和使用 where 子句

let point = CGPoint(x: 10, y: 10)switch point {

case let p where p.x == 0 && p.y == 0:    

print("中心点")

case let p where p.x == 0:   

 print("Y轴")

case let p where p.y == 0:   

 print("X轴")

case let p where abs(p.x) == abs(p.y):   

 print("对角线")

default:    print("其他")
}

如果只希望进行条件判断,赋值部分可以省略

switch score {
case _ where score > 80: print("优")

case _ where score > 60: print("及格")

default: print("其他")
}

for 循环

OC 风格的循环

var sum = 0for var i = 0; i < 10; i++ {
    sum += i
}print(sum)

swift 风格的循环

var sum = 0//for-in,0..<10, 表示从0到9for i in 0..<10 {
    sum += i
}print(sum)//范围 0...10 表示从0到10sum = 0for i in 0...10 {
    sum += i
}print(sum)

注意:..< 和 ... 用于定义 Range 类型,左右都不要添加空格
格式: for 变量 in 范围 { // 代码 }
省略下标
能够匹配任意类型 表示忽略对应位置的值

for _ in 0...10 {    
print("hello")
}

Array、Set和Dictionary

swift中的数组
1、定义数组

//定义不可变数组
let array = ["蓝波湾","蓝波图","蓝博思睿"]

//定义可变数组
var arrayM = [String]()
var arrayM1:[String]
var arrayM2 = Array<String>()

2、创建带有默认值的数组

var arrayM3:[Int] = Array(repeating: 0, count: 3)

3、数组基本操作

        //增
        arrayM3.append(1)
        //删
        arrayM3.remove(at: 0)
        arrayM3.removeSubrange(0..<2)//区间删除
        arrayM3.removeAll()
        arrayM3.removeFirst()
        arrayM3.removeLast()
        //改
        arrayM3[0] = 100
        arrayM3[0..<2] = [0,1]//区间替换
        //根据下标值进行遍历
        for i in 0..<arrayM3.count {
            print(arrayM3[i])
        }
        //倒序
        for i in arrayM3.reversed() {
            print(i)
        }
      //合并
      let resultArray = arrayM3 + arrayM

swift中的集合
集合(Set)用来存储相同类型并且没有确定顺序的值。当集合元素顺序不重要时或者希望确保每个元素只出现一次时可以使用集合而不是数组。

集合中的元素必须有确定的hashvalue,或者是实现了hashable协议。而swift提供的Int,String等类型其实都是实现了hashable协议的。hashable是equable的子协议,如果要判断两个元素是否相等,就要看他们的hashvalue是否相等。

1、定义集合

使用set<Element>定义。

Element表示集合中允许存储的类型,和数组不同的是,集合没有等价的简化形式。

//创建空集合
var letters = Set<Character>()
//使用字面量创建集合
var favorite:Set<String> = ["绮罗生","意琦行"]
//要注意的是一个Set类型是不能直接后面跟的字面量被单独推断出来的,因此这个Set是必须要显示声明的。但是由于swift的自动推断功能,可以不用写出Set的具体类型。比如说上面那个例子,省去String,也能推断出Set的正确类型。
var favorite:Set = ["绮罗生","意琦行"]

2、访问和修改集合
通过.count属性知道集合的长度,通过isEmpty判断集合是否为空。
3、添加元素

favorite.insert("寒烟翠")
print(favorite.count)

4、删除元素
通过remove的方法删除元素,若这个值真的存在就会删除改值,并且返回被删除的元素。若集合中不包含这个值,就会返回nil。

if let removeBack = favorite.remove("意琦行"){
    print(removeBack)
}else{
    print("没有找到值")
}

5、集合操作
swift提供了许多数学方法来操作集合。

print(oddD.union(evenD).sorted()) //并集

print(oddD.intersection(evenD).sorted())//交集

print(oddD.subtracting(siggleDPrime).sorted())//取差值

print(oddD.symmetricDifference(siggleDPrime).sorted())//去掉相同值

6、遍历集合

for item in favorite {
    print(item)
}
//按照首字母的顺序输出
for item1 in favorite.sorted() {
    print(item1)
}

7、集合的成员关系

  • 用 ==来判断两个集合是否包含全部相同的值
  • 用 isSubset(of:)来判断一个集合中的值是否也被包含在另外一个集合中
  • 用 isSuperset(of:)来判断一个集合中包含另一个集合所有的值
  • 用isStrictSubset(of:)或者isStrictSuperset(of:)方法来判断一个集合是否是另外一个集合的子集合或父集合并且两个集合不相等

swift中的字典
字典是一种存储多个相同类型的值的容器。每个值value都关联这唯一的键key。键就是这个字典的标识符。而且字典中的数据项并没有具体顺序。键集合不能有重复元素,而值集合是可以重复的。
1、定义字典
使用let定义不可变的字典,使用var定义可变字典。用字面量赋值时,系统会自动判断[]中存放的是键值对还是要一个个的元素。

let dict = [1:"one",2:"two",3:"three"]  //定义不可变字典
var dictM = Dictionary<String,NSObject>()  //定义可变字典
var dictM1 = [String:NSObject]()
//AnyObject一般用于指定类型,NSObject一般用于创建对象

2、对可变字典做基本操作
添加、删除和获取元素

dictM1["name"] = "小仙女" as NSObject
dictM["age"] = 17 as NSObject
dictM.removeValue(forKey:"name")
//获取:swift中只保留了最简单的写法,OC中有objectforkey的方法在swift中也被删除掉了。
dictM["name"]  

3、修改元素
若字典中已经有对应的key,操作的结果是直接修改原来的key中保存的value。若字典中没有对应的key,则会添加新的键值对。

dictM["name"] = "llx"

4、遍历字典

可以通过范围for遍历所有的key和value。也可以遍历所有的键值对。

for (key,value) in dictM {
    print(key)
    print(value)
}

5、合并字典

合并字典时通过遍历的方式将第二个字典的内容添加到第一个字典中。绝对不能用相加的方式对字典进行合并。

var dict1 = ["name":"llx","age":"17"]
var dict2 = ["num":"007"]

for (key,value) in dict2 {
    dict1[key] = value
}