Swift 5.x - 可選鏈接(中文文檔)

引言

繼續(xù)學(xué)習(xí)Swift文檔披蕉,從上一章節(jié):析構(gòu)函數(shù)颈畸,我們學(xué)習(xí)了Swift析構(gòu)函數(shù)相關(guān)的內(nèi)容。現(xiàn)在没讲,我們學(xué)習(xí)Swift可選鏈接的相關(guān)的內(nèi)容眯娱。由于篇幅較長,這里分篇來記錄爬凑,接下來徙缴,F(xiàn)ighting!

如果你已經(jīng)熟悉這部分內(nèi)容嘁信,移步下一章節(jié):錯誤處理

可選鏈接

可選鏈接是一個查詢和調(diào)用當(dāng)前可能為零的可選屬性于样,方法和下標(biāo)的過程。 如果可選包含值潘靖,則屬性穿剖,方法或下標(biāo)調(diào)用成功。 如果可選值為nil卦溢,則屬性糊余,方法或下標(biāo)調(diào)用將返回nil秀又。 可以將多個查詢鏈接在一起,如果鏈中的任何鏈接為nil啄刹,則整個鏈都會失敗涮坐。

注意
Swift中的可選鏈接類似于Objective-C中的無消息傳遞,但是它適用于任何類型誓军,并且可以檢查成功或失敗袱讹。

1 可選鏈接作為強(qiáng)制展開的替代方法

如果可選值不為nil,可以通過在要調(diào)用屬性昵时,方法或下標(biāo)的可選值之后放置問號(捷雕?)來指定可選鏈。這非常類似于將感嘆號(R忌)放在可選值之后以強(qiáng)制展開其值救巷。主要區(qū)別在于,當(dāng)可選值為nil時句柠,強(qiáng)制展開會觸發(fā)運(yùn)行時錯誤浦译。

為了反映可以在nil值上調(diào)用可選鏈接的事實(shí),即使要查詢的屬性溯职,方法或下標(biāo)返回的是非可選值精盅,可選鏈接調(diào)用的結(jié)果也始終是可選值。您可以使用此可選返回值來檢查可選鏈接調(diào)用是否成功(返回的可選包含一個值)谜酒,或者由于鏈中的值為nil而失斕厩巍(返回的可選值為nil)。

具體來說僻族,可選鏈接調(diào)用的結(jié)果與預(yù)期返回值的類型相同粘驰,但包裝在可選中。通常通過可選鏈訪問時述么,返回Int的屬性將返回Int蝌数?。

接下來的幾個代碼片段演示了可選鏈接與強(qiáng)制展開如何不同度秘,并使您能夠檢查是否成功籽前。

首先,定義了兩個類敷钾,分別是Person和Residence:

class Person {
    var residence: Residence?
}

class Residence {
    var numberOfRooms = 1
}

Residence實(shí)例具有一個名為numberOfRooms的Int屬性,默認(rèn)值為1肄梨。Person實(shí)例具有類型為Residence阻荒?的可選Residence屬性。

如果創(chuàng)建新的Person實(shí)例众羡,則其residence屬性由于是可選屬性而默認(rèn)初始化為nil侨赡。 在下面的代碼中,john的住宅屬性值為nil:

let john = Person()

如果您嘗試訪問此人的residence的numberOfRooms屬性,方法是在residence后放置一個感嘆號以使其值解開羊壹,從而觸發(fā)運(yùn)行時錯誤蓖宦,因?yàn)闆]有要解開的residence值:

let roomCount = john.residence!.numberOfRooms
// this triggers a runtime error

上面的代碼在john.residence具有非nil值時成功,并將roomCount設(shè)置為包含適當(dāng)房間數(shù)的Int值油猫。 但是稠茂,如上所示,此代碼總是在駐留時間為nil時觸發(fā)運(yùn)行時錯誤情妖。

可選鏈接提供了一種訪問numberOfRooms值的替代方法睬关。 要使用可選鏈接,請使用問號代替感嘆號:

if let roomCount = john.residence?.numberOfRooms {
    print("John's residence has \(roomCount) room(s).")
} else {
    print("Unable to retrieve the number of rooms.")
}
// Prints "Unable to retrieve the number of rooms."

這告訴Swift可以在可選的Residence屬性上“鏈接”毡证,并在存在residence的情況下檢索numberOfRooms的值电爹。

由于嘗試訪問numberOfRooms可能會失敗,因此可選的鏈接嘗試將返回Int料睛?類型的值丐箩,即“ optional Int”。 如上例所示恤煞,當(dāng)Residence為nil時屎勘,此可選的Int也將為nil,以反映無法訪問numberOfRooms的事實(shí)阱州。 通過可選的綁定訪問可選的Int可以解開整數(shù)并將非可選值分配給roomCount變量挑秉。

請注意,即使numberOfRooms是非可選的Int苔货,也是如此犀概。 通過可選鏈查詢它的事實(shí)意味著對numberOfRooms的調(diào)用將始終返回Int? 而不是Int夜惭。

您可以將一個Residence實(shí)例分配給john.residence姻灶,以使其不再具有nil值:

john.residence = Residence()

john.residence現(xiàn)在包含實(shí)際的Residence實(shí)例,而不是nil诈茧。 如果您嘗試使用與以前相同的可選鏈接來訪問numberOfRooms产喉,現(xiàn)在它將返回一個Int? 包含默認(rèn)的numberOfRooms值1:

if let roomCount = john.residence?.numberOfRooms {
    print("John's residence has \(roomCount) room(s).")
} else {
    print("Unable to retrieve the number of rooms.")
}
// Prints "John's residence has 1 room(s)."

2 定義可選鏈接的模型類

您可以將可選鏈接與深度超過一級的屬性敢会,方法和下標(biāo)一起使用曾沈。 這使您可以深入研究相互關(guān)聯(lián)類型的復(fù)雜模型中的子屬性,并檢查是否可以訪問這些子屬性上的屬性鸥昏,方法和下標(biāo)塞俱。

下面的代碼段定義了四個模型類,可用于后續(xù)的幾個示例中吏垮,包括多級可選鏈接的示例障涯。 這些類通過添加帶有相關(guān)屬性罐旗,方法和下標(biāo)的Room和Address類,從上面擴(kuò)展了Person and Residence模型唯蝶。

Person類的定義與以前相同:

class Person {
    var residence: Residence?
}

Residence類比以前更復(fù)雜九秀。 這次,Residence類定義了一個名為Rooms的變量屬性粘我,該屬性使用[Room]類型的空數(shù)組初始化:

class Residence {
    var rooms = [Room]()
    var numberOfRooms: Int {
        return rooms.count
    }
    subscript(i: Int) -> Room {
        get {
            return rooms[i]
        }
        set {
            rooms[i] = newValue
        }
    }
    func printNumberOfRooms() {
        print("The number of rooms is \(numberOfRooms)")
    }
    var address: Address?
}

由于此版本的Residence存儲了一系列Room實(shí)例鼓蜒,因此其numberOfRooms屬性被實(shí)現(xiàn)為計算屬性,而不是存儲屬性涂滴。 計算出的numberOfRooms屬性只是從rooms數(shù)組中返回count屬性的值友酱。

作為訪問其房間數(shù)組的捷徑,此版本的Residence提供了一個可讀寫的下標(biāo)柔纵,該下標(biāo)提供了對房間數(shù)組中請求的索引的訪問缔杉。

此版本的Residence還提供了一種名為printNumberOfRooms的方法,該方法僅打印該房間的房間數(shù)量搁料。

最后或详,Residence定義了一個名為address的可選屬性,其類型為Address?郭计。 此屬性的Address類類型在下面定義霸琴。

用于rooms數(shù)組的Room類是一個簡單的類,具有一個名為name的屬性昭伸,以及一個用于將該屬性設(shè)置為合適的房間名稱的初始化方法:

class Room {
    let name: String
    init(name: String) { self.name = name }
}

此模型中的最后一類稱為地址梧乘。 此類具有String?類型的三個可選屬性庐杨。 前兩個屬性buildingName和buildingNumber是將特定建筑物標(biāo)識為地址一部分的替代方法选调。 第三個屬性street用來為該地址命名街道:

class Address {
    var buildingName: String?
    var buildingNumber: String?
    var street: String?
    func buildingIdentifier() -> String? {
        if let buildingNumber = buildingNumber, let street = street {
            return "\(buildingNumber) \(street)"
        } else if buildingName != nil {
            return buildingName
        } else {
            return nil
        }
    }
}

Address類還提供了一個名為buildingIdentifier()的方法,該方法的返回類型為String?灵份。 此方法檢查地址的屬性仁堪,如果有值則返回buildingName,如果有值則返回與street串聯(lián)的buildingNumber填渠,否則返回nil弦聂。

3 通過可選鏈接訪問屬性

如“可選鏈接”作為強(qiáng)制展開的替代中所演示的,您可以使用可選鏈接來訪問可選值上的屬性氛什,并檢查該屬性訪問是否成功莺葫。

使用上面定義的類創(chuàng)建一個新的Person實(shí)例,然后嘗試像以前一樣訪問其numberOfRooms屬性:

let john = Person()
if let roomCount = john.residence?.numberOfRooms {
    print("John's residence has \(roomCount) room(s).")
} else {
    print("Unable to retrieve the number of rooms.")
}
// Prints "Unable to retrieve the number of rooms."

由于john.residence為nil枪眉,因此此可選鏈接與前面相同的方式捺檬,調(diào)用失敗。

您還可以嘗試通過可選的鏈接設(shè)置屬性的值:

let someAddress = Address()
someAddress.buildingNumber = "29"
someAddress.street = "Acacia Road"
john.residence?.address = someAddress

在此示例中鸳粉,嘗試設(shè)置john.residence的地址屬性將失敗,因?yàn)閖ohn.residence當(dāng)前為nil锦溪。

賦值是可選鏈接的一部分竿秆,這意味著=運(yùn)算符右側(cè)的任何代碼都不會被調(diào)用。 在上一個示例中垢粮,不容易發(fā)現(xiàn)someAddress從未被調(diào)用,因?yàn)樵L問常量沒有任何反應(yīng)。 下面的清單執(zhí)行相同的分配职车,但是它使用一個函數(shù)來創(chuàng)建地址。 該函數(shù)在返回值之前打印“調(diào)用了函數(shù)”鹊杖,這使您可以查看=運(yùn)算符的右側(cè)是否已被求值悴灵。

func createAddress() -> Address {
    print("Function was called.")

    let someAddress = Address()
    someAddress.buildingNumber = "29"
    someAddress.street = "Acacia Road"

    return someAddress
}
john.residence?.address = createAddress()

您可以說未調(diào)用createAddress()函數(shù),因?yàn)槲创蛴∪魏蝺?nèi)容骂蓖。

4 通過可選鏈接調(diào)用方法

您可以使用可選鏈接來對可選值調(diào)用方法积瞒,并檢查該方法調(diào)用是否成功。 即使該方法未定義返回值登下,也可以執(zhí)行此操作茫孔。

Residence類上的printNumberOfRooms()方法將打印numberOfRooms的當(dāng)前值。 該方法如下:

func printNumberOfRooms() {
    print("The number of rooms is \(numberOfRooms)")
}

此方法未指定返回類型被芳。 但是缰贝,沒有返回類型的函數(shù)和方法具有隱式的Void返回類型,如 Functions Without Return Values中所述畔濒。 這意味著它們返回值()或一個空的元組剩晴。

如果您通過可選鏈接對可選值調(diào)用此方法,則該方法的返回類型將為Void ?侵状,而不是Void赞弥,因?yàn)橥ㄟ^可選鏈接調(diào)用時,返回值始終為可選類型壹将。 這使您可以使用if語句來檢查是否有可能調(diào)用printNumberOfRooms()方法嗤攻,即使該方法本身并未定義返回值。 將printNumberOfRooms調(diào)用的返回值與nil進(jìn)行比較诽俯,以查看方法調(diào)用是否成功:

if john.residence?.printNumberOfRooms() != nil {
    print("It was possible to print the number of rooms.")
} else {
    print("It was not possible to print the number of rooms.")
}
// Prints "It was not possible to print the number of rooms."

如果您嘗試通過可選鏈接設(shè)置屬性妇菱,則情況也是如此。 上面的“通過可選鏈訪問屬性”中的示例嘗試為john.residence設(shè)置地址值暴区,即使Residence屬性為nil闯团。 任何通過可選鏈接設(shè)置屬性的嘗試都會返回Void類型的值,這使您可以與nil進(jìn)行比較以查看是否成功設(shè)置了該屬性:

if (john.residence?.address = someAddress) != nil {
    print("It was possible to set the address.")
} else {
    print("It was not possible to set the address.")
}
// Prints "It was not possible to set the address."

5 通過可選鏈接訪問下標(biāo)

您可以使用可選鏈接嘗試從下標(biāo)中檢索和設(shè)置可選值的值仙粱,并檢查該下標(biāo)調(diào)用是否成功房交。

注意
通過可選鏈接訪問下標(biāo)上的下標(biāo)值時,將問號放在下標(biāo)方括號之前伐割,而不是之后候味。 可選鏈接問號總是緊接在表達(dá)式的可選部分之后刃唤。

下面的示例嘗試使用Residence類定義的下標(biāo)檢索john.residence屬性的rooms數(shù)組中第一個房間的名稱。 因?yàn)閖ohn.residence當(dāng)前為nil白群,所以下標(biāo)調(diào)用失斏邪:

if let firstRoomName = john.residence?[0].name {
    print("The first room name is \(firstRoomName).")
} else {
    print("Unable to retrieve the first room name.")
}
// Prints "Unable to retrieve the first room name."

此下標(biāo)調(diào)用中的可選鏈接問號放在john.residence之后,在下標(biāo)括號之前帜慢,因?yàn)閖ohn.residence是嘗試進(jìn)行可選鏈接的可選值笼裳。

同樣,您可以嘗試通過帶有可選鏈接的下標(biāo)設(shè)置新值:

john.residence?[0] = Room(name: "Bathroom")

該下標(biāo)設(shè)置嘗試也將失敗粱玲,因?yàn)楫?dāng)前居住地為nil躬柬。

如果您創(chuàng)建一個實(shí)際的Residence實(shí)例并將其分配給john.residence,并且在rooms數(shù)組中包含一個或多個Room實(shí)例抽减,則可以使用Residence下標(biāo)通過可選的鏈接訪問Rooms數(shù)組中的實(shí)際項(xiàng)目:

let johnsHouse = Residence()
johnsHouse.rooms.append(Room(name: "Living Room"))
johnsHouse.rooms.append(Room(name: "Kitchen"))
john.residence = johnsHouse

if let firstRoomName = john.residence?[0].name {
    print("The first room name is \(firstRoomName).")
} else {
    print("Unable to retrieve the first room name.")
}
// Prints "The first room name is Living Room."

5.1 訪問可選類型的下標(biāo)

如果下標(biāo)返回的是可選類型的值(例如Swift的Dictionary類型的關(guān)鍵下標(biāo))允青,則在下標(biāo)的右括號后面放置一個問號,以鏈接到其可選的返回值上:

var testScores = ["Dave": [86, 82, 84], "Bev": [79, 94, 81]]
testScores["Dave"]?[0] = 91
testScores["Bev"]?[0] += 1
testScores["Brian"]?[0] = 72
// the "Dave" array is now [91, 82, 84] and the "Bev" array is now [80, 94, 81]

上面的示例定義了一個名為testScores的字典胯甩,該字典包含兩個將字符串鍵映射到Int值數(shù)組的鍵值對昧廷。 該示例使用可選的鏈接將“ Dave”數(shù)組中的第一項(xiàng)設(shè)置為91。 將“ Bev”數(shù)組中的第一項(xiàng)增加1偎箫; 并嘗試為“ Brian”鍵設(shè)置數(shù)組中的第一項(xiàng)木柬。 前兩個調(diào)用成功,因?yàn)閠estScores詞典包含“ Dave”和“ Bev”的鍵淹办。 第三次調(diào)用失敗眉枕,因?yàn)閠estScores詞典不包含“ Brian”的鍵。

6 鏈接多個級別的鏈接

您可以將多個級別的可選鏈接鏈接在一起怜森,以深入挖掘模型中更深的屬性速挑,方法和下標(biāo)。 但是副硅,多個級別的可選鏈接不會為返回的值添加更多級別的可選性姥宝。

換一種方式:

  • 如果您嘗試檢索的類型不是可選的,則由于可選的鏈接恐疲,它將變?yōu)榭蛇x的腊满。
  • 如果您嘗試檢索的類型已經(jīng)是可選的,則由于鏈接的原因培己,它將不再是可選的碳蛋。

因此:

  • 如果您嘗試通過可選鏈接檢索Int值,則為Int省咨? 無論使用多少級鏈接肃弟,總是返回。
  • 同樣,如果您嘗試檢索一個Int笤受? 通過可選的鏈接(Int)獲得Int穷缤? 無論使用多少級鏈接,總是返回箩兽。

下面的示例嘗試訪問john的Residence屬性的address屬性的street屬性绅项。 此處使用兩個級別的可選鏈接,以鏈接駐留和地址屬性比肄,兩者均為可選類型:

if let johnsStreet = john.residence?.address?.street {
    print("John's street name is \(johnsStreet).")
} else {
    print("Unable to retrieve the address.")
}
// Prints "Unable to retrieve the address."

john.residence的值當(dāng)前包含有效的Residence實(shí)例。 但是囊陡,john.residence.address的值當(dāng)前為nil芳绩。 因此,對john.residence撞反?.address妥色?.street的調(diào)用失敗。

請注意遏片,在上面的示例中嘹害,您嘗試檢索street屬性的值。 此屬性的類型為String?吮便。 因此笔呀,即使除了屬性的基礎(chǔ)可選類型之外,還應(yīng)用了兩個級別的可選鏈接髓需,john.residence许师?.address?.street的返回值也是String?僚匆。

如果您將實(shí)際的Address實(shí)例設(shè)置為john.residence.address的值微渠,并為該地址的street屬性設(shè)置了實(shí)際值,則可以通過多層可選鏈訪問street屬性的值:

let johnsAddress = Address()
johnsAddress.buildingName = "The Larches"
johnsAddress.street = "Laurel Street"
john.residence?.address = johnsAddress

if let johnsStreet = john.residence?.address?.street {
    print("John's street name is \(johnsStreet).")
} else {
    print("Unable to retrieve the address.")
}
// Prints "John's street name is Laurel Street."

在此示例中咧擂,設(shè)置john.residence的address屬性的嘗試將成功逞盆,因?yàn)閖ohn.residence的值當(dāng)前包含有效的Residence實(shí)例。

7 鏈接具有可選返回值的方法

前面的示例顯示了如何通過可選鏈接檢索可選類型的屬性的值松申。 您還可以使用可選鏈接來調(diào)用返回可選類型值的方法云芦,并根據(jù)需要鏈接該方法的返回值。

下面的示例通過可選的鏈接調(diào)用Address類的buildingIdentifier()方法攻臀。 此方法返回String焕数?類型的值。 如上所述刨啸,在可選鏈接之后堡赔,此方法調(diào)用的最終返回類型也是String ?:

if let buildingIdentifier = john.residence?.address?.buildingIdentifier() {
    print("John's building identifier is \(buildingIdentifier).")
}
// Prints "John's building identifier is The Larches."

如果要對該方法的返回值執(zhí)行進(jìn)一步的可選鏈接,請?jiān)谠摲椒ǖ睦ㄌ柡蠓胖每蛇x鏈接問號:

if let beginsWithThe =
    john.residence?.address?.buildingIdentifier()?.hasPrefix("The") {
    if beginsWithThe {
        print("John's building identifier begins with \"The\".")
    } else {
        print("John's building identifier does not begin with \"The\".")
    }
}
// Prints "John's building identifier begins with "The"."

注意
在上面的示例中设联,您將可選的鏈接問號放在括號后面善已,因?yàn)橐溄拥目蛇x值是buildingIdentifier()方法的返回值灼捂,而不是buildingIdentifier()方法本身。

總結(jié)

這章內(nèi)容主要講了可選鏈接的作用和用法换团,涉及到“?”和“!”這兩個關(guān)鍵符號悉稠,通過使用?,來判斷是否有值或者為nil艘包,使用可選綁定if-let配合來判斷調(diào)用哪個邏輯的猛。使用!強(qiáng)制解包一定有值的屬性,若為nil想虎,會報錯卦尊;這部分內(nèi)容理解就好。

喜歡的朋友麻煩動動你的??舌厨,點(diǎn)個??哦岂却,謝謝~

上一章節(jié):析構(gòu)函數(shù)

下一章節(jié):錯誤處理

參考文檔:Swift - Optional Chaining

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市裙椭,隨后出現(xiàn)的幾起案子躏哩,更是在濱河造成了極大的恐慌,老刑警劉巖揉燃,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件扫尺,死亡現(xiàn)場離奇詭異,居然都是意外死亡炊汤,警方通過查閱死者的電腦和手機(jī)器联,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來婿崭,“玉大人拨拓,你說我怎么就攤上這事∶フ唬” “怎么了渣磷?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長授瘦。 經(jīng)常有香客問我醋界,道長,這世上最難降的妖魔是什么提完? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任形纺,我火速辦了婚禮,結(jié)果婚禮上徒欣,老公的妹妹穿的比我還像新娘逐样。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布脂新。 她就那樣靜靜地躺著挪捕,像睡著了一般。 火紅的嫁衣襯著肌膚如雪争便。 梳的紋絲不亂的頭發(fā)上级零,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天,我揣著相機(jī)與錄音滞乙,去河邊找鬼奏纪。 笑死,一個胖子當(dāng)著我的面吹牛斩启,可吹牛的內(nèi)容都是我干的亥贸。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼浇垦,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了荣挨?” 一聲冷哼從身側(cè)響起男韧,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎默垄,沒想到半個月后此虑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡口锭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年朦前,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鹃操。...
    茶點(diǎn)故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡韭寸,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出荆隘,到底是詐尸還是另有隱情恩伺,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布椰拒,位于F島的核電站晶渠,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏燃观。R本人自食惡果不足惜褒脯,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望缆毁。 院中可真熱鬧番川,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至适篙,卻和暖如春往核,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背嚷节。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工聂儒, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人硫痰。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓衩婚,卻偏偏與公主長得像,于是被迫代替她去往敵國和親效斑。 傳聞我的和親對象是個殘疾皇子非春,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評論 2 355