iOS | Swift5.0學習 & 總結(二)

image.png

Swift 結構體和類

結構體

在 Swift 標準庫中芭商,絕大多數(shù)的公開類型都是結構體搀缠,而枚舉和類只占很小一部分
比如Bool艺普、Int、Double岸浑、 String缴罗、Array面氓、Dictionary等常見類型都是結構體

1. 初始化器

所有的結構體都有一個編譯器自動生成的初始化器(initializer,初始化方法掘譬、構造器呻拌、構造方法)

struct Date {
    var year: Int
    var month: Int
    var day: Int
}
// 可以傳入所有成員值,用以初始化所有成員(存儲屬性靴拱,Stored Property)
var date = Date(year: 2019, month: 06, day: 29)

如果給屬性設置可選變量,則會生成多個構造器(初始化器)

 struct Point {
    var x: Int?
    var y: Int?
}
var p1 = Point(x: 10, y: 10)
var p2 = Point(y: 10)
var p3 = Point(x: 10)
var p4 = Point()


1. 類的初始化器

  • 類的定義和結構體類似猾普,但編譯器并沒有為類自動生成可以傳入成員值的初始化器
  • 如果類的所有成員都在定義的時候指定了初始值初家,編譯器會為類生成無參的初始化器
class Point {
    var x: Int = 0
    var y: Int = 0
}
var point = Point()

2. 結構體與類的本質區(qū)別

結構體是值類型(枚舉也是值類型)乌助,類是引用類型(指針類型)

image.png

值類型

  • 值類型賦值給var他托、let或者給函數(shù)傳參赏参,是直接將所有內容拷貝一份
    • 類似于對文件進行copy浙芙、paste操作嗡呼,產生了全新的文件副本。屬于深拷貝(deep copy)
  • 在Swift標準庫中揍很,為了提升性能万伤,String敌买、Array、Dictionary聋庵、Set采取了Copy On Write的技術
    • 比如僅當有“寫”操作時祭玉,才會真正執(zhí)行拷貝操作
    • 對于標準庫值類型的賦值操作春畔,Swift 能確保最佳性能律姨,所有沒必要為了保證最佳性能來避免賦值
  • 建議:不需要修改的,盡量定義成let

引用類型

  • 引用賦值給var铺韧、let或者給函數(shù)傳參缓淹,是將內存地址拷貝一份
    • 類似于制作一個文件的替身(快捷方式讯壶、鏈接),指向的是同一個文件立轧。屬于淺拷貝(shallow copy)




Swift 屬性

1. 存儲屬性&計算屬性

Swift中跟實例對象相關的屬性可以分為2大類

存儲屬性(Stored Property)

  • 類似于成員變量這個概念
  • 存儲在實例對象的內存中
  • 結構體氛改、類可以定義存儲屬性
  • 枚舉不可以定義存儲屬性

計算屬性(Computed Property)

  • 本質就是方法(函數(shù))
  • 不占用實例對象的內存
  • 枚舉比伏、結構體赁项、類都可以定義計算屬性
struct Circle {
    // 存儲屬性
    var radius: Double
    // 計算屬性
    var diameter: Double {
        set {
            radius = newValue / 2
        }
        get {
            return radius * 2
        }
    }
}

2. 計算屬性

set傳入的新值默認叫做newValue悠菜,也可以自定義

 struct Circle {
    var radius: Double
    var diameter: Double {
        set(newDiameter) {
            radius = newDiameter / 2
        } 
        get {
            radius * 2 }
        } 
}

只讀計算屬性:只有get,沒有set

struct Circle {
    var radius: Double
    var diameter: Double {
        get {
            radius * 2
        } 
    }
}
  • 定義計算屬性只能用var摩窃,不能用let
    • let代表常量:值是一成不變的
    • 計算屬性的值是可能發(fā)生變化的(即使是只讀計算屬性)

3. 枚舉rawValue原理

枚舉原始值rawValue的本質是:只讀計算屬性

 enum TestEnum : Int {
    case test1 = 1, test2 = 2, test3 = 3
    var rawValue: Int {
        switch self {
        case .test1:
            return 10
        case .test2:
            return 11
        case .test3:
            return 12 }
    } 
}

4. 延遲存儲屬性(Lazy Stored Property)

使用lazy可以定義一個延遲存儲屬性猾愿,在第一次用到屬性的時候才會進行初始化

  • lazy屬性必須是var德玫,不能是let
    • let必須在實例對象的初始化方法完成之前就擁有值
  • 如果多條線程同時第一次訪問lazy屬性
    • 無法保證屬性只被初始化1次
class PhotoView {
    lazy var image: Image = {
        let url = "https://www.../xx.png"        
        let data = Data(url: url)
        return Image(data: data)
    }() 
} 

5. 屬性觀察器(Property Observer)

可以為非lazy的var存儲屬性設置屬性觀察器

struct Circle {
    var radius: Double {
        willSet {
            print("willSet", newValue)
       } 
       didSet {
            print("didSet", oldValue, radius)
        }
   } 
  init() {
        self.radius = 1.0
        print("Circle init!")
    }
}
  • willSet會傳遞新值宰僧,默認叫newValue
    • didSet會傳遞舊值琴儿,默認叫oldValue
    • 在初始化器中設置屬性值不會觸發(fā)willSet和didSet

6.類型屬性(Type Property)

嚴格來說,屬性可以分為

實例屬性(Instance Property): 只能通過實例對象去訪問

  • 存儲實例屬性(Stored Instance Property):存儲在實例對象的內存中显熏,每個實例對象都有1份
  • 計算實例屬性(Computed Instance Property)

類型屬性(Type Property):只能通過類型去訪問

  • 存儲類型屬性(Stored Type Property):整個程序運行過程中喘蟆,就只有1份內存(類似于全局變量)
  • 計算類型屬性(Computed Type Property)

可以通過static定義類型屬性 p如果是類,也可以用關鍵字class

struct Car {
    static var count: Int = 0
    init() {
        Car.count += 1
    }
}

不同于存儲實例屬性港谊,你必須給存儲類型屬性設定初始值

  • 因為類型沒有像實例對象那樣的init初始化器來初始化存儲屬性

存儲類型屬性默認就是lazy歧寺,會在第一次使用的時候才初始化

  • 就算被多個線程同時訪問棘脐,保證只會初始化一次
  • 存儲類型屬性可以是let

枚舉類型也可以定義類型屬性(存儲類型屬性蛀缝、計算類型屬性)

7. 單例模式

通過 類型屬性+let+private 來寫單例;

 public class FileManager {
    public static let shared = {
        // ....
        // ....
        return FileManager()
     }()
    private init() { }
}




Swift 方法

枚舉、結構體蕴潦、類都可以定義實例方法潭苞、類型方法

  • 實例方法(Instance Method):通過實例對象調用
  • 類型方法(Type Method):通過類型調用真朗,用static或者class關鍵字定義
 class Car {
    static var cout = 0
    init() {
        Car.cout += 1
    }
    static func getCount() -> Int { cout }
}
let c0 = Car()
let c1 = Car()
let c2 = Car()
print(Car.getCount()) // 3

self
1.在實例方法中代表實例對象
2.在類型方法中代表類型

在類型方法static func getCount中
cout等價于self.cout遮婶、Car.self.cout、Car.cout

1.mutating

結構體和枚舉是值類型蹦骑,默認情況下臀防,值類型的屬性不能被自身的實例方法修改

  • 在func關鍵字前加mutating可以允許這種修改行為
struct Point {
    var x = 0.0, y = 0.0
    mutating func moveBy(deltaX: Double, deltaY: Double) {
        x += deltaX
        y += deltaY
        // self = Point(x: x + deltaX, y: y + deltaY)
} }

2. @discardableResult

在func前面加個@discardableResult袱衷,可以消除:函數(shù)調用后返回值未被使用的警告

struct Point {
   var x = 0.0, y = 0.0
   
   @discardableResult mutating
   func moveX(deltaX: Double) -> Double {
       x += deltaX
   return x }
}
var p = Point()
p.moveX(deltaX: 10)
@discardableResult
func get() -> Int {
return 10 }
get()




Swift 下標

使用subscript可以給任意類型(枚舉致燥、結構體、類)增加下標功能辐益,有些地方也翻譯為:下標腳本

  • subscript的語法類似于實例方法智政、計算屬性,本質就是方法(函數(shù))
class Point {
    var x = 0.0, y = 0.0
    subscript(index: Int) -> Double {
        set {
            if index == 0 {
                x = newValue
            } else if index == 1 {
                y = newValue }
        }
        get {
            if index == 0 {
                return x
            } else if index == 1 {
                return y
            }
            return 0
        }
    }
}

var p = Point()
p[0] = 11.1
p[1] = 22.2
print(p.x) // 11.1
print(p.y) // 22.2
print(p[0]) // 11.1
print(p[1]) // 22.2
  • subscript中定義的返回值類型決定了
    • get方法的返回值類型
    • set方法中newValue的類型
  • subscript可以接受多個參數(shù),并且類型任意

1. 下標的細節(jié)

  • subscript可以沒有set方法疾忍,但必須要有get方法
class Point {
    var x = 0.0, y = 0.0
    subscript(index: Int) -> Double {
        get {
            if index == 0 {
                return x
            } else if index == 1 {
return y }
return 0 }
} }
  • 如果只有get方法一罩,可以省略get
class Point {
    var x = 0.0, y = 0.0
    subscript(index: Int) -> Double {
        if index == 0 {
            return x
        } else if index == 1 {
            return y
    }
    return 0 
    }
}
  • 可以設置參數(shù)標簽
class Point {
    var x = 0.0, y = 0.0
    subscript(index i: Int) -> Double {
        if i == 0 {
            return x
        } else if i == 1 {
            return y
}
return 0 }
}
  • 下標可以是類型方法
class Sum {
    static subscript(v1: Int, v2: Int) -> Int {
        return v1 + v2
    }
}
print(Sum[10, 20]) // 30

2. 接收多個參數(shù)的下標

class Grid {
    var data = [
        [0, 1, 2],
        [3, 4, 5],
        [6, 7, 8]
]
subscript(row: Int, column: Int) -> Int {
set {
guard row >= 0 && row < 3 && column >= 0 && column < 3 else {
return
}
data[row][column] = newValue }
get {
guard row >= 0 && row < 3 && column >= 0 && column < 3 else {
return 0 }
return data[row][column] }
} }

var grid = Grid()
grid[0, 1] = 77
grid[1, 2] = 88
grid[2, 0] = 99
print(grid.data)
 




Swift 繼承

  1. 值類型(枚舉聂渊、結構體)不支持繼承汉嗽,只有類支持繼承
  2. 沒有父類的類找蜜,稱為:基類 ,Swift并沒有像OC洗做、Java那樣的規(guī)定:任何類最終都要繼承自某個基類
  3. 子類可以重寫父類的下標、方法撰筷、屬性畦徘,重寫必須加上override關鍵字
class Animal {
   var age = 0
}
class Dog : Animal {
   var weight = 0
}
class ErHa : Dog {
   var iq = 0
}

1. 重寫實例方法旧烧、下標

class Animal {
    func speak() {
        print("Animal speak")
    }
    subscript(index: Int) -> Int {
        return index
} }

var anim: Animal
anim = Animal()
// Animal speak
anim.speak()
// 6
print(anim[6])
class Cat : Animal {
    override func speak() {
        super.speak()
        print("Cat speak")
    }
    override subscript(index: Int) -> Int {
        return super[index] + 1
} }

anim = Cat()
// Animal speak
// Cat speak
anim.speak()
// 7
print(anim[6])
  • 被class修飾的類型方法掘剪、下標,允許被子類重寫
  • 被static修飾的類型方法廉赔、下標蜡塌,不允許被子類重寫

2. 重寫屬性

  • 子類可以將父類的屬性(存儲、計算)重寫為計算屬性
  • 子類不可以將父類屬性重寫為存儲屬性
  • 只能重寫var屬性劳曹,不能重寫let屬性
  • 重寫時铁孵,屬性名房资、類型要一致
  • 子類重寫后的屬性權限 不能小于 父類屬性的權限
    • 如果父類屬性是只讀的轰异,那么子類重寫后的屬性可以是只讀的、也可以是可讀寫的
    • 如果父類屬性是可讀寫的婴削,那么子類重寫后的屬性也必須是可讀寫的

3. 屬性觀察器

可以在子類中為父類屬性(除了只讀計算屬性馆蠕、let屬性)增加屬性觀察器

class Circle {
    var radius: Int = 1
}
class SubCircle : Circle {
    override var radius: Int {
        willSet {
            print("SubCircle willSetRadius", newValue) }
        didSet {
            print("SubCircle didSetRadius", oldValue, radius)
        } }
}
var circle = SubCircle()
// SubCircle willSetRadius 10 // SubCircle didSetRadius 1 10 circle.radius = 10
class Circle {
    var radius: Int = 1 {
        willSet {
            print("Circle willSetRadius", newValue)
        } didSet {
            print("Circle didSetRadius", oldValue, radius) }
    }
}

class SubCircle : Circle {
    override var radius: Int {
        willSet {
            print("SubCircle willSetRadius", newValue)
        } didSet {
            print("SubCircle didSetRadius", oldValue, radius) }
    }
}
class Circle {
    var radius: Int {
        set {
            print("Circle setRadius", newValue)
        } get {
            print("Circle getRadius")
            return 20 }
    }
}
class SubCircle : Circle {
    override var radius: Int {
        willSet {
            print("SubCircle willSetRadius", newValue)
        } didSet {
            print("SubCircle didSetRadius", oldValue, radius) }
    }
}

4. final

  • 被final修飾的方法互躬、下標颂郎、屬性乓序,禁止被重寫
  • 被final修飾的類,禁止被繼承




Swift 初始化

1. 初始化器

類寄雀、結構體陨献、枚舉都可以定義初始化器

類有2種初始化器: 指定初始化器(designated initializer)便捷初始化器(convenience initializer)

 // 指定初始化器 
init(parameters) {
    statements 
}
// 便捷初始化器
convenience init(parameters) {
    statements 
} 

規(guī)則:

  • 每個類至少有一個指定初始化器沮协,指定初始化器是類的主要初始化器
  • 默認初始化器總是類的指定初始化器
  • 類偏向于少量指定初始化器卓嫂,一個類通常只有一個指定初始化器

初始化器的相互調用規(guī)則

  • 指定初始化器必須從它的直系父類調用指定初始化器
  • 便捷初始化器必須從相同的類里調用另一個初始化器
  • 便捷初始化器最終必須調用一個指定初始化器
// 便捷初始化器最終必須調用一個 指定初始化器,保證安全,保證所有屬性都被初始化
class Person {
    var name: String
    var age: Int
    var height: Int {
        get {
            return age*10;
        }
    }
    // 指定初始化器
    init(name: String, age: Int) {
        self.name = name;
        self.age = age;
    }
    
    // 便捷初始化器
    convenience init(name: String){
        self.init(name: name, age: 0);
    }

    // 便捷初始化器
    convenience init (age: Int) {
        self.init(name: "", age: age);
    }

    // 便捷初始化器
    convenience init(){
        self.init(name: "", age: 0);
    }
}

var ppp = Person(age: 10);
var ppp1 = Person(name: "alex");
var PPP2 = Person(name: "alex", age: 10);

初始化器的相互調用

image.png

2. 兩段式初始化

Swift在編碼安全方面是煞費苦心行瑞,為了保證初始化過程的安全蘑辑,設定了兩段式初始化坠宴、 安全檢查

兩段式初始化

  • 第1階段:初始化所有存儲屬性

    1. 外層調用指定\便捷初始化器
    2. 分配內存給實例喜鼓,但未初始化
    3. 指定初始化器確保當前類定義的存儲屬性都初始化
    4. 指定初始化器調用父類的初始化器,不斷向上調用衔肢,形成初始化器鏈
  • 第2階段:設置新的存儲屬性值

    1. 從頂部初始化器往下庄岖,鏈中的每一個指定初始化器都有機會進一步定制實例
    2. 初始化器現(xiàn)在能夠使用self(訪問、修改它的屬性角骤,調用它的實例方法等等)
    3. 最終隅忿,鏈中任何便捷初始化器都有機會定制實例以及使用self

3. 安全檢查

  • 指定初始化器必須保證在調用父類初始化器之前,其所在類定義的所有存儲屬性都要初始化完成
  • 指定初始化器必須先調用父類初始化器邦尊,然后才能為繼承的屬性設置新值
  • 便捷初始化器必須先調用同類中的其它初始化器背桐,然后再為任意屬性設置新值
  • 初始化器在第1階段初始化完成之前蝉揍,不能調用任何實例方法链峭、不能讀取任何實例屬性的值,也不能引用self n 直到第1階段結束又沾,實例才算完全合法

4. 重寫

  • 當重寫父類的指定初始化器時弊仪,必須加上override(即使子類的實現(xiàn)是便捷初始化器)
  • 如果子類寫了一個匹配父類便捷初始化器的初始化器,不用加上override
    • 因為父類的便捷初始化器永遠不會通過子類直接調用杖刷,因此励饵,嚴格來說,子類無法重寫父類的便捷初始化器

5.自動繼承

  • 如果子類沒有自定義任何指定初始化器滑燃,它會自動繼承父類所有的指定初始化器
  • 如果子類提供了父類所有指定初始化器的實現(xiàn)(要么通過方式1繼承役听,要么重寫)
    • 子類自動繼承所有的父類便捷初始化器
  • 就算子類添加了更多的便捷初始化器,這些規(guī)則仍然適用
  • 子類以便捷初始化器的形式重寫父類的指定初始化器,也可以作為滿足規(guī)則2的一部分

6.required

  • 用required修飾指定初始化器禾嫉,表明其所有子類都必須實現(xiàn)該初始化器(通過繼承或者重寫實現(xiàn))
  • 如果子類重寫了required初始化器灾杰,時也必須加上required,不用加override
class Person {
    required init() { }
    init(age: Int) { }
}
class Student: Person {
    required init() {
        super.init()
    }
}

7.屬性觀察器

父類的屬性在它自己的初始化器中賦值不會觸發(fā)屬性觀察器熙参,但在子類的初始化器中賦值會觸發(fā)屬性觀察器

class Person {
    var age: Int {
        willSet {
            print("willSet", newValue)
} didSet {
            print("didSet", oldValue, age)
        }
} init() {
self.age = 0 }
}

class Student: Person {
    override init() {
        super.init()
self.age = 1 }
}
// willSet 1
// didSet 0 1
var stu = Student()
 

8.可失敗初始化器

類艳吠、結構體、枚舉都可以使用init?定義可失敗初始化器

class Person {
    var name: String
    init?(name: String) {
        if name.isEmpty  {
            return nil
}
        self.name = name
    }
}
  • 不允許同時定義參數(shù)標簽孽椰、參數(shù)個數(shù)昭娩、參數(shù)類型相同的可失敗初始化器和非可失敗初始化器
  • 可以用init!定義隱式解包的可失敗初始化器
  • 可失敗初始化器可以調用非可失敗初始化器,非可失敗初始化器調用可失敗初始化器需要進行解包
  • 如果初始化器調用一個可失敗初始化器導致初始化失敗黍匾,那么整個初始化過程都失敗栏渺,并且之后的代碼都停止執(zhí)行
  • 可以用一個非可失敗初始化器重寫一個可失敗初始化器,但反過來是不行的

9.反初始化器(deinit)

deinit叫做反初始化器锐涯,類似于C++的析構函數(shù)磕诊、OC中的dealloc方法

  • 當類的實例對象被釋放內存時,就會調用實例對象的deinit方法
 class Person {
    deinit {
        print("Person對象銷毀了") 
    }
}
  • deinit不接受任何參數(shù)纹腌,不能寫小括號霎终,不能自行調用
  • 父類的deinit能被子類繼承
  • 子類的deinit實現(xiàn)執(zhí)行完畢后會調用父類的deinit




Swift 可選鏈

可選鏈是一個調用和查詢可選屬性、方法和下標的過程升薯,它可能為 nil 莱褒。如果可選項包含值,屬性涎劈、方法或者下標的調用成功广凸;如果可選項是 nil ,屬性蛛枚、方法或者下標的調用會返回 nil 谅海。多個查詢可以鏈接在一起,如果鏈中任何一個節(jié)點是 nil 蹦浦,那么整個鏈就會得體地失敗胁赢。


class Car { var price = 0 }
class Dog { var weight = 0 }
class Person {
    var name: String = ""
    var dog: Dog = Dog()
    var car: Car? = Car()
    func age() -> Int {
        return 18
        
    }
    func eat() {
        print("Person eat")
    }
    subscript(index: Int) -> Int {
        return index
        
    }
}

var person: Person? = Person()
var age1 = person!.age() // Int
var age2 = person?.age() // Int?
var name = person?.name // String?
var index = person?[6] // Int?

func getName() -> String { return "jack" }
// 如果person是nil,不會調用getName()
person?.name = getName()
  • 如果可選項為nil白筹,調用方法智末、下標、屬性失敗徒河,結果為nil
  • 如果可選項不為nil系馆,調用方法、下標顽照、屬性成功由蘑,結果會被包裝成可選項
    • 如果結果本來就是可選項闽寡,不會進行再次包裝
var dog = person?.dog // Dog?
var weight = person?.dog.weight // Int? 
var price = person?.car?.price // Int?
  • 多個?可以鏈接在一起
    • 如果鏈中任何一個節(jié)點是nil,那么整個鏈就會調用失敗
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末尼酿,一起剝皮案震驚了整個濱河市爷狈,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌裳擎,老刑警劉巖涎永,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異鹿响,居然都是意外死亡羡微,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門惶我,熙熙樓的掌柜王于貴愁眉苦臉地迎上來妈倔,“玉大人,你說我怎么就攤上這事绸贡《⒑” “怎么了?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵听怕,是天一觀的道長结洼。 經常有香客問我,道長叉跛,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任蒸殿,我火速辦了婚禮筷厘,結果婚禮上,老公的妹妹穿的比我還像新娘宏所。我一直安慰自己酥艳,他們只是感情好,可當我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布爬骤。 她就那樣靜靜地躺著充石,像睡著了一般。 火紅的嫁衣襯著肌膚如雪霞玄。 梳的紋絲不亂的頭發(fā)上骤铃,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天,我揣著相機與錄音坷剧,去河邊找鬼惰爬。 笑死,一個胖子當著我的面吹牛惫企,可吹牛的內容都是我干的撕瞧。 我是一名探鬼主播陵叽,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼丛版!你這毒婦竟也來了巩掺?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤页畦,失蹤者是張志新(化名)和其女友劉穎胖替,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體寇漫,經...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡刊殉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了州胳。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片记焊。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖栓撞,靈堂內的尸體忽然破棺而出遍膜,到底是詐尸還是另有隱情,我是刑警寧澤瓤湘,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布瓢颅,位于F島的核電站,受9級特大地震影響弛说,放射性物質發(fā)生泄漏挽懦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一木人、第九天 我趴在偏房一處隱蔽的房頂上張望信柿。 院中可真熱鬧,春花似錦醒第、人聲如沸渔嚷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽形病。三九已至,卻和暖如春霞幅,著一層夾襖步出監(jiān)牢的瞬間漠吻,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工司恳, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留侥猩,地道東北人。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓抵赢,卻偏偏與公主長得像欺劳,于是被迫代替她去往敵國和親唧取。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內容