Swift中enum、struct蝗茁、class三者異同

前言

由于在開發(fā)過程中常常需要用到系統(tǒng)提供的基礎(chǔ)類型之外的的類型,所以Swift允許我們根據(jù)自己的需要構(gòu)建屬于自己的類型系統(tǒng)以便于更加靈活和方便的開發(fā)程序并將其稱之為 “named types“寻咒。

Swift主要為我們提供了以下四種”named types“ 分別是:enum哮翘、structclassprotocol毛秘。相信熟悉iOS開發(fā)的同學(xué)們對于枚舉饭寺、結(jié)構(gòu)體和類的概念一點都不陌生。相比于前輩Objective-C中的這三者叫挟,Swift將enumstruct變得更加靈活且強大艰匙,并且賦予了他們很多和class相同的屬性實現(xiàn)更加豐富多彩的功能,以至于有時候我們很難分清他們到底有什么區(qū)別以及我該什么時候用哪種類型抹恳,接下來本文將重點介紹一下在Swift中enumstruct的定義和新特性以及兩者與class之間的異同员凝,也是自己學(xué)習(xí)Swift以來的階段性總結(jié)。

?枚舉(enum)

  • 枚舉的定義
    Swift中的枚舉是為一組有限種可能性的相關(guān)值提供的通用類型(在C/C++/Objective-C中奋献,枚舉是一個被命名的整型常數(shù)的集合)健霹;使用枚舉可以類型安全并且有提示性地操作這些值。與結(jié)構(gòu)體瓶蚂、類相似糖埋,使用關(guān)鍵詞enum來定義枚舉,并在一對大括號內(nèi)定義具體內(nèi)容包括使用case關(guān)鍵字列舉成員扬跋。就像下面一樣:
//定義一個表示學(xué)生類型的全新枚舉類型 StudentType,他有三個成員分別是pupil(小學(xué)生凌节,玩LOL最怕遇到這種隊友了)钦听、middleSchoolStudent(中學(xué)生,現(xiàn)在的中學(xué)生都很拽)倍奢、collegeStudents(大學(xué)生朴上,據(jù)說大學(xué)生活很不錯,注意斷句)
enum StudentType {
    case pupil
    case middleSchoolStudent
    case collegeStudent
}

上面的代碼可以讀作:如果存在一個StudentType的實例卒煞,他要么是pupil (小學(xué)生)痪宰、要么是middleSchoolStudent(中學(xué)生)、要么是collegeStudent(大學(xué)生)。注意衣撬,和C乖订、Objective-C中枚舉的不同,Swift 中的枚舉成員在被創(chuàng)建時不會分配一個默認(rèn)的整數(shù)值具练。而且不需要給枚舉中的每一個成員都提供值(如果你需要也是可以的)乍构。如果一個值(所謂“原始值”)要被提供給每一個枚舉成員,那么這個值可以是字符串扛点、字符哥遮、任意的整數(shù)值,或者是浮點類型(引自文檔翻譯)陵究。簡單說Swift中定義的枚舉只需要幫助我們表明不同的情況就夠了眠饮,他的成員可以沒有值,也可以有其他類型的值(不局限于整數(shù)類型)铜邮。
枚舉中有兩個很容易混淆的概念:原始值(raw value)仪召、關(guān)聯(lián)值(associated value),兩個詞聽起來比較模糊牲距,下面簡單介紹一下:

  • 枚舉的原始值(raw value)
    枚舉成員可以用相同類型的默認(rèn)值預(yù)先填充返咱,這樣的值我們稱為原始值(raw value),下面的StudentType中三個成員分別被Int類型的10 牍鞠、15咖摹、 20填充表示不同階段學(xué)生的年齡。注意:Int修飾的是StudentType成員原始值的類型而不是StudentType的類型难述,StudentType類型從定義開始就是一個全新的枚舉類型萤晴。
enum StudentType: Int{
      case pupil = 10
      case middleSchoolStudent = 15
      case collegeStudents = 20
}

定義好StudentType成員的原始值之后,我們可以使用枚舉成員的rawValue屬性來訪問成員的原始值胁后,或者是使用原始值初始化器來嘗試創(chuàng)建一個枚舉的新實例

//  常量student1值是 10
let student1 = StudentType.pupil.rawValue
//  變量student2值是 15
var student2 = StudentType.middleSchoolStudent.rawValue
//  使用成員rawValue屬性創(chuàng)建一個`StudentType`枚舉的新實例
let student3 = StudentType.init(rawValue: 15)
//  student3的值是 Optional<Senson>.Type
type(of: student3)
//  student4的值是nil店读,因為并不能通過整數(shù)30得到一個StudentType實例的值
let student4 = StudentType.init(rawValue: 30)

使用原始值初始化器這種方式初始化創(chuàng)建得到StudentType的實例student4是一個StudentType可選類型,因為并不是給定一個年齡就能找到對應(yīng)的學(xué)生類型攀芯,比如在StudentType中給定年齡為30就找不到對應(yīng)的學(xué)生類型(很可能30歲的人已經(jīng)是博士了)屯断。所以原始值初始化器是一個可失敗初始化器。
總結(jié)一句:原始值是為枚舉的成員們綁定了一組類型必須相同值不同的固定的值(可能是整型侣诺,浮點型殖演,字符類型等等)。這樣很好解釋為什么提供原始值的時候用的是等號年鸳。

  • 枚舉的關(guān)聯(lián)值(associated value)
    關(guān)聯(lián)值原始值不同趴久,關(guān)聯(lián)值更像是為枚舉的成員們綁定了一組類型,不同的成員可以是不同的類型(提供關(guān)聯(lián)值時用的是括號)搔确。例如下面的代碼:
//定義一個表示學(xué)生類型的枚舉類型 StudentType彼棍,他有三個成員分別是pupil灭忠、middleSchoolStudent、collegeStudents
enum StudentType {
    case pupil(String)
    case middleSchoolStudent(Int, String)
    case collegeStudents(Int, String)
}

這里我們并沒有為StudentType的成員提供具體的值座硕,而是為他們綁定了不同的類型弛作,分別是pupil綁定String類型、middleSchoolStudentcollegeStudents綁定(Int坎吻, String)元祖類型缆蝉。接下來就可以創(chuàng)建不同StudentType枚舉實例并為對應(yīng)的成員賦值了。

    //student1 是一個StudentType類型的常量瘦真,其值為pupil(小學(xué)生)刊头,特征是"have fun"(總是在玩耍)
let student1 = StudentType.pupil("have fun")
    //student2 是一個StudentType類型的常量,其值為middleSchoolStudent(中學(xué)生)诸尽,特征是 7, "always study"(一周7天總是在學(xué)習(xí))
let student2 = StudentType.middleSchoolStudent(7, "always study")
    //student3 是一個StudentType類型的常量原杂,其值為collegeStudent(大學(xué)生),特征是 7, "always LOL"(一周7天總是在擼啊擼)
let student3 = StudentType.middleSchoolStudent(7, "always LOL")

這個時候如果需要判斷某個StudentType實例的具體的值就需要這樣做了:

switch student3 {
      case .pupil(let things):
          print("is a pupil and \(things)")
      case .middleSchoolStudent(let day, let things):
          print("is a middleSchoolStudent and \(day) days \(things)")
      case .collegeStudent(let day, let things):
          print("is a collegeStudent and \(day) days \(things)")
    }  

控制臺輸出:is a collegeStudent and 7 days always LOL您机,看到這你可能會想穿肄,是否可以為一個枚舉成員提供原始值并且綁定類型呢,答案是不能的际看!因為首先給成員提供了固定的原始值咸产,那他以后就不能改變了;而為成員提供關(guān)聯(lián)值(綁定類型)就是為了創(chuàng)建枚舉實例的時候賦值仲闽。這不是互相矛盾嗎脑溢。

  • 遞歸枚舉
    遞歸枚舉是擁有另一個枚舉作為枚舉成員關(guān)聯(lián)值的枚舉(引自文檔翻譯)。
    關(guān)于遞歸枚舉我們可以拆封成兩個概念來看:遞歸 + 枚舉赖欣。遞歸是指在程序運行中函數(shù)(或方法)直接或間接調(diào)用自己的這樣一種方式屑彻,其特點為重復(fù)有限個步驟、格式較為簡單顶吮。下面是一個經(jīng)典的通過遞歸算法求解n!(階乘)的函數(shù)社牲。
func factorial(n: Int)->Int {
      if n > 0 {
          return n * factorial(n: n - 1)
      } else {
          return 1
      }
  }
  //1 * 2 * 3 * 4 * 5 * 6 = 720
  let sum = factorial(n: 6)

函數(shù)factorial (n: int)-> Int在執(zhí)行過程中很明顯的調(diào)用了自身。結(jié)合枚舉的概念我們這里可以簡單的理解為遞歸枚舉類似上面將枚舉值本身傳入給成員去判斷的情況悴了。因為實在沒找到很好體現(xiàn)遞歸枚舉的例子搏恤,而且本人對遞歸枚舉的使用場景都用在哪些地方還不是很了解,所以呢這里就不獻(xiàn)丑了湃交。

可以看出Swift中枚舉變得更加靈活和復(fù)雜熟空,有遞歸枚舉的概念,還有很多和Class類似的特性巡揍,比如:計算屬性用來提供關(guān)于枚舉當(dāng)前值的額外信息痛阻;實例方法提供與枚舉表示值相關(guān)的功能菌瘪;定義初始化器來初始化成員值腮敌;而且能夠遵循協(xié)議來提供標(biāo)準(zhǔn)功能等等阱当,由于筆者目前還沒有更加深入的學(xué)習(xí)這些東西,所以這些內(nèi)容有機會將在后面的章節(jié)講到糜工。

? 結(jié)構(gòu)體(struct)

  • 結(jié)構(gòu)體的定義
    結(jié)構(gòu)體是由一系列具有相同類型或不同類型的數(shù)據(jù)構(gòu)成的數(shù)據(jù)集合弊添。結(jié)構(gòu)體是一種值類型的數(shù)據(jù)結(jié)構(gòu),在Swift中常常使用結(jié)構(gòu)體封裝一些屬性甚至是方法來組成新的復(fù)雜類型捌木,目的是簡化運算油坝。我們通過使用關(guān)鍵詞struct來定義結(jié)構(gòu)體。并在一對大括號內(nèi)定義具體內(nèi)容包括他的成員和自定義的方法(是的刨裆,Swift中的結(jié)構(gòu)體有方法了)澈圈,定義好的結(jié)構(gòu)體存在一個自動生成的成員初始化器,使用它來初始化結(jié)構(gòu)體實例的成員屬性帆啃。廢話不多說直接上代碼:
 //定義一個 Student(學(xué)生)類型的結(jié)構(gòu)體用于表示一個學(xué)生瞬女,Student的成員分別是語、數(shù)努潘、外三科`Int`類型的成績
 struct Student {
    var chinese: Int
    var math: Int
    var english: Int
 }

看到這里熟悉Swift的同學(xué)可能已經(jīng)發(fā)現(xiàn)了一點結(jié)構(gòu)體和類的區(qū)別了:定義結(jié)構(gòu)體類型時其成員可以沒有初始值诽偷。如果使用這種格式定義一個類,編譯器是會報錯的疯坤,他會提醒你這個類沒有被初始化报慕。

  • 結(jié)構(gòu)體實例的創(chuàng)建 :
    創(chuàng)建結(jié)構(gòu)體和類的實例的語法非常相似,結(jié)構(gòu)體和類兩者都能使用初始化器語法來生成新的實例压怠。最簡單的語法是在類或結(jié)構(gòu)體名字后面接一個空的圓括號眠冈,例如 let student1 = Student()。這樣就創(chuàng)建了一個新的類或者結(jié)構(gòu)體的實例刑峡,任何成員都被初始化為它們的默認(rèn)值(前提是成員均有默認(rèn)值)洋闽。但是結(jié)合上面的代碼,由于在定義Student結(jié)構(gòu)體時我們并沒有為他的成員賦初值突梦,所以 let student1 = Student()在編譯器中報錯了诫舅,此處報錯并不是因為不能這樣創(chuàng)建實例而是因為student1成員沒有默認(rèn)值,所以我們可以使用下面的方式創(chuàng)建實例:
 //使用Student類型的結(jié)構(gòu)體創(chuàng)建Student類型的實例(變量或常量)并初始化三個成員(這個學(xué)生的成績會不會太好了點)
 let student2 = Student(chinese: 90, math: 80, english: 70)

所有的結(jié)構(gòu)體都有一個自動生成的成員初始化器宫患,你可以使用它來初始化新結(jié)構(gòu)體實例的成員就像上面一樣(前提是沒有自定義的初始化器)刊懈。如果我們在定義Student時為他的成員賦上初值,那么下面的代碼是編譯通過的:

struct Student {
    var chinese: Int = 50
    var math: Int = 50
    var english: Int = 50
}
let student2 = Student(chinese: 90, math: 80, english: 70)
let student4 = Student()

總結(jié)一句:定義結(jié)構(gòu)體類型時其成員可以沒有初始值娃闲,但是創(chuàng)建結(jié)構(gòu)體實例時該實例的成員必須有初值虚汛。

  • 自定義的初始化器
    當(dāng)我們想要使用自己的方式去初始化創(chuàng)建一個Student類型的實例時,系統(tǒng)提供的成員初始化器可能就不夠用了皇帮。例如卷哩,我們希望通過形如:let student5 = Student(stringScore: "70,80,90")的方式創(chuàng)建實例時,就需要自定義初始化方法了:
struct Student {
    var chinese: Int = 50
    var math: Int = 50
    var english: Int = 50
        init() {}
        init(chinese: Int, math: Int, english: Int) {
              self.chinese = chinese
              self.math = math
             self.english = english
        }
        init(stringScore: String) {
             let cme = stringScore.characters.split(separator: ",")
             chinese = Int(atoi(String(cme.first!)))
             math = Int(atoi(String(cme[1])))
             english = Int(atoi(String(cme.last!)))
        }
    }
    let student6 = Student()
    let student7 = Student(chinese: 90, math: 80, english: 70)
    let student8 = Student(stringScore: "70,80,90")

一旦我們自定義了初始化器属拾,系統(tǒng)自動的初始化器就不起作用了将谊,如果還需要使用到系統(tǒng)提供的初始化器冷溶,在我們自定義初始化器后就必須顯式的定義出來。

  • 定義其他方法
    如果此時需要修改某個學(xué)生某科的成績尊浓,該如何實現(xiàn)呢逞频?當(dāng)然,我們可以定義下面的方法:
//更改某個學(xué)生某門學(xué)科的成績
func changeChinese(num: Int, student: inout Student){
    student.chinese += num
}
changeChinese(num: 20, student: &student7)

此時student7的語文成績就由原來的90被修改到了110栋齿,但是此方法有兩個明顯的弊端:1苗胀,學(xué)生的語文成績chineseStudent結(jié)構(gòu)體的內(nèi)部成員,一個學(xué)生的某科成績無需被Student的使用者了解瓦堵。即我們只關(guān)心學(xué)生的語文成績更改了多少基协,而不是關(guān)心學(xué)生語文成績本身是多少。2菇用,更改一個學(xué)生的語文成績本身就是和Student結(jié)構(gòu)體內(nèi)部成員計算相關(guān)的事情堡掏,我們更希望達(dá)到形如:student7.changeChinese(num: 10) 的效果,因為只有學(xué)生本身清楚自己需要將語文成績更改多少(更像是面向?qū)ο蠓庋b的思想)刨疼。很明顯此時changeChinese(num:)方法是Student結(jié)構(gòu)體內(nèi)部的方法而不是外部的方法泉唁,所以我定義了一個修改某個學(xué)生數(shù)學(xué)成績的內(nèi)部方法用于和之前修改語文成績的外部方法對比:

struct Student {
    var chinese: Int = 50
    var math: Int = 50
    var english: Int = 50
   //修改數(shù)學(xué)成績
    mutating func changeMath(num: Int) {
        self.math += num
    }
  }
  var student7 = Student(chinese: 20, math: 30, english: 40)
  //更改分?jǐn)?shù)中語文學(xué)科的成績
  func changeChinese(num: Int, student: inout Student){
      student.chinese += num
    }
  changeChinese(num: 20, student: &student7)
  student7.changeMath(num: 10)

盡管兩者都能達(dá)到同樣的效果,但是把修改結(jié)構(gòu)體成員的方法定義在結(jié)構(gòu)體內(nèi)部顯得更加合理同時滿足面向?qū)ο蠓庋b的特點揩慕。以上兩點就是我們?yōu)?code>Student結(jié)構(gòu)體內(nèi)部添加changeMath(num:)的原因亭畜,他讓我們把類型相關(guān)的計算表現(xiàn)的更加自然和統(tǒng)一,即自己的事情應(yīng)該用自己的方法實現(xiàn)不應(yīng)該被別人關(guān)心迎卤。值得一提的是在結(jié)構(gòu)體內(nèi)部方法中如果修改了結(jié)構(gòu)體的成員拴鸵,那么該方法之前應(yīng)該加入:mutating關(guān)鍵字。

由于結(jié)構(gòu)體是值類型蜗搔,Swift規(guī)定不能直接在結(jié)構(gòu)體的方法(初始化器除外)中修改成員劲藐。原因很簡單,結(jié)構(gòu)體作為值的一種表現(xiàn)類型怎么能提供改變自己值的方法呢樟凄,但是使用mutating我們便可以辦到這點聘芜,當(dāng)然這也是和類的不同點。

  • 常見的結(jié)構(gòu)體
    Swift中很多的基礎(chǔ)數(shù)據(jù)類型都是結(jié)構(gòu)體類型缝龄,下面列舉的是一些常用的結(jié)構(gòu)體類型:
//表示數(shù)值類型的結(jié)構(gòu)體:
    Int汰现,F(xiàn)loat,Double叔壤,CGFloat...
//表示字符和字符串類型的結(jié)構(gòu)體
    Character瞎饲,String...
//位置和尺寸的結(jié)構(gòu)體
    CGPoint,CGSize...
//集合類型結(jié)構(gòu)體
    Array炼绘,Set嗅战,Dictionary...

很多時候你不細(xì)心觀察的話可能不會想到自己信手拈來的代碼中居然藏了這么多結(jié)構(gòu)體。另外有時候在使用類和結(jié)構(gòu)體的時候會出現(xiàn)下面的情況

// Person 類
class Person {
      var name: String = "jack"
      let life: Int = 1
}
      var s1 = Person()
      var s2 = s1
       s2.name = "mike"
       s1
// People 結(jié)構(gòu)體數(shù)據(jù)結(jié)構(gòu)
struct People {
      var name: String = "jack"
      let life: Int = 1
}
      var p1 = People()
      var p2 = p1
        p2.name = "mike"
        p1

細(xì)心的同學(xué)可能已經(jīng)發(fā)現(xiàn)了其中的詭異俺亮。變量s1驮捍、s2Person類的實例形庭,修改了s2name屬性,s1name也會改變厌漂;而p1叛甫、p2作為People結(jié)構(gòu)體的實例争便,修改了p1name屬性,p2name并不會發(fā)生改變审姓。這是為什么呢囤踩?總結(jié)中告訴你旨椒。

總結(jié)

關(guān)于枚舉結(jié)構(gòu)體的介紹這里僅僅是冰山一角堵漱,他們還有更加豐富的功能需要讀者在閱讀完本文后深入學(xué)習(xí)综慎。了解這些基礎(chǔ)內(nèi)容,可以幫助我們在Swift開發(fā)中更熟練的使用他們勤庐。這里根據(jù)官方文檔介紹結(jié)合自己的理解簡單的做一下總結(jié):

  • 枚舉示惊、結(jié)構(gòu)體、類的共同點:
    1愉镰,定義屬性和方法米罚;
    2,下標(biāo)語法訪問值丈探;
    3录择,初始化器;
    4碗降,支持?jǐn)U展增加功能隘竭;
    5,可以遵循協(xié)議讼渊;

  • 類特有的功能:
    1动看,繼承;
    2爪幻,允許類型轉(zhuǎn)換弧圆;
    3,析構(gòu)方法釋放資源笔咽;
    4搔预,引用計數(shù);

  • 類是引用類型
    引用類型(reference types叶组,通常是類)被復(fù)制的時候其實復(fù)制的是一份引用拯田,兩份引用指向同一個對象。所以在修改一個實例的數(shù)據(jù)時副本的數(shù)據(jù)也被修改了(s1甩十、s2)船庇。

  • 枚舉吭产,結(jié)構(gòu)體是值類型
    值類型(value types)的每一個實例都有一份屬于自己的數(shù)據(jù),在復(fù)制時修改一個實例的數(shù)據(jù)并不影響副本的數(shù)據(jù)(p1鸭轮、p2)臣淤。值類型引用類型是這三兄弟最本質(zhì)的區(qū)別。

  • 我該如何選擇
    關(guān)于在新建一個類型時如何選擇到底是使用值類型還是引用類型的問題其實在理解了兩者之間的區(qū)別后是非常簡單的窃爷,在這蘋果官方已經(jīng)做出了非常明確的指示(以下內(nèi)容引自蘋果官方文檔):

    當(dāng)你使用Cocoa框架的時候邑蒋,很多API都要通過NSObject的子類使用,所以這>時候必須要用到引用類型class按厘。在其他情況下医吊,有下面幾個準(zhǔn)則:

    • 什么時候該用值類型:
      要用==運算符來比較實例的數(shù)據(jù)時
      你希望那個實例的拷貝能保持獨立的狀態(tài)時
      數(shù)據(jù)會被多個線程使用時
    • 什么時候該用引用類型(class):
      要用==運算符來比較實例身份的時候
      你希望有創(chuàng)建一個共享的、可變對象的時候

文章最后

以上就是本人前段時間學(xué)習(xí)心得逮京,示例代碼在Swift3.0語法下都是編譯通過的卿堂,知識點比較少,部分描述引自官方的文檔懒棉。如果文中有任何紕漏或錯誤歡迎在評論區(qū)留言指出草描,本人將在第一時間修改過來;喜歡我的文章策严,可以關(guān)注我以此促進(jìn)交流學(xué)習(xí)陶珠; 如果覺得此文戳中了你的G點請隨手點贊;轉(zhuǎn)載請注明出處享钞,謝謝支持揍诽。

下一篇:Swift中協(xié)議的簡單介紹

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市栗竖,隨后出現(xiàn)的幾起案子暑脆,更是在濱河造成了極大的恐慌,老刑警劉巖狐肢,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件添吗,死亡現(xiàn)場離奇詭異,居然都是意外死亡份名,警方通過查閱死者的電腦和手機碟联,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來僵腺,“玉大人鲤孵,你說我怎么就攤上這事〕饺纾” “怎么了普监?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我凯正,道長毙玻,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任廊散,我火速辦了婚禮桑滩,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘允睹。我一直安慰自己运准,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布擂找。 她就那樣靜靜地躺著,像睡著了一般浩销。 火紅的嫁衣襯著肌膚如雪贯涎。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天慢洋,我揣著相機與錄音塘雳,去河邊找鬼。 笑死普筹,一個胖子當(dāng)著我的面吹牛败明,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播太防,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼妻顶,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蜒车?” 一聲冷哼從身側(cè)響起讳嘱,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎酿愧,沒想到半個月后沥潭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡嬉挡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年钝鸽,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片庞钢。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡拔恰,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出基括,到底是詐尸還是另有隱情仁连,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站饭冬,受9級特大地震影響使鹅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜昌抠,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一患朱、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧炊苫,春花似錦裁厅、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至唠梨,卻和暖如春袋励,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背当叭。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工茬故, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蚁鳖。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓磺芭,卻偏偏與公主長得像,于是被迫代替她去往敵國和親醉箕。 傳聞我的和親對象是個殘疾皇子钾腺,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 前言 由于在開發(fā)過程中常常需要用到系統(tǒng)提供的基礎(chǔ)類型之外的的類型坞琴,所以Swift允許我們根據(jù)自己的需要構(gòu)建屬于自己...
    心淡然如水閱讀 450評論 0 1
  • enum:Swift中的枚舉是為一組有限種可能性的相關(guān)值提供的通用類型(在C/C++/C#中,枚舉是一個被命名的整...
    雨燕oc閱讀 342評論 0 0
  • 由于在開發(fā)過程中常常需要用到系統(tǒng)提供的基礎(chǔ)類型之外的的類型加勤,所以Swift允許我們根據(jù)自己的需要構(gòu)建屬于自己的類型...
    清風(fēng)沐沐閱讀 362評論 0 1
  • 前言 由于在開發(fā)過程中常常需要用到系統(tǒng)提供的基礎(chǔ)類型之外的的類型仙辟,所以Swift允許我們根據(jù)自己的需要構(gòu)建屬于自己...
    silly鴻閱讀 1,214評論 0 0
  • 今天是520,很多人都在表達(dá)愛的日子鳄梅。 今天是周五叠国,六點下班之后就是兩天的假期。 突然想聽靜茹的歌戴尸。 搜了粟焊。聽了《...
    倪思quliss閱讀 317評論 0 0