iOS学习笔记(3)-Swift概览

上次找到一个iOS实战教程,用的是swift,看了下确实比obj-c要方便不少,于是看了《swift programming language》,总结下基础语法,swift版本为2.2。

1 数据类型

  • 常量和变量: 用let声明常量,用var声明变量,常量只能赋值一次。
  • 类型推断: 定义变量的时候可以不用声明类型,swift可以自动推断。不过要注意的是,如果初始值信息不够或者没有初始值,需要声明变量类型,见下面例子。
  • 类型转换: 值不会隐式转换为其他类型,比如下面的字符串拼接,可以用+拼接字符串,但是整数需要先显示转换为String类型才可以拼接。另外,也可以通过反斜杠加括号的方式拼接。需要注意的是,不像python等其他语言,Swift的字符串必须用""而不是''括起来。
  • 元组: 通过()创建,元组内部的元素数据类型可以任意,不需要一样。
  • 数组和字典:数组和字典统一通过[]来创建。空的数组和字典需要使用初始化语法。如果类型信息可以推断出来,可以省掉类型信息。
  • 可选类型: 可选类型用来处理值可能缺失的情况,这是swift独有的,C或者objective-C中都没有这个类型。定义的时候在类型后面加个?表示可选类型。注意,nil不能用于非可选的变量,如果变量有可能缺失值,则需要声明为可选类型。可选类型如果声明的时候没有赋值,则自动会被设置为nil。
  • 类型别名: 可以通过typealias关键字来给已有类型定义一个别名。
//1 常量和变量
let apples = 3
apples = 4 //错误,常量只能赋值一次
var orange = 5
orange = 6 //正确

let orangesAreOrange = true 
let turnipsAreDelicious = false

//2 类型推断
let implicitInteger = 70
let implicitDouble = 70.0
let explicitDouble: Double = 70 //显示声明类型,因为根据初始值无法确定变量类型

//3 类型转换
let desc = "Apple num: "
let descLabel = desc + String(apples)
let appleSummary = "I have \(apples) apples."


//4 元组
let http404Error = (404, "Not Found") //元组里的数据类型可以任意,不需要一致

//5 数组和字典
var shoppingList = ["catfish", "water", "tulips"]
shoppingList[1] = "bottle of water"
 
var occupations = [
    "Malcolm": "Captain",
    "Kaylee": "Mechanic",
]
occupations["Jayne"] = "Public Relations"

let emptyArray = [String]() //不加类型信息 let emptyArray = []
let emptyDictionary = [String: Float]() //不加类型信息 let emptyDictionary = [:]

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

oranges = nil //错误
var surveyAnswer: String?// surveyAnswer 被自动设置为 nil

//7 类型别名
typealias AudioSample = UInt16
var maxAmplitudeFound = AudioSample.min

2 控制流

与其他语言一样,有 if...else..., while, repeat...while, for...in

  • 括号问题: 循环或判断语句的括号可以省略,如下面的for...in,但是语句体的花括号{}必须有。
  • 强制解析和可选绑定: 在确定可选类型有值的情况下,使用!可以强制解析可选类型,也使用可选绑定来判断可选类型是否有值以及解析出可选类型的值。
  • 隐式解析可选类型: 有些可选类型在第一次被赋值后可以确定总会有值,这时候可以将可选类型定义为隐式解析可选类型,隐式解析可选类型方式为将类型后面的?改为!
  • switchif: switch语句支持任意类型的数据和各种操作,也不需要在每个case后面加break。还有if语句的判断必须是Bool类型,不能像其他语言那样可以直接拿整数值进行判断。
//1 括号问题
let individualScores = [75, 43, 103, 87, 12]
var teamScore = 0
for score in individualScores {
    if score > 50 {
        teamScore += 3
    } else {
        teamScore += 1
    }
}
print(teamScore)

//2 强制解析和可选绑定
let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)
if convertedNumber != nil {
     print("convertedNumber has an integer value of \(convertedNumber!).")
}
if let actualNumber = Int(possibleNumber) { //Int
    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"


//3 可选类型/隐式解析可选类型
let possibleString: String? = "An optional string."
let forcedString: String = possibleString! // 需要惊叹号来获取值
let assumedString: String! = "An implicitly unwrapped optional string." 
let implicitString: String = assumedString // 不需要感叹号

//4 switch语句不用在每个case后面加break,if判断必须是Bool类型
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.")
}

let i = 1 
if i {
   //编译错误
}
if i == 1 {
  //编译成功 
}

3 函数

  • 使用func来声明函数,使用->来指定函数返回值的类型,函数可以带有可变个数的参数(可变参数后面带...)。
  • 函数可以嵌套函数。函数也可以作为参数和另一个函数的返回值。
//1 函数声明
func sumOf(numbers: Int...) -> Int {
    var sum = 0
    for number in numbers {
        sum += number
    }
    return sum 
}
sumOf()
sumOf(42, 597, 12)

//2 函数作为参数
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, 17, 12]
hasAnyMatches(numbers, condition: lessThanTen)

4 对象和类 & 枚举和结构体

  • 使用class来创建一个类,类中属性和常量声明普通变量和常量声明,只是它们属于这个类。引用实例变量用self关键字,调用父类方法用super关键字。属性也可以有gettersetter
  • 构造函数为init,析构函数为deinit(注意后面没有括号),不需要func关键字。
  • 类之间继承用:,子类覆盖父类方法需要用override关键字。
  • 结构体和类相似,只是传参的时候结构体传的是值,类是传引用。
//1 类
class NamedShape {
    var numberOfSides: Int = 0
    var name: String
    init(name: String) {
        self.name = name
    }
    deinit { 
        print("deinit")
    }
    func simpleDescription() -> String {
        return "A shape with \(numberOfSides) sides."
    } 
}


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 triagle with sides of length \(sideLength)."
    }
}
let optionalSquare: EquilateralTriangle? = EquilateralTriangle(sideLength: 2.5, name: "optional square")
let sideLength = optionalSquare?.sideLength //处理可选变量的新语法,如果变量为nil,则返回nil,否则返回问号后面的值。注意,整个表达式返回的也是可选值。

//2 枚举和结构体
 enum Suit {
     case Spades, Hearts, Diamonds, Clubs
     func simpleDescription() -> String {
         switch self {
         case .Spades:
             return "spades"
         case .Hearts:
             return "hearts"
         case .Diamonds:
             return "diamonds"
         case .Clubs:
             return "clubs"
         }
     } 
 }
 let hearts = Suit.Hearts
 let heartsDescription = hearts.simpleDescription()

 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()

5 协议和扩展

  • 使用protocol声明协议,extension声明扩展。协议有点类似接口,而扩展用来为已有类添加新的功能。
  • 类,结构体和枚举都可以实现协议。注意结构体中的方法需要声明为mutating,用于标记该方法会修改结构体。而类中的方法不需要,因为类中方法总是可以修改类属性。
//1 协议声明
protocol ExampleProtocol {
    var simpleDescription: String { get }
    mutating func adjust()
}

//2 类实现协议
class SimpleClass: ExampleProtocol {
    var simpleDescription: String = "A very simple class."
    var anotherProperty: Int = 69105
    func adjust() {
        simpleDescription += "  Now 100% adjusted."
    }
}
var a = SimpleClass()
a.adjust()
let aDescription = a.simpleDescription
 
//3 结构体实现协议
struct SimpleStructure: ExampleProtocol {
    var simpleDescription: String = "A simple structure"
    mutating func adjust() {
        simpleDescription += " (adjusted)"
    }
}
var b = SimpleStructure()
b.adjust()
let bDescription = b.simpleDescription

//4 扩展Int,添加一个测试函数。
extension Int: ExampleProtocol {
    var simpleDescription: String {
        return "The number \(self)"
    }
    mutating func adjust() {
        self += 42 
    }
}
print(7.simpleDescription)

6 错误捕获

  • 使用throws关键字声明一个函数可能抛出异常,使用do...catch关键字捕获函数。
enum PrinterError: ErrorType {
    case OutOfPaper
    case NoToner
    case OnFire
}

func sendToPrinter(printerName: String) throws -> String {
    if printerName == "Never Has Toner" {
        throw PrinterError.NoToner
    }
    return "Job sent"
}

do {
    let printerResponse = try sendToPrinter("Bi Sheng")
    print(printerResponse)
} catch {
    print(error)
}

7 泛型

  • 泛型用尖括号<>来标识,跟Java里面一样。
func repeatItem(item: Item, numberOfTimes: Int) -> [Item] {
     var result = [Item]()
     for _ in 0..

参考资料

  • A Swift Tour
  • Swift 初见

你可能感兴趣的:(iOS学习笔记(3)-Swift概览)