Swift3.0學習筆記(一)

開篇

接觸Swift大概有1個多月的時間了,剛開始學習Swift的那段日子真是苦不堪言,面對著一個陌生的語言,真是不知道該從哪里著手開始學習,所以跌跌撞撞地到處碰壁,踩坑。不過經過了這一段時間自己的摸索,以及向各路大神請教,加上網上各種檢索資料,到現在應該算是一腳踏入了Swift的大門了,盡管另外一只腳還在門外,但我會不斷地學習的。
因為我是從Objective-C語言轉過來學習Swift的,所以剛開始接觸Swift的時候,總想著在Swift里怎么實現OC的那些風格習慣,比如說使用OC中的宏定義、PrefixHeader文件等等,我想,會OC的童鞋們在學習Swift時可能也會有和我一樣的想法,因此,在這里我將我學習Swift 的一些經驗分享給大家,可能有些內容我說的不準確,甚至是錯誤的,還請大家幫我指出,另外,我有個和大家一起討論Swift3.0學習的技術交流群185826825,歡迎大家來與我們共同學習!我的本系列其它文章:
Swift3.0學習筆記(二)

寫在前面

當嘗試著用一個自己陌生的語言,去實現一個自己想要達到的功能,是很令人興奮的。所以,在文章的開始,我想先用一個極其簡單的demo作為Swift學習的開始,這個demo的功能是頁面上有一個按鈕,點擊按鈕跳轉到另一個頁面。

大家看這段代碼,是不是發現和OC的風格很像呢?是不是發現自己很容易就能看懂呢?其實我想說的是,世上無難事,只怕有心人,只要你愿意花時間去學習,你就會發現其實他并不難。

基礎

  • 導入文件###

在Swift中,同一個工程項目不需要引入各自的類文件,比如我新建了一個工程,里面有兩個ViewController,我在vc_A中希望引用vc_B的某個公開屬性,這時在我的vc_A中是不需要引入vc_B的文件的。
不在本工程內創建的文件,如一些系統庫,或是通過CocoaPods加入到工程的,在使用時則需要引入到工程內,引入時也區別OC,簡單使用import 庫名即可,例如:

import UIKit
import ReactiveSwift
  • 常量與變量###

在Swift中,使用let來表示常量,var來表示變量,所謂常量,即為不可改變的量,比如你聲明一個UIButton對象,后面不會給這個對象賦值成別的什么按鈕對象,初始化時即在內存中給這個對象開辟了一塊空間,后面不會去改變這個對象的地址,因此,你可以這樣來創建這個對象:

let btn = UIButton(type: .system)

改變對btn的一些屬性設置,不會影響這個對象在內存中的地址變化,因此,也就不需要將btn設置成var類型,這個看你的需求而定。
像在OC中常使用的NSMutableArray,在Swift中沒有類似可變數組這樣的類,可以直接聲明一個數組類型的變量來達到同樣的效果,比如這樣:

var array: Array<String>

需要說明的是,Array<String>為字符串類型的數組,關于數組后面會介紹。

  • 數據類型###

大體上數據類型和OC也沒有什么差別,布爾類型的值從OC的YES/NO換成了true/false,其它值得注意的就是Swift本身是類型安全的語言,因此像在OC中習慣使用的小數,比如CGFloat和Float在使用運算符進行運算時就會報類型不一致的錯誤了:

修改方法是需要將其中的一個進行類型轉換,以保證兩個進行運算的值的類型是一致的:

let a: CGFloat = 0.3
let b: Float = 0.4
let sum = Float(a) + b

值得說明的有兩點,

  1. Swift的變量和常量在聲明時可以不說明它的類型,編譯器會通過初始化的值對該變量或常量進行類型推斷。

通過這張圖我們可以看出來,我在聲明常量a時,并沒有指定a的數據類型,而是通過給a進行初始化賦了一個值0.3,這時候編譯器會根據初始化的值對常量a進行類型推斷,推斷出的結果是常量a是一個Double類型的常量。

  1. Swift中不需要;作為句尾結束符,因此在Swift中對于空格的使用就要注意一些,比如在賦值符=的左右兩邊,都必須有至少一個空格才能正常編譯通過。
  • 輸出函數###

由于Swift可以兼容OC,因此我們仍可以繼續使用NSLog輸出函數來進行輸出,同樣,Swift也提供了自己的輸出函數,Print,這個函數中不再需要占位符了,你希望輸出一個變量類似這樣:

let name = "Shaw"
print("Hello \(name)")

或者這樣

let name = "Shaw"
print("Hello" + name)
  • 可選類型###

這個可以算是Swift相較OC變化較大的內容了,這就是你在閱讀Swift的代碼時經常能夠看到的在一個變量的后面,跟了一個?或者!,這就跟可選類型相關。
聲明一個可選類型的變量,表示這個變量可以被賦值為nil,這個不同于OC,在OC里,所有的對象都可以被賦值為nil,在編譯時不會報錯,但是Swift不可以,如果一個對象在聲明時沒有聲明成可選類型,那么這個對象在編譯時是不允許被賦值為nil的。比如下面這樣:


這樣就是不允許的,這時,我們發現報的這個錯誤編譯器可以幫我們自動修正,修正后就是這個樣子了:

var x: UIImageView? = nil

可以發現,編譯器只是幫我們在數據類型的后面增加了一個?,這樣就可以將變量x賦值為nil了。接下來我們給這個UIImageView對象賦一張圖片,像這樣:

x = UIImageView.init(image: UIImage.init(named: "abc"))

接下來,我們再聲明一個UIImage類型的常量y,并將變量x的image屬性的值賦給y,這時候我們不允許y為nil,我們這樣做:


你突然發現編譯器給我們報了兩個錯誤,先不要著急,讓我們來一一看這兩個錯誤都是什么,

  1. 第一個錯誤點在x的下面,說可選類型的UIImageView沒有打開,你是要使用'!'或者'?'么?,這個錯誤發生的原因和之前我們在說Float和CGFloat那部分的問題是一樣的,由于Swift是類型安全的語言,因此一旦你聲明確定了一個變量或常量的類型,那么這個變量或常量無論在編譯時還是運行時都只能是這個類型的,對于剛才變量x下面的那個錯誤點,因為只有真正的UIImageView對象,才會有image屬性,而由于我們在聲明變量x的類型時,將x聲明成了可選類型,也就是允許x = nil,如果在訪問x的image屬性前,x的值是nil的話,程序運行就會崩潰,所以編譯器為了避免這個直接導致崩潰的問題發生,在編譯時會要求我們將可選類型的變量進行解包操作,只有解包后的變量x的數據類型才是真正的UIImageView類型,解包的方式就是在可選類型變量的后面加上?或者!即可,那么這二者的區別又是什么呢?
    ?表示嘗試將這個變量或常量進行解包,如果解包后x的值是nil,那么程序將不再去訪問x的image屬性;!則不同,其表示強制對x進行解包,如果發現解包后的x的值是nil,則程序會崩潰,因此需要慎用!
  2. 明白了第一個錯誤是如何產生的,第二個問題也就迎刃而解了,同樣,我們在給一個UIImage類型的常量y賦值時,編譯器不允許y被賦值為nil,因此會強制要求你將x.image后面加上!的,注意,這時候后面不可用?,原因還是由于Swift是類型安全的語言,不能嘗試對x.image進行解包,如果你解出來是個nil怎么辦?因此編譯器直接讓你強制解包,解出來是nil的話就搞崩潰你。
    下面有兩種對于剛才這個問題的正確寫法,
let y: UIImage = x!.image!
let y: UIImage = (x?.image)!

對于這兩種寫法,都是正確的,只不過解包的思路有些不同,上面那種是先將x強制解包成UIImageView對象,再對他的image屬性進行強制解包;下面那種是先嘗試將x解包,然后訪問他的image屬性,最后對訪問的這個屬性進行強制解包。
說到這也許你會問,雖然大概明白了什么是可選類型,以及什么是解包,為什么要解包,但是你在開發時,仍然不可避免的忽略掉這些,不要捉急,機智的編譯器已將替大家考慮到這個問題了,他會在你寫代碼的時候,悄悄的自動為你加上這些符號,如果你真的寫錯了的話,他還能幫你自動修正,是不是發現這時候的Xcode真的挺可愛的呢?

  • 運算符###

基本的運算符還都和OC一致,不過在使用運算符進行運算的時候需要注意類型一致,另外,在Swift3之前的版本中,支持對浮點數進行求余操作,但是Swift3不再支持了,系統提示使用一個方法進行代替:

var  a: Float = 10.5
//a = a % 3
a = a.truncatingRemainder(dividingBy: 3)

輸出結果1.5
以下表格列出了在Swift3中支持的基本運算符,舉例: x = 10, y = 20

運算符 運算 結果
+ x + y 30
- x - y -10
* x * y 200
/ x / y 0
% x % y 10

對于OC和Swift3之前的版本所支持的++--運算,在Swift3中只支持這樣的形式:

實例 等價 結果
x += 10 x = x + 10 20
y -= 1 y = y - 1 19

Swift3中的邏輯運算符和位運算符都與OC沒有什么差異,需要注意的是,像這樣在OC中可以用位運算符中的邏輯或囊括的多個枚舉值:

[UIView animateWithDuration:0.1 delay:0 options:
UIViewAnimationOptionAutoreverse
| UIViewAnimationOptionAllowUserInteraction  
animations:^ {
       
} completion: nil];

在Swift中寫起來要麻煩一些:

UIView.animate(withDuration: 0.1, delay: 0, options: 
(UIViewAnimationOptions(rawValue: 
UIViewAnimationOptions.autoreverse.rawValue 
| UIViewAnimationOptions.allowUserInteraction.rawValue)), 
animations: {
            
}, completion: nil)

另外,在Swift3中,增加了一個符號??,該符號的用法如下:

實例 等價
let a = b ?? c let a = b != nil ? b! : c

舉例說明,一個函數的功能是接收一個可選字符串類型的參數,返回一個字符串,如果傳進來的是nil,就將參數重新賦值成一個既定的字符串并返回,代碼如下:

func showMessage(msg: String? = nil) -> String {
      let msg = msg ?? "默認字符串"
      return msg
}

Swift3.0的區間運算符:

實例 等價 說明
0...10 0 <= x <= 10 從0到10的閉區間
0..<10 0 <= x < 10 從0到10的左閉右開區間
  • 數據存儲###

  1. 枚舉####

你可以聲明一個枚舉,像這樣:

enum ControlCMD {
          case up, right, down, left
}

比如我們現在有個需求,滑動手指時輸出一個手指滑動的方向的英文,在Swift里我們只需要這樣實現:

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        let leftGR = UISwipeGestureRecognizer
            .init(target: self, action: #selector(swipe(_:)))
        leftGR.direction = .left
        let rightGR = UISwipeGestureRecognizer
            .init(target: self, action: #selector(swipe(_:)))
        rightGR.direction = .right
        let upGR = UISwipeGestureRecognizer
            .init(target: self, action: #selector(swipe(_:)))
        upGR.direction = .up
        let downGR = UISwipeGestureRecognizer
            .init(target: self, action: #selector(swipe(_:)))
        downGR.direction = .down
        self.view.addGestureRecognizer(leftGR)
        self.view.addGestureRecognizer(rightGR)
        self.view.addGestureRecognizer(upGR)
        self.view.addGestureRecognizer(downGR)
    }
    
    enum ControlCMD: String {
        case up, right, down, left
    }
    
    func swipe(_ sender: UISwipeGestureRecognizer) {

        switch sender.direction {
        case UISwipeGestureRecognizerDirection.up:
            self.sendMessage(cmd: .up)
        case UISwipeGestureRecognizerDirection.down:
            self.sendMessage(cmd: .down)
        case UISwipeGestureRecognizerDirection.left:
            self.sendMessage(cmd: .left)
        case UISwipeGestureRecognizerDirection.right:
            self.sendMessage(cmd: .right)
        default: break
        }

    }
    
    func sendMessage(cmd: ControlCMD) {
        print("滑動的方向" + cmd.rawValue)
    }
}

注意,我在聲明枚舉時,將枚舉類型指定為String類型的枚舉,這樣,我在發送消息時就可以使用cmd.rawValue來訪問枚舉值的字符串了。
Swift中的枚舉還有一些更高級的用法,因為我暫時還沒有用過,所以也不在此描述了,以后遇上時再補充上。

  1. 元組####

對于元組這個概念,這是OC中所沒有的,我理解的元組是將多個值組合成為一個值,感覺有點像數組,但是元組中的值的類型可以是任意類型的,舉個例子:

let tuple = ("abc", 1, 0.5, [UIImage()])

這就是一個元組,元組中可以有多個元素,也可以只有一個元素,當然,由于元組就是為了存儲多個值的,如果只有一個值也就不需要元組,多個值的時候,我們可以像數組那樣,通過使用序號來訪問元組中的元素,比如這樣:

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,362評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,577評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,486評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,852評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,600評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,944評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,944評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,108評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,652評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,385評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,616評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,111評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,798評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,205評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,537評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,334評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,570評論 2 379

推薦閱讀更多精彩內容