Learn iOS With Swift 0

789 阅读3分钟

let常量值

let 表示定义好的常量值,并不一定在编译期确定但是的确只能被初始化一次。

let lfkdsk = 1000 // 直接初始化
        let lfkdsk : Int // 没有直接初始化要提供类型推倒
        lfkdsk = 100
        let lfkdsk = 100 + String(1000) // 类型转化要使用显示转换
        let apple = 1000
        let lfkdsk = "lfkdsk have \(apple) apples" // 类比Ruby的${}
        

字典和元组

var shoppingList = ["fuck ","you"]
            var occupations = ["S":"M","F","Y"]
            occupations["F"] = xxx
            // 这些都很好理解
            
// 创建空数组合字典 可以写出类型
            let emptyArray = [String]() // 但是初始化之后就不能再修改了
            let emptyDictionary = [String: Float]()
            

类型可以显示推断的话用:

shoppingList = []
        occupations = [:]
        

条件控制

使用if和switch来进行条件操作,使用for-in、for、while和repeat-while来进行循环。包裹条件和循环变量括号可以省略,但是语句体的大括号是必须的。

后加表示可选变量

let nickName: String? = nil
        let fullName: String = "John Appleseed"
        // 另一种提供默认值的方式
        let informalGreeting = "Hi \(nickName ?? fullName)”
        

Swich语句支持多种类型和表达式,无需break但是不可缺少default:

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.")
            }
        

for-in语句,可设定key-value值的样子:

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
                }
            }
            }
        

while语句:

var n = 2
        while n < 100 {
            n = n * 2
            }
        print(n)
         
        var m = 2
        repeat {
            m = m * 2
            } while m < 100
        print(m)
        // 你可以在循环中使用..<来表示范围。
        var total = 0
        for i in 0..<4 { // 0...<4包含上界
            total += i
            }
        print(total)
        

函数和闭包

func greet(name: String, day: String) -> String {
                return "Hello \(name), today is \(day)."
                }
            greet(name:"Bob", day: "Tuesday")
            

如代码所示,使用参数调用函数,使用->设定返回值(总的来说语法很类似)。

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)
        print(statistics.2)
        

返回多个返回值。

func sumOf(numbers: Int...) -> Int {
            var sum = 0
            for number in numbers {
                sum += number
            }
            return sum
            }
        sumOf()
        sumOf(numbers: 42, 597, 12)
        

可变参数,这个和很多语言都很类似。

可定义函数内函数,作用域包含外界,所以也可以传递函数:

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)
        

函数实际上是一种特殊的闭包:它是一段能之后被调取的代码。闭包中的代码能访问闭包所建作用域中能得到的变量和函数,即使闭包是在一个不同的作用域被执行的 - 你已经在嵌套函数例子中所看到。你可以使用{}来创建一个匿名闭包。使用in将参数和返回值类型声明与闭包函数体进行分离。

numbers.map({
            (number: Int) -> Int in // 匿名闭包 使用 in 区分
            let result = 3 * number
            return result
            })
        
var numbers = [20, 19, 7, 12]
        numbers.map({
            (number :Int) -> (Bool) in
            let result  = number % 2 != 0;
            return result;
            })
        numbers.sort{ $0 > $1}
        print(numbers)
        

类和对象

class Shape {
                var numberOfSides = 0
                func simpleDescription() -> String {
                    return "A shape with \(numberOfSides) sides."
                }
                }
            var shape = Shape()
            shape.numberOfSides = 7
            var shapeDescription = shape.simpleDescription()
            

类中的initdeinit函数是构造函数和析构函数。

子类在类名后添加父类的名称,函数重载需要加override标签。

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
                   }
            }
             
            override func simpleDescription() -> String {
                return "An equilateral triagle with sides of length \(sideLength)."
            }
            }
        var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")
        print(triangle.perimeter)
        triangle.perimeter = 9.9
        print(triangle.sideLength)
        

构造器执行了三步:

  1. 设置子类声明的属性值
  2. 调用父类的构造器
  3. 改变父类的属性值,其他的工作如调用方法,getterssetters也可以在这个阶段完成。
class TriangleAndSquare {
            var triangle: EquilateralTriangle {
                willSet {
                    square.sideLength = newValue.sideLength
                }
            }
            var square: Square {
                willSet {
                    triangle.sideLength = newValue.sideLength
                }
            }
            init(size: Double, name: String) {
                square = Square(sideLength: size, name: name)
                triangle = EquilateralTriangle(sideLength: size, name: name)
            }
            }
        var triangleAndSquare = TriangleAndSquare(size: 10, name: "another test shape")
        print(triangleAndSquare.square.sideLength)
        print(triangleAndSquare.triangle.sideLength)
        triangleAndSquare.square = Square(sideLength: 50, name: "larger square")
        print(triangleAndSquare.triangle.sideLength)
        

处理变量的可选值时,你可以在操作(比如方法、属性和子脚本)之前加?。如果?之前的值是nil,?后面的东西都会被忽略,并且整个表达式返回nil。否则,?之后的东西都会被运行。在这两种情况下,整个表达式的值也是一个可选值。

let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")
        let sideLength = optionalSquare?.sideLength
        

枚举和结构体

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的使用:

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

结构体和类的区别是,结构体是传值,类是传引用。

enum ServerResponse {
            case Result(String, String)
            case Failure(String)
            }
        // 实例和原始值
        let success = ServerResponse.Result("6:00 am", "8:09 pm")
        let failure = ServerResponse.Failure("Out of cheese.")
         
        switch success {
        case let .Result(sunrise, sunset):
            let serverResponse = "Sunrise is at \(sunrise) and sunset is at \(sunset)."
            case let .Failure(message):
            print("Failure...  \(message)")
            }
        

协议和扩展

使用protocol来声明一个协议,就是interface,protocol这种命名真是奇怪。

使用mutating来标记Struct中改变内容的值,使用extension拓展一个类的内容。

protocol ExampleProtocol {
            var simpleDescription: String { get }
            mutating func adjust()
            }
        class SimpleClass: ExampleProtocol {
            var simpleDescription: String = "A very simple class."
            var anotherProperty: Int = 69105
            func adjust() {
                simpleDescription += "  Now 100% adjusted."
            }
            }
        extension Int: ExampleProtocol {
            var simpleDescription: String {
                return "The number \(self)"
            }
            mutating func adjust() {
                self += 42
            }
            }
        print(7.simpleDescription)
        

错误处理

嗯,首先有Error这个Interface来代表错误信息。

函数后标记throw表示可以抛出错误。

错误处理:

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)
            }
        
let printerSuccess = try? sendToPrinter("Mergenthaler")
        let printerFailure = try? sendToPrinter("Never Has Toner")
        

defer绑定函数结尾,写到这,我觉得swift越来越像golang了。

var fridgeIsOpen = false
        let fridgeContent = ["milk", "eggs", "leftovers"]
         
        func fridgeContains(_ food: String) -> Bool {
            fridgeIsOpen = true
            defer {
                fridgeIsOpen = false
            }
             
            let result = fridgeContent.contains(food)
            return result
            }
        fridgeContains("banana")
        print(fridgeIsOpen)
        

泛型

func repeatItem<Item>(repeating item: Item, numberOfTimes: Int) -> [Item] {
                var result = [Item]()
                for _ in 0..<numberOfTimes {
                    result.append(item)
                }
                return result
                }
            repeatItem(repeating: "knock", numberOfTimes:4)
            

返回一个泛型数组,使用where子句实现泛型的特化。