Swift语言学习日志–总览篇
写在前面:这篇文章是关于Swift语言的一个大概全貌的基本了解,是基于文尾的链接写的,写的比较简略,看完之后可以开始动手写一些简单的Swift代码,详细的各个知识点后续再更新
变量与常量
定义
var myVariable = 42
myVariable = 50
let myConstant = 42
var
表示变量 let
表示常量
let explicitDouble: Double = 70
带有显式定义的类型的常量
类型转换
let label = "The width is "
let width = 94
let widthLabel = label + String(width)
True
let label = "The width is "
let width = 94
let widthLabel = label + width
False
在Swift语言中没有隐式转换 需要转换只能是显示转换
let apples = 3
let oranges = 5
let appleSummary = "I have \(apples) apples."
let fruitSummary = "I have \(apples + oranges) pieces of fruit."
\()
可以进行字符串中的计算以及表达式的使用
多行字符串
let quotation = """
I said "I have \(apples) apples."
And then I said "I have \(apples + oranges) pieces of fruit."
"""
多行字符串使用""" """
字典和数组
var shoppingList = ["catfish", "water", "tulips"]
shoppingList[1] = "bottle of water"
print(shoppingList)
//["catfish", "bottle of water", "tulips"]
var occupations = [
"Malcolm": "Captain",
"Kaylee": "Mechanic",
]
occupations["Jayne"] = "Public Relations"
print(occupations)
/*
[
"Malcolm": "Captain",
"Kaylee": "Mechanic",
"Jayne":"Public Relations"
]
*/
key-value key可以用来检索,不一定是String类型
let emptyArray = [String]()
let emptyDictionary = [String: Float]()
创建空数组或字典
控制流
for-in结构
let individualScores = [75, 43, 103, 87, 12]
var teamScore = 0
for score in individualScores {
if score > 50 {
teamScore += 3
} else {
teamScore += 1
}
}
print(teamScore)
// Prints "11"
这里score的默认为let常量,不可以在循环中改变或者赋值,如果需要赋值或者改变的话需要这样写:
for var score in individualScores{
......
score = 5
}
这样就可以给他赋值了
可选值的使用
var optionalString: String? = "Hello"
print(optionalString == nil)
// Prints "false"
var optionalName: String? = "John Appleseed"
var greeting = "Hello!"
if let name = optionalName {
greeting = "Hello, \(name)"
}
这里String?
相当于一种新类型,表示可以为空,运用这种类型时要注意检查它是否为空,同时输出时直接输出得到的结果和一般的字符串不一样
print(optinalString)
//optinal("Hello")
如果要得到正常输出请使用
print(optinalString!)
//Hello
最后这段代码的意思等同于
if let name = optionalName {
greeting = "Hello, \(name)"
}
//等同于
if optinalName != nil {
let name = optianlName
greeting = "Hell0,\(name)"
}
处理可选值的??方式
let nickName: String? = nil
let fullName: String = "John Appleseed"
let informalGreeting = "Hi \(nickName ?? fullName)"
switch-case结构
这里第三个Case中表示如果x并且x中符合where后面的布尔表达式(x.hasSuffix()是一个函数返回布尔值)则执行case后面的代码
let vegetable = "red pepper"
switch vegetable {
case "celery":
print("Add some raisins and make ants on a log.")
case "cucumber", "watercress":
print("That would make a good tea sandwich.")
case let x where x.hasSuffix("pepper"):
print("Is it a spicy \(x)?")
default:
print("Everything tastes good in soup.")
}
// Prints "Is it a spicy red pepper?"
字典中的for-in结构
对字典的迭代循环
let interestingNumbers = [
"Prime": [2, 3, 5, 7, 11, 13],
"Fibonacci": [1, 1, 2, 3, 5, 8],
"Square": [1, 4, 9, 16, 25],
]
var largest = 0
for (kind, numbers) in interestingNumbers {
for number in numbers {
if number > largest {
largest = number
}
}
}
//kind为标签 numbers为值数组
print(largest)
// Prints "25"
范围表示
m..<n
表示范围[m,n)m...n
表示范围[m,n]
var total = 0
for i in 0..<4 {
total += i
}
print(total)
// Prints "6"
功能和闭包
函数的声明
函数中的输入参数带有标签(名字)和类型,调用的时候要记得带上函数的标签来使用如下:
func greet(person: String, day: String) -> String {
return "Hello \(person), today is \(day)."
}
greet(person: "Bob", day: "Tuesday")
如果确实为不需要标签,我们可以使用_
来表示
func greet(_ person: String, on day: String) -> String {
return "Hello \(person), today is \(day)."
}
greet("John", on: "Wednesday")
函数需要返回多个值时,可以使用元组来完成
func calculateStatistics(scores: [Int]) -> (min: Int, max: Int, sum: Int) {
var min = scores[0]
var max = scores[0]
var sum = 0
for score in scores {
if score > max {
max = score
} else if score < min {
min = score
}
sum += score
}
return (min, max, sum)
}
let statistics = calculateStatistics(scores: [5, 3, 100, 3, 9])
print(statistics.sum)
// Prints "120"
print(statistics.2)
// Prints "120"
函数也可以嵌套使用
func returnFifteen() -> Int {
var y = 10
func add() {
y += 5
}
add()
return y
//y 15
}
returnFifteen()
函数可以使用函数作为返回值,类似于C++中的函数指针
func makeIncrementer() -> ((Int) -> Int) {
func addOne(number: Int) -> Int {
return 1 + number
}
return addOne
}
var increment = makeIncrementer()
increment(7)
当然函数也可以作为参数
func hasAnyMatches(list: [Int], condition: (Int) -> Bool) -> Bool {
for item in list {
if condition(item) {
return true
}
}
return false
}
func lessThanTen(number: Int) -> Bool {
return number < 10
}
var numbers = [20, 19, 7, 12]
hasAnyMatches(list: numbers, condition: lessThanTen)
闭包的使用
numbers.map({ (number: Int) -> Int in
let result = 3 * number
return result
})
对象和类
类的创建,init为初始化,self类本身,deinit创建取消初始化程序,override为重写覆盖不可省略
class Square: NamedShape {
var sideLength: Double
init(sideLength: Double, name: String) {
self.sideLength = sideLength
super.init(name: name)
numberOfSides = 4
}
func area() -> Double {
return sideLength * sideLength
}
override func simpleDescription() -> String {
return "A square with sides of length \(sideLength)."
}
}
let test = Square(sideLength: 5.2, name: "my test square")
test.area()
test.simpleDescription()
get和set为变量设置属性,这种方法还可以使关联变量保持一致
class EquilateralTriangle: NamedShape {
var sideLength: Double = 0.0
init(sideLength: Double, name: String) {
self.sideLength = sideLength
super.init(name: name)
numberOfSides = 3
}
var perimeter: Double {
get {
return 3.0 * sideLength
}
set {
sideLength = newValue / 3.0
}
}
override func simpleDescription() -> String {
return "An equilateral triangle with sides of length \(sideLength)."
}
}
var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")
print(triangle.perimeter)
此处调用perimeter的get函数
// Prints "9.3"
triangle.perimeter = 9.9
此处调用perimeter的set函数
print(triangle.sideLength)
// Prints "3.3000000000000003"
枚举与结构体
枚举
枚举类型中第一个默认值为0,除非如下设置起始值,后面的量递加,与C/C++一样
enum Rank: Int {
case ace = 1
case two, three, four, five, six, seven, eight, nine, ten
case jack, queen, king
func simpleDescription() -> String {
switch self {
case .ace:
return "ace"
case .jack:
return "jack"
case .queen:
return "queen"
case .king:
return "king"
default:
return String(self.rawValue)
}
}
}
let ace = Rank.ace
let aceRawValue = ace.rawValue
结构体
结构体的关键字为struct
与C/C++一样,可以定义不同的变量的结构,其中可以设置一些常用的函数,结构体带有默认的初始化函数,这点与类不一样
struct Card {
var rank: Rank
var suit: Suit
func simpleDescription() -> String {
return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
}
}
let threeOfSpades = Card(rank: .three, suit: .spades)
let threeOfSpadesDescription = threeOfSpades.simpleDescription()
协议和扩展
协议
协议用关键字protocol
来定义,协议是用来约束和规定某些规范的,当类或者是结构体接受某种协议时,与其继承父类属性类似,必须遵从协议的规范,如下面的简单的协议,协议表明,其中必须有一个名为simpleDescription
的变量,其类型为String
,还必须有一个函数adjust
protocol ExampleProtocol {
var simpleDescription: String { get }
mutating func adjust()
}
如下类接受了上述的协议,则其中必须上述要素,当在xcode中编写代码时,接受协议而没有按照约定规范书写时,会出现编译错误,此时点击警告中的·FIX
按钮,则xcode会自动添加规范代码
class SimpleClass: ExampleProtocol {
var simpleDescription: String = "A very simple class."
var anotherProperty: Int = 69105
func adjust() {
simpleDescription += " Now 100% adjusted."
}
}
扩展
扩展用关键字extension
来扩展已经定义好的类或者结构体,增加我们需要的功能,如下代码中扩展Int
中的功能,增加了协议ExampleProtocol
,扩展了我们需要的功能
extension Int: ExampleProtocol {
var simpleDescription: String {
return "The number \(self)"
}
mutating func adjust() {
self += 42
}
}
print(7.simpleDescription)
// Prints "The number 7"
错误处理
错误处理是为了处理一些错误情况,用关键字throw
来定义,try catch
类处理错误,如果没有发生错误则正常执行try
模块,否则调其catch
模块处理错误。如下代码先定义了三个错误类型,函数中使用错误处理模块,如果出现错误情况,则向系统抛出异常
enum PrinterError: Error {
case outOfPaper
case noToner
case onFire
}
func send(job: Int, toPrinter printerName: String) throws -> String {
if printerName == "Never Has Toner" {
throw PrinterError.noToner
}
return "Job sent"
}
do {
let printerResponse = try send(job: 1040, toPrinter: "Bi Sheng")
print(printerResponse)
} catch {
print(error)
}
// Prints "Job sent"
范型
范型的使用有利于代码的复用,与C/C++类似,定义以及使用如下
func makeArray<Item>(repeating item: Item, numberOfTimes: Int) -> [Item] {
var result = [Item]()
for _ in 0..<numberOfTimes {
result.append(item)
}
return result
}
makeArray(repeating: "knock", numberOfTimes: 4)
参考Swift官方文档:
Swift Tour文档