讓你 2 小時學會 Swift
來自: http://my.oschina.net/mengshuai/blog/614396?fromerr=9Zgmw1NU
過年不能閑著,一邊學習Swift,一邊寫筆記,相信在有一定其他語言基礎的情況下用1.5小時看完該文章即可掌握。然后再花30分鐘打開XCode寫個Demo.
生命中拿出2小時來認識一門語言,很值吧!
筆記共分為兩部分,一Swift基礎知識,二使用Xcode開發一個軟件
[TOC]
</div>
swift基礎知識
變量和常量
//定義變量 var myVariable = 123//定義常量 let myConstantVariable = 123
// 隱式指定整數類型 var anInteger = 2
// 明確指定整數類型 let anExplicitInteger :Int = 2</pre>
元組
let aTuple = (1, "Yes") let anotherTuple = (aNumber: 1, aString: "Yes") let theOtherNumber = anotherTuple.aNumber // = 1其他用法
let http404Error = (404, "Not Found") let (statusCode, statusMessage) = http404Error print("The status code is \(statusCode)")更多用戶函數返回值,返回兩個以上的值,跟golang很像
數組
var arrayOfIntegers : [Int] = [1,2,3] // 隱式指定 var implicitArrayOfIntegers = [1,2,3]// 也可以創建空數組,但必須提供其類型 let anotherArray = Int
//使用 append 函數向數組的末尾追加對象 myArray.append(4)
//數組中的任意位置插入對象 myArray.insert(5, atIndex: 0)</pre>
字典
字典是一種將鍵映射到值的類型,類似Java的Map,PHP的數組
var crew = [ "Caption": "Jean-Luc Picard", "First officer": "William Riker", "Second Officer": "Data" ];crew["Captain"] // = "Jean-Luc Picard"</pre>
控制流
if
if 1+1 == 2 { println("The math checks out") }for-in
let loopingArray = [1,2,3,4,5] var loopSum = 0 for number in loopingArray { loopSum += number } loopSum // = 15var firstCounter = 0 for index in 1 ..< 10 { firstCounter++ } // 循環9次var secondCounter = 0 for index in 1 ... 10 { // 注意是三個句點,不是兩個 secondCounter++ } // 循環10次
var sum = 0 for var i = 0; i < 3; i++ { sum += 1 } sum // = 3</pre>
while
var countDown = 5 while countDown > 0 { countDown-- } countDown // = 0var countUP = 0 do { countUp++ } while countUp < 5 countUp // = 5if-let
可以用 if-let 語句檢查一個可選變量是否包 含值。如果包含,則將這個值指定給一個常量變量,然后運行某段代碼。這樣可以減少很 多行代碼,同時又能夠保證安全性
var conditionalString : String? = "a string" if let theString = conditionalString? { println("The string is '\(theString)'") } else { println("The string is nil") } // 輸出 "The string is 'a string'"函數
單返回值簡單函數
兩個參數一個返回值,都為Int
func thirdFunction(firstValue: Int, secondValue: Int) -> Int { return firstValue + secondValue } thirdFunction(1, 2)使用元組多返回值
func fourthFunction(firstValue: Int, secondValue: Int) -> (doubled: Int, quadrupled: Int) { return (firstValue 2, secondValue 4) } fourthFunction(2, 4)// 用數字訪問: fourthFunction(2, 4).1 // = 16
// 其他相同,只是使用了名字: fourthFunction(2, 4).quadrupled // = 16</pre>
外部名稱調用
在定義函數時,可以為參數指定名字。當無法馬上明白每個參數的用途時,這一功能會非 常有用。可以像下面這樣來定義參數名字:
func addNumbers(firstNumber num1 : Int, toSecondNumber num2: Int) -> Int { return num1 + num2 } addNumbers(firstNumber: 2, toSecondNumber: 3) // = 5在為參數創建名字時,就是為參數創建一個內部名字和一個外部名字,一個參數的內部名字應當與外部名字相同。將同一個名字輸 入兩次也沒有什么問題,但的確有一種簡便的方式來定義一個外部名字與內部名字相同的 參數——就是在參數名之前放一個 # 符號
func multiplyNumbers(#firstNumber: Int, #multiplier: Int) -> Int { return firstNumber * multiplier } multiplyNumbers(firstNumber: 2, multiplier: 3) // = 6將函數用作變量
var numbersFunc: (Int, Int) -> Int; // numbersFunc現在可以存儲任何接受兩個Int并返回一個Int的函數numbersFunc = addNumbers numbersFunc(2, 3) // = 5</pre>
閉包closure
sort需要傳遞一個閉包作為參數
var numbers = [2,4,34,6,33,1,67,20] var numbersSorted = numbers.sort( { (first, second ) -> Bool inreturn first < second})</pre>
閉包只包含一行代碼,可以省略 return 關鍵字
var numbersSorted = numbers.sort( { $1 > $0}) print(numbersSorted)如果一個閉包是函數調用中的最后一個參數,可以將它放在括號外面。這純粹是為 了提高可讀性,不會改變閉包的工作方式
var numbersSorted = numbers.sort(){ $1 > $0} print(numbersSorted)閉包放在變量里面
var comparator = {(a: Int, b: Int) in a < b} comparator(1, 2) // = true對象
定義
class Vehicle { var color: String? var maxSpeed = 80 func description() -> String { return "A \(self.color) vehicle" } func travel() { print("Traveling at \(maxSpeed) kph") } }使用
var redVehicle = Vehicle() redVehicle.color = "Red" redVehicle.maxSpeed = 90 redVehicle.travel() // 輸出"Traveling at 90 kph" redVehicle.description() // = "A Red vehicle"繼承
要重寫一個函數,要在子類中重新聲明它,并添加 override 關鍵字
class Car: Vehicle { // 繼承類可以重寫函數 override func description() -> String { var description = super.description() return description + ", which is a car" } }在一個被重寫的函數中,可以通過 super 回調該函數在父類中的版本
override func description() -> String { var description = super.description() return description + ", which is a car" }初始化與反初始化
class InitAndDeinitExample { // 指定的初始化器(也就是主初始化器) init() { print("I've been created!") } // 便捷初始化器,是調用上述指定初始化器所必需的 convenience init (text: String) { self.init() // 這是必需的 print("I was called with the convenience initializer!") } // 反初始化器 deinit { print("I'm going away!") } }var example : InitAndDeinitExample? // 使用指定的初始化器 example = InitAndDeinitExample() // 輸出"I've been created!" example = nil // 輸出"I'm going away" // 使用便捷初始化器 example = InitAndDeinitExample(text: "Hello") // 輸出"I've been created!" // 然后輸出"I was called with the convenience initializer"</pre>
創建一個可以返回 nil 的初始化器(也稱為可以失敗的初始化器),就在 init 關鍵字的后面放上一個問號,并在初始化器確定它不能成功地構造該對象時,使用 return nil:
convenience init? (value: Int) { self.init() if value > 5 { // 不能初始化這個對象;返回nil,表示初始化失敗 return nil } }在使用一個可以失敗的初始化器時,任何可以在其中存儲該結果的變量都是可選的:
let failableExample = InitAndDeinitExample(value: 6) // = nil協議
使用協議的好處是,可以利用 Swift 的類型體系來引用任何遵守某一給定協議的對象,個人現在理解為是Interface概念。
protocol Blinking{ var isBlinking:Bool{get} var blinkSpeed: Double { get set } func startBlinking(blinkSpeed: Double) -> Void}
class Light:Blinking{ var isBlinking = false var blinkSpeed = 1.2 func startBlinking(blinkSpeed: Double) { print("now my speed is (self.blinkSpeed)") }
}</pre>
擴展
extension Int { var doubled : Int { return self 2 } func multiplyWith(anotherNumber: Int) -> Int { return self anotherNumber } }2.doubled // = 4 4.multiplyWith(32) // = 128</pre>
還可以利用擴展使一個類型遵守一個協議
extension Int : Blinking { var isBlinking : Bool { return false; } var blinkSpeed : Double { get { return 0.0; } set { // 不做任何事情 } } func startBlinking(blinkSpeed : Double) { print("I am the integer \(self). I do not blink.") } } 2.isBlinking // = false 2.startBlinking(2.0) // 輸出"I am the integer 2. I do not blink."訪問控制
在將一個方法或屬性聲明為 public 時,App 中的所有人都能看到它:
// 可供所有人訪問 public var publicProperty = 123//如果將一個方法或屬性聲明為 private,那只能在聲明它的源文件內部看到它: // 只能在這個源文件中訪問 private var privateProperty = 123
// 僅能供本模塊訪問 // 這里的'internal'是默認的,可以省略 internal var internalProperty = 123</pre>
運算符重載
類似C++的運算符重載
class Vector2D { var x : Float = 0.0 var y : Float = 0.0 init (x : Float, y: Float) { self.x = x self.y = y }} func +(left : Vector2D, right: Vector2D) -> Vector2D { let result = Vector2D(x: left.x + right.x, y: left.y + right.y) return result }
let first = Vector2D(x: 2, y: 2) let second = Vector2D(x: 4, y: 1) let result = first + second</pre>
泛型
Swift與Java泛型相同
class Tree <T> { // 'T'現在可以用作一種類型 var value : T var value:T var children : [Tree <T>] = [] init(value : T) { self.value = value } func addChild(value : T) -> Tree <T> { var newChild = Tree<T>(value: value) children.append(newChild) reutrn newChild } }// 整數樹 let integerTree = Tree<Int>(value: 5) // 可以增加包含Int的子樹 integerTree.addChild(10) //用Swift設計程序 | 45 integerTree.addChild(5) // 字符串樹 let stringTree = Tree<String>(value: "Hello") stringTree.addChild("Yes") stringTree.addChild("Internets")</pre>
字符串
比較字符串
let string1 : String = "Hello" let string2 : String = "Hel" + "lo" if string1 == string2 { println("The strings are equal") }查找字符串
if string1.hasPrefix("H") { println("String begins with an H") } if string1.hasSuffix("llo") { println("String ends in 'llo'") }數據
let stringToConvert = "Hello, Swift" let data = stringToConvert.dataUsingEncoding(NSUTF8StringEncoding)Swift with cocoa用Xcode開發軟件
打開Xcode 7.2
STEP1
打開Xcode新建Project選擇OSX Application
![]()
?
STEP2
?
STEP3
打開Main.storyboard,在ViewController中拖入Label
?
STEP4
修改ViewController.swift代碼
import Cocoaclass ViewController: NSViewController {
@IBOutlet weak var timestamp:NSTextField! @IBOutlet weak var dateLabel:NSTextField! @IBAction func calc(sender:NSButton){ //將輸入的字符串轉為NSString let string = NSString(string: self.timestamp.stringValue) //轉為double類型 let ts:NSTimeInterval = string.doubleValue //轉換日期 let date = NSDate(timeIntervalSince1970: ts) //日期格式化 let dfmatter = NSDateFormatter() dfmatter.dateFormat="yyyy年MM月dd日" //顯示到Label dateLabel.stringValue = dfmatter.stringFromDate(date) } override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. } override var representedObject: AnyObject? { didSet { // Update the view, if already loaded. } }}</pre>
上述的NSTextField后面的嘆號,它被稱為隱式拆封的可選類型,是一種特殊類型,指出變量可能有值,也可能為nil。Swift運行 環境不喜歡訪問值為nil的變量,因此Swift程序員必須知曉變量的值,尤其在其可能為nil時。將變量聲明為隱式拆封的可選類型相當于告訴Swift編譯器,你承諾在該變量的值為nil時絕 不會訪問它。這是你與編譯器簽訂的一個合約,你必須遵守。如果你不遵守,在變量為nil時訪 問它,將引發運行階段錯誤,導致應用程序停止運行
另外也可以開啟兩個視圖直接拖入例如:
![]()
?
STEP5
鏈接UI與代碼部分,將TextField右鍵,選擇new referencing Outlets點加號指向ViewController,在彈出的選項里面選擇timestamp,同樣方式選擇到label上。
![]()
?
綁定按鈕的click事件
![]()
?
STEP6
點擊上方的三角箭頭運行程序
</div>
?
?
?
?