標籤:
最近計劃把Swift語言系統學習一下,然後將MagViewer用這種新語言重構一次,並且最佳化一下,這裡記錄一下Swift的學習筆記。
Swift和Objective-C相比,在文法和書寫形式上做了很多改進,面向開發人員的體驗更好了。比如:
println("Hello, world!")
就可以列印出這個字串,這條語句就是完整的一句,句末不需要添加分號,也不需要引入額外的頭或者庫檔案比如標準輸入輸出等。在全域範圍內書寫的代碼就會作為程式的入口,因此不需要編寫main函數了。
簡單值
用let聲明常量,用var聲明變數。常量的值在編譯的時候不需要知道,但是必須在某個地方真正給它賦值一次,因此常量通常是在一個地方聲明和賦值,在很多地方使用的。
var myVariable = 42myVariable = 50let myConstant = 42
常量和變數的類型必須和所賦的值保持一致。但是,並不用每次都顯示地寫明變數類型,可以只給它們提供值,而讓編譯器去推測它們的類型。上面的例子就是這樣的,也可以顯示地寫明類型:
let explicitDouble: Double = 70
變數不會隱式地進行類型轉換,如果需要類型轉換,必須要開發人員顯示地進行,比如:
let label = "The width is "let width = 94let widthLabel = label + String(width)
在字串中引用變數還有更簡單的方式,就是直接用反斜線加上圓括弧就可以了,比如:
let apples = 3let oranges = 5let appleSummary = "I have \(apples) apples."let fruitSummary = "I have \(apples + oranges) pieces of fruit."
建立數組和字典是用中括弧,擷取數組或字典的值也是。
var shoppingList = ["catfish", "water", "tulips", "blue paint"]shoppingList[1] = "bottle of water" var occupations = [ "Malcolm": "Captain", "Kaylee": "Mechanic",]occupations["Jayne"] = "Public Relations"
建立空數組或空字典時,用初始化文法更為簡便:
let emptyArray = [String]()let emptyDictionary = [String: Float]()
如果元素類型能夠被推理出來,甚至可以省略型別宣告,用[]表示空數組,[:]表示空字典,比如:
shoppingList = []occupations = [:]
控制流程
用if和switch做條件選擇,用for-in,for,while,do-while做迴圈,選擇條件的圓括弧和迴圈變數是可以省略的,但是主體部分的大括弧不能省略:
let individualScores = [75, 43, 103, 87, 12]var teamScore = 0for score in individualScores { if score > 50 { teamScore += 3 } else { teamScore += 1 }}println(teamScore)
在if結構中,條件陳述式的值必須是一個Boolean運算式,這就使得上面的例子中if score {。。。}無法通過,而不是將score值隱式地轉換了。
if和let可以結合使用,這樣可以避免找不到該變數。這種變數相當於可省略的,可省略的變數要麼等於某個值,要麼就是nil(未找到該變數),在變數類型之後加上一個?來標明該變數是可省略的:
var optionalString: String? = "Hello"println(optionalString == nil) var optionalName: String? = "John Appleseed"var greeting = "Hello!"if let name = optionalName { greeting = "Hello, \(name)"}
switch支援任何資料類型以及很多種條件比較運算式(並不限定為整數或者判斷是否相等):
let vegetable = "red pepper"switch vegetable {case "celery": let vegetableComment = "Add some raisins and make ants on a log."case "cucumber", "watercress": let vegetableComment = "That would make a good tea sandwich."case let x where x.hasSuffix("pepper"): let vegetableComment = "Is it a spicy \(x)?"default: let vegetableComment = "Everything tastes good in soup."}
//Is it a spicy red pepper?
default分支是必須的,否則編譯會報錯。
注意是如何用let將滿足一個運算式的值賦給一個常量的。
在進入合適的case之後,程式會跳出switch塊,忽略其他case,因此不需要在每個case最後都加上break;
用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 = 0for (kind, numbers) in interestingNumbers { for number in numbers { if number > largest { largest = number } }}println(largest)
white和do-while用來做迴圈:
var n = 2while n < 100 { n = n * 2}println(n) var m = 2do { m = m * 2} while m < 100println(m)
當然,在迴圈體中可以引用當前的index,要麼用..<來建立index的範圍,或者顯示地聲明初始值,條件陳述式和遞增量,這兩種方法是完全等價的:
var firstForLoop = 0for i in 0..<4 { firstForLoop += i}println(firstForLoop) var secondForLoop = 0for var i = 0; i < 4; ++i { secondForLoop += i}println(secondForLoop)
..<不包含範圍的最大值,而...包含範圍的最大值和最小值
函數和閉包
用func來聲明函數,用->來標明函數的傳回值:
func greet(name: String, day: String) -> String { return "Hello \(name), today is \(day)."}greet("Bob", "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([5, 3, 100, 3, 9])println(statistics.sum)println(statistics.2)
函數也可以接受不定個數的變數,把它們全部包含進一個數組,比如:
func sumOf(numbers: Int...) -> Int { var sum = 0 for number in numbers { sum += number } return sum}sumOf()sumOf(42, 597, 12)
函數是可以嵌套的,內建函式可以訪問外部函數的變數(JS中的閉包)
func returnFifteen() -> Int { var y = 10 func add() { y += 5 } add() return y}returnFifteen()
函數本身也可以作為傳回值被外部函數返回或者作為參數被傳遞:
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(numbers, lessThanTen)
函數其實是閉包的一種特殊情況而已:就是可以在程式的其他地方被調用的代碼塊。閉包裡的代碼可以訪問閉包被建立時所在的範圍鏈上的變數或者函數,不管閉包在執行的時候是在哪個範圍,嵌套函數就很好地說明這個問題了。
編寫匿名閉包可以通過將程式碼封裝含在大括弧裡邊,用in將參數序列及傳回值和函數體分開:
numbers.map({ (number: Int) -> Int in let result = 3 * number return result})
閉包可以寫得更簡潔,如果閉包的類型是已知的,比如某個代理的回調,則可以省略它的參數類型和傳回值類型。
let mappedNumbers = numbers.map({ number in 3 * number })println(mappedNumbers)
變數的引用也可以用數字而非名字,這在短閉包中非常有用。被作為最後一個參數傳遞給函數的閉包可以直接在圓括弧之後出現:
let sortedNumbers = sorted(numbers) { $0 > $1 }println(sortedNumbers)
這一篇就到這裡吧,接下來就要接觸到類相關的文法了。
Swift學習筆記一