当前位置: 首页 > news >正文

Swift 入门(一 - 基础语法)

常量和变量

let maximumNumberOfLoginAttempts = 10
var currentLoginAttempt = 0
var x = 0.0, y = 0.0, z = 0.0

类型注解

var welcomeMessage: String
var red, green, blue: Double

一般来说很少需要写类型注解。如果在声明常量或变量的时候赋来了一个初始值,Swift可以推断出这个量的类型。

变量和常量的命名

可以包含任何字符,包括Unicode字符,但不能数学符号、箭头,保留的(或非法的)Unicode码位,连线与制表符。也不能以数字开头,但是可以在常量与变量名的其他地方包含数字。

let π = 3.14159
let 你好 = "你好世界"
let 🐶🐮 = "dogcow"

一旦确定了常量或者变量的类型,就不能使用相同的名字在此进行声明,或者改变其存储的值的类型。同时,也不能讲常量和变量进行互转。

如果你需要使用与 Swift 保留关键字相同的名称作为常量或者变量名,你可以使用反引号(`)将关键字包围的方式将其作为名字使用。无论如何,你应当避免使用关键字作为常量或变量名,除非你别无选择。

var friendlyWelcome = "Hello!"
friendlyWelcome = "Bonjour!"
// friendlyWelcome 现在是 "Bonjour!"
let languageName = "Swift"
languageName = "Swift++"
// 这会报编译时错误 - languageName 不可改变

输出常量和变量

print(friendlyWelcome)
// 输出“Bonjour!
print("The current value of friendlyWelcome is \(friendlyWelcome)")
// 输出“The current value of friendlyWelcome is Bonjour!”

print(_:separator:terminator:) 是一个用来输出一个或多个值到适当输出区的全局函数。如果你用 Xcode,print(_:separator:terminator:) 将会输出内容到“console”面板上。separator 和 terminator 参数具有默认值,因此你调用这个函数的时候可以忽略它们。默认情况下,该函数通过添加换行符来结束当前行。如果不想换行,可以传递一个空字符串给 terminator 参数--例如,print(someValue, terminator:"") 。

分号

Swift 并不强制要求你在每条语句的结尾处使用分号,但打算在同一行内写多条独立语句时,必须要用分号。

let cat = "🐱"; print(cat)
// 输出“🐱”

整数

let minValue = UInt8.min  // minValue 为 0,是 UInt8 类型
let maxValue = UInt8.max  // maxValue 为 255,是 UInt8 类型

UInt:无符号类型

浮点数

  • Double 表示64位浮点数。当你需要存储很大或者很高精度的浮点数时请使用此类型。
  • Float 表示32位浮点数。精度要求不高的话可以使用此类型。

Double 精确度很高,至少有15位数字,而 Float 只有6位数字。选择哪个类型取决于你的代码需要处理的值的范围,在两种类型都匹配的情况下,将优先选择 Double

类型安全和类型判断

let meaningOfLife = 42
// meaningOfLife 会被推测为 Int 类型
let pi = 3.14159
// pi 会被推测为 Double 类型
let anotherPi = 3 + 0.14159
// anotherPi 会被推测为 Double 类型

数值型字面量

let decimalInteger = 17
let binaryInteger = 0b10001       // 二进制的17
let octalInteger = 0o21           // 八进制的17
let hexadecimalInteger = 0x11     // 十六进制的17
  • 1.25e2 表示 1.25 × 10^2,等于 125.0
  • 1.25e-2 表示 1.25 × 10^-2,等于 0.0125
  • 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

数值型类型转换

整数转换
let cannotBeNegative: UInt8 = -1
// UInt8 类型不能存储负数,所以会报错
let tooBig: Int8 = Int8.max + 1
// Int8 类型不能存储超过最大值的数,所以会报错
let twoThousand: UInt16 = 2_000
let one: UInt8 = 1
let twoThousandAndOne = twoThousand + UInt16(one)

现在两个数字的类型都是 UInt16,可以进行相加。目标常量 twoThousandAndOne 的类型被推断为 UInt16,因为它是两个 UInt16 值的和。

整数和浮点数转换

必须显式制定类型:

let three = 3
let pointOneFourOneFiveNine = 0.14159
let pi = Double(three) + pointOneFourOneFiveNine
// pi 等于 3.14159,所以被推测为 Double 类型
let integerPi = Int(pi)
// integerPi 等于 3,所以被推测为 Int 类型

当用这种方式来初始化一个新的整数值时,浮点值会被截断。也就是说 4.75 会变成 4-3.9 会变成 -3。

结合数字类常量和变量不同于结合数字类字面量。字面量 3 可以直接和字面量 0.14159 相加,因为数字字面量本身没有明确的类型。它们的类型只在编译器需要求值的时候被推测。

类型别名

typealias AudioSample = UInt16
var maxAmplitudeFound = AudioSample.min
// maxAmplitudeFound 现在是 0

布尔值

let orangesAreOrange = true
let turnipsAreDelicious = false

元组

let http404Error = (404, "Not Found")
// http404Error 的类型是 (Int, String),值是 (404, "Not Found")let (statusCode, statusMessage) = http404Error
print("The status code is \(statusCode)")
// 输出“The status code is 404”
print("The status message is \(statusMessage)")
// 输出“The status message is Not Found”let (justTheStatusCode, _) = http404Error
print("The status code is \(justTheStatusCode)")
// 输出“The status code is 404”print("The status code is \(http404Error.0)")
// 输出“The status code is 404”
print("The status message is \(http404Error.1)")
// 输出“The status message is Not Found”let http200Status = (statusCode: 200, description: "OK")
print("The status code is \(http200Status.statusCode)")
// 输出“The status code is 200”
print("The status message is \(http200Status.description)")
// 输出“The status message is OK”

如果你的数据结构比较复杂,不要使用元组,用类或结构体去建模。

可选类型

使用可选类型(optionals)来处理值可能缺失的情况。可选类型表示两种可能: 或者有值, 你可以解析可选类型访问这个值, 或者根本没有值。

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

因为该构造器可能会失败,所以它返回一个可选类型(optional)Int,而不是一个 Int。一个可选的 Int 被写作 Int? 而不是 Int。问号暗示包含的值是可选类型,也就是说可能包含 Int 值也可能不包含值。(不能包含其他任何值比如 Bool 值或者 String 值。只能是 Int 或者什么都没有。)

nil

var serverResponseCode: Int? = 404
// serverResponseCode 包含一个可选的 Int 值 404
serverResponseCode = nil
// serverResponseCode 现在不包含值

nil 不能用于非可选的常量和变量。如果你的代码中有常量或者变量需要处理值缺失的情况,请把它们声明成对应的可选类型。

var surveyAnswer: String?
// surveyAnswer 被自动设置为 nil

if 语句以及强制解析

if convertedNumber != nil {print("convertedNumber contains some integer value.")
}
// 输出“convertedNumber contains some integer value.”if convertedNumber != nil {print("convertedNumber has an integer value of \(convertedNumber!).")
}
// 输出“convertedNumber has an integer value of 123.”

当你确定可选类型确实包含值之后,你可以在可选的名字后面加一个感叹号(!)来获取值。

可选绑定

使用可选绑定 来判断可选类型是否包含值,如果包含就把值赋给一个临时常量或者变量。可选绑定可以用在 if 和 while 语句中,这条语句不仅可以用来判断可选类型中是否有值,同时可以将可选类型中的值赋给一个常量或者变量。

if let constantName = someOptional {statements
}
if let actualNumber = Int(possibleNumber) {print("\'\(possibleNumber)\' has an integer value of \(actualNumber)")
} else {print("\'\(possibleNumber)\' could not be converted to an integer")
}
// 输出“'123' has an integer value of 123”

这段代码可以被理解为:如果 Int(possibleNumber) 返回的可选 Int 包含一个值,创建一个叫做 actualNumber 的新常量并将可选包含的值赋给它。

如果转换成功,actualNumber 常量可以在 if 语句的第一个分支中使用。它已经被可选类型 包含的 值初始化过,所以不需要再使用 ! 后缀来获取它的值。在这个例子中,actualNumber 只被用来输出转换结果。

if let firstNumber = Int("4"), let secondNumber = Int("42"), firstNumber < secondNumber && secondNumber < 100 {print("\(firstNumber) < \(secondNumber) < 100")
}
// 输出“4 < 42 < 100”if let firstNumber = Int("4") {if let secondNumber = Int("42") {if firstNumber < secondNumber && secondNumber < 100 {print("\(firstNumber) < \(secondNumber) < 100")}}
}
// 输出“4 < 42 < 100”

在 if 条件语句中使用常量和变量来创建一个可选绑定,仅在 if 语句的句中(body)中才能获取到值。相反,在 guard 语句中使用常量和变量来创建一个可选绑定。

隐式解析可选类型

有时候在程序架构中,第一次被赋值之后,可以确定一个可选类型总会有值。在这种情况下,每次都要判断和解析可选值是非常低效的,因为可以确定它总会有值。

这种类型的可选状态被定义为隐式解析可选类型(implicitly unwrapped optionals)。把想要用作可选的类型的后面的问号(String?)改成感叹号(String!)来声明一个隐式解析可选类型。

let possibleString: String? = "An optional string."
let forcedString: String = possibleString! // 需要感叹号来获取值let assumedString: String! = "An implicitly unwrapped optional string."
let implicitString: String = assumedString  // 不需要感叹号

如果在隐式解析可选类型没有值的时候尝试取值,会触发运行时错误。和你在没有值的普通可选类型后面加一个惊叹号一样。

if assumedString != nil {print(assumedString!)
}
// 输出“An implicitly unwrapped optional string.”
if let definiteString = assumedString {print(definiteString)
}
// 输出“An implicitly unwrapped optional string.”

如果一个变量之后可能变成 nil 的话请不要使用隐式解析可选类型。如果需要在变量的生命周期中判断是否是 nil 的话,请使用普通可选类型。

错误处理

do {try canThrowAnError()// 没有错误消息抛出
} catch {// 有一个错误消息抛出
}
func makeASandwich() throws {// ...
}do {try makeASandwich()eatASandwich()
} catch SandwichError.outOfCleanDishes {washDishes()
} catch SandwichError.missingIngredients(let ingredients) {buyGroceries(ingredients)
}

在此例中,makeASandwich()(做一个三明治)函数会抛出一个错误消息如果没有干净的盘子或者某个原料缺失。因为 makeASandwich() 抛出错误,函数调用被包裹在 try 表达式中。将函数包裹在一个 do 语句中,任何被抛出的错误会被传播到提供的 catch 从句中。

如果没有错误被抛出,eatASandwich() 函数会被调用。如果一个匹配 SandwichError.outOfCleanDishes 的错误被抛出,washDishes() 函数会被调用。如果一个匹配 SandwichError.missingIngredients 的错误被抛出,buyGroceries(_:) 函数会被调用,并且使用 catch 所捕捉到的关联值 [String] 作为参数。

断言和先决条件

断言和先决条件是在运行时所做的检查。可以用他们来检查在执行后续代码之前是否一个必要的条件已经被满足了。如果断言或者先决条件中的布尔条件评估的结果为 true(真),则代码像往常一样继续执行。如果布尔条件评估结果为 false(假),程序的当前状态是无效的,则代码执行结束,应用程序中止。

let age = -3
assert(age >= 0, "A person's age cannot be less than zero")
// 因为 age < 0,所以断言会触

如果不需要断言信息,可以忽略:

assert(age >= 0)

如果代码已经检查了条件,可以使用 assertionFailure(_:file:line:) 函数来表明断言失败了:

if age > 10 {print("You can ride the roller-coaster or the ferris wheel.")
} else if age > 0 {print("You can ride the ferris wheel.")
} else {assertionFailure("A person's age can't be less than zero.")
}

强制执行先决条件

当一个条件可能为假,但是继续执行代码要求条件必须为真时,需要使用先决条件。例如使用先决条件来检查下标越界,或者检查是否将一个正确的参数传给函数。

可以使用全局precondition(_:_:file:line:)函数来写一个先决条件。向这个函数传入一个结果为 true 或者 false 的表达式以及一条信息,当表达式的结果为 false 的时候这条信息会被显示:

// 在一个下标的实现里...
precondition(index > 0, "Index must be greater than zero.")
http://www.dtcms.com/a/407887.html

相关文章:

  • GCMSCNN 模块:气相色谱 - 质谱数据的分子特征提取方案
  • 简单网页制作模板图片福州seo兼职
  • 新德通:深耕光通信领域,打造全场景网络连接解决方案
  • 汽车网站模板免费下载做网站的注意点
  • COMSOL建立Voronoi泰森多边形二维模型
  • springboot - 邮箱验证码登录
  • 百度收录什么网站京东网站建设的策划书
  • 进程的概念(上)
  • 高仿id97网站模板涞水县建设局网站
  • 网站数据库结构被删了怎么办一键优化为什么不能100
  • 余姚建设网站的公司网站new图标
  • 重庆网站推广流程php5mysql网站开发实例精讲
  • 小型商城网站没技术怎么做网站
  • 网络公司网站模版视频网站做app开发的
  • 北京建站管理系统开发中企动力中山分公司网站
  • 手机端企业网站模板网页怎么设计与制作
  • 代码随想录算法训练营第21天 -- 回溯4 || 491.非递减子序列 / 46.全排列 /47.全排列 II
  • 绍兴公司网站建设 中企动力绍兴wordpress edc
  • 怎么找到做网站的客户岳阳网站建设团队
  • Android匿名共享内存突破Binder传递大小限制
  • 网络网站推广首荐乐云seowordpress关键字内链
  • 元气森林宇宙大赛——第五届高校创新挑战赛
  • 51的烧录与调试
  • 如何解决 pip install 安装报错 ModuleNotFoundError: No module named ‘tokenizers’ 问题
  • 数字门店的未来蓝图:从水果店到餐厅再到超市
  • 做动态图片下载哪个网站好百度高级搜索网址
  • Mnn模型转换
  • 在Windows中通过网络共享文件
  • 网站开发入门习题优化大师兑换码
  • 保定网站制作方案四川住房和城乡建设厅进不去网站