swift-基本数据类型和optional类型

312 阅读6分钟

2022年3月更新-可选类型

如果你有其他程序的开发经验,那么这一系列的swift入门教程分享,将很适合你。

开始吧,启动Xcode:打开Xcode,选择“Get started with a playground”,选择“macOS”下的“Blank”,在下一步里选定保存位置,就可以了。

常量和变量

let 声明常量

常量:是固定值,程序中不可改,声明时须赋值。

let π = 3.14 

var 声明变量

变量:非固定值,程序中可改,未赋值不可用。

var a:String = "a string"
var b:Int = 10
var c:Float = 1.2
var d:Double = 1.9
var e:Bool = true
var f:Character = "a"//单个字符

变量未赋值不可以使用

var name:String
print(name)
//Variable 'name' used before being initialized

可以在一行中声明多个常量或者多个变量,用逗号隔开:

var x = 0.0, y = 0.0, z = 0.0

类型注解

上面示例代码中,在常量或者变量名后面加上一个冒号和空格,再加上类型名称,就是为声明的常量和变量加上了类型注解。

var welcomeMessage: String

如果你在声明常量或者变量的时候赋了一个初始值,Swift 可以推断出这个常量或者变量的类型,,没有给 welcomeMessage 赋初始值,所以变量 welcomeMessage 的类型是通过一个类型注解指定的,而不是通过初始值推断的。

你可以在一行中定义多个同样类型的变量,用逗号分割,并在最后一个变量名之后添加类型注解:

var red, green, blue: Double

注释

注释分单行、多行、多行嵌套

// 这是单行注释
    
/*
这是多行注释的第一行
这是多行注释的第二行
*/

/* 多行套用注释,外部
code
/* 多行套用注释,内部 */
code
多行套用注释,外部 */

输出语句

使用 print(_:separator:terminator:) 函数来输出当前常量或变量的值, 用字符串插值(string interpolation)的方式把常量名或者变量名当做占位符加入到长字符串中 将常量或变量名放入圆括号中,并在开括号前使用反斜杠将其转义:

print(a,b,c)

//拼接字符串 只能拼接String类型的 在后面字符串的文章里还会再探讨; 
print(a + h)

print("a + \(b)")

print("\(true) - \(100) - \(1.00)" + a)

关键字

请不要使用下列英文单词作为自已在Swift编程中的命名(包括但不仅限于下列单词)

  • class,类
  • deinit,析构函数
  • enum,枚举
  • extension,拓展类
  • func,函数
  • import,引入模块
  • init,构造函数
  • let,常量
  • protocol,协议
  • static,静态
  • struct,结构体
  • subscript,下标语法
  • typealias,类型别名
  • var 变量

数据类型

  • 整型
  • 浮点型
  • 布尔
  • 字符
  • 字符串 这里就不展开各个类型来说了,主要探讨swift的类型安全和类型推断。

类型推断

Swift 是一个类型安全(type safe) 的语言。类型安全的语言可以让你清楚地知道代码要处理的值的类型。由于 Swift 是类型安全的,所以它会在编译你的代码时进行类型检查(type checks) ,并把不匹配的类型标记为错误。这可以让你在开发的时候尽早发现并修复错误。

类型推断其实很简单,对于声明的常量或者变量,如果没有显式的指定类型(就是上面说到的类型注解),那么编译器在编辑代码的时候,只要检查你赋给变量或者常量的值,就可以推断出对应的类型。

var h = "this is a string"
//输出数据类型
print(type(of: h))

let anotherPi = 3 + 0.14159
// anotherPi 会被推测为 Double 类型

类型别名

typealias dog = Int//dog就是Int
var aa:dog = 10
var bb:Int = 20
print(aa,bb)
typealias S = String
var cc:S = "WAL"

类型转换

SomeType(ofInitialValue) 是调用 Swift 构造器并传入一个初始值的默认方法,用来做强制的类型转换。

var dd = 10
print("this is a " + String(dd));

print("this is a " + String(false));

var ee = "hello"

print(Int(ee)) //nil

var ff = "100"

print(Int(ff)) //Optional(100)

var gg = Double(aa) ?? 0

print(Int(110.5))//110

print(Double(10))//10.0

print(Bool(100))//true

可选类型optional

什么是可选类型呢,这个概念在C 和 Objective-C 中并没有,用来处理值可能缺失的情况,我们可以通过在类型后面加一个 ? 来将变量声明为 Optional 的。用一个例子来说:

let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)
// convertedNumber 被推测为类型 "Int?", 或者类型 "optional Int"

这里使用了Int 类型的构造器,将一个 String 值转换成一个 Int 值,但并不是所有的字符串都可以转换成一个整数,构造器可能会失败,所以返回了一个可选类型Int?,而不是Int。这样就可以理解可选类型的意义了吧。

var aaa:Int? = nil
print((aaa) ?? 10)

可以给可选变量赋值为nil来表示他没有值,或者声明一个可选变量或者常量并且没有赋值,他们会自动被设置成nil。Swift 里的 nil 和 objc 里的 nil 完全不是一回事儿。objc 的 nil 是一个实实在在的指针,它指向一个空的对象;在 Swift 中,nil 不是指针,它是一个确定的值,用来表示值缺失。任何类型的可选状态都可以被设置为 nil,不只是对象类型。

var bbb:Int? = 100
print(bbb)//Optional(100)
//确定有真实的值 可以用叹号语法解析出真实的值
print(bbb!)//100
var value:String? = "hello"
print(value)

if value == nil {
    print("no value")
} else {
    //拼接的时候也要先解析出真实值
    print("value is" + value! + String(bbb!))
}

当确定可选类型包含真实值之后,可以通过叹号语法来获取值,这就是可选值的强制解析(forced unwrapping)。使用 ! 来获取一个不存在的可选值会导致运行时错误。

可选绑定

使用可选绑定(optional binding) 来判断可选类型是否包含值,如果包含就把值赋给一个临时常量或者变量。在 if 条件语句中使用常量和变量来创建一个可选绑定,仅在 if 语句的句中(body)中才能获取到值。相反,在 guard 语句中使用常量和变量来创建一个可选绑定,仅在 guard 语句外且在语句后才能获取到值。

var f:Int? = 10
//这里最好用 let  var 会报警告
if let fValue = f {
    //这里就不需要 用叹号运算符 解析真实值了
    print("fvalue = \(fValue)")
} 

var obj1:Int? = 1
var obj2:Int? = 2
//if-let语法结构来进行optional类型值的绑定操作
if let tmp1 = obj1, let tmp2 = obj2, tmp1 < tmp2 {
    print(tmp1, tmp2)
 }

隐式解析可选类型

在确定了可选类型有值之后,后面每次使用都要判断和解析可选值,效率就非常低了,所以我们可以声明的时候,把可选的类型的后面的问号(String?)改成感叹号(String!)来声明一个隐式解析可选类型。

一个隐式解析可选类型其实就是一个普通的可选类型,但是可以被当做非可选类型来使用,并不需要每次都使用解析来获取可选值。

var g:Int! = 100

print(g)//不需要感叹号强制解析

模拟面试

一、简述在swift中,对符号"?" 和 "!" 的理解

回答要点:

  1. 首先分类型和实例两个方面理解,"?"出现在类型后表示optional类型,出现在实例后表示可选链调用。"!" 出现在类型后表示默认隐式解析,出现在实例后表示强制拆包。
  2. 这两个符号都和swift中的optional类型相关,optional类型是swift语言强调安全性的一种方式,某个变量可否为空,应该是逻辑上决定的,而不是不可预知不可控的
  3. if-let结构与optional类型值的结合使用,可以编写出优化安全的代码

元组

元组是不同数据类型的集合,可通过下标或关键字获取元素。

申明元组

var a1 = (1,15,6.0,"hello")
print(a1)
//指定元组中的类型
var b1:(Int,String) = (10,"swift")
print(b1)

//空元组
var c1 = ()

//元组取值
print(a1.3)//hello

//赋值 值传递 copy一份
var d1 = ("hello",true)

var e1 = d1
d1.0 = "val"

var f1 = (name1:"hello",name2:true)
print(f1.name1)

var g1:(name1:Int,name2:String) = (100,"hello")
print(g1.name1)

拆分元组

let (n1,n2) = ("swift",2.0)
print(n1)


let (_,_,n3) = ("swift",2.0,true)
print(n3)

传递元组

//元组可以作为参数 和 返回值 函数多返回值
var data = (1,"hello",true)
func handle(param:(Int,String,Bool))->(Int,String,Bool) {
    var data_param = param
    data_param.0 = 300
    data_param.1 = param.1 + " lily"
    data_param.2 = false
    return data_param
    
}

let resut = handle(param: data)
print(resut)