第十一章——編輯UITableView【譯】

在上一章中管呵,您創(chuàng)建了一個(gè)在 UITableView 中顯示 Item 實(shí)例列表的應(yīng)用程序兴垦。 下一步是允許用戶與表進(jìn)行交互——添加日矫,刪除和移動行茵汰。 圖11.1顯示了本章結(jié)束后的 Homepwner枢里。

圖11.1 編輯模式下的Homepwner

編輯模式

UITableView 有一個(gè) editing 屬性,當(dāng)該屬性設(shè)置為 true 時(shí),UITableView 進(jìn)入編輯模式栏豺。 表視圖處于編輯模式后彬碱,表的行可由用戶操縱。 根據(jù)表視圖的配置方式奥洼,用戶可以更改行的順序巷疼,添加行或刪除行。(編輯模式不允許用戶編輯行的文本內(nèi)容灵奖。)

但首先嚼沿,用戶需要一個(gè)將 UITableView 置于編輯模式的方法。 現(xiàn)在瓷患,您將在表的 頭部視圖(header view) 中添加一個(gè)按鈕骡尽。 頭部視圖顯示在表格的頂部,對于添加 section 范圍內(nèi) 或 表范圍內(nèi) 的標(biāo)題和控件很有用擅编。它可以是任何 UIView 實(shí)例攀细。

請注意,表視圖有兩種 “header” : table header 和 section header爱态。 同樣谭贪,也有 table footer 和 section footer(圖11.2)。

圖11.2 header 和 footer

您正在創(chuàng)建一個(gè)頭部視圖锦担。 它將有兩個(gè)子視圖并且是 UIButton 的實(shí)例:一個(gè)用于切換編輯模式俭识,另一個(gè)用于在表中添加一個(gè)新的 Item。 您可以以編程方式創(chuàng)建此視圖吆豹,但在這種情況下鱼的,您將在故事板文件中創(chuàng)建這個(gè)視圖及其子視圖理盆。

首先痘煤,我們設(shè)置必要的代碼。 重新打開 Homepwner.xcodeproj猿规。 在 ItemsViewController.swift 中衷快,實(shí)現(xiàn)兩個(gè)方法。

class ItemsViewController: UITableViewController {

??var itemStore: ItemStore!

??@IBAction func addNewItem(_ sender: UIButton) {

??}

??@IBAction func toggleEditingMode(_ sender: UIButton) {

??}

現(xiàn)在打開 Main.storyboard姨俩。 從對象庫中蘸拔,將 View 拖動到 prototype cell 上方的表視圖的最頂部。 這將添加視圖作為表視圖的 頭部視圖环葵。 調(diào)整這個(gè)視圖的高度大約為 60 點(diǎn)调窍。 (如果你要確切地修改,可以使用尺寸檢查器)张遭。

現(xiàn)在將兩個(gè) Button 從對象庫拖動到頭部視圖邓萨。 更改文本并定位它們,如圖11.3所示。 您不需要和圖中一樣精確——您將很快添加約束來定位按鈕缔恳。

圖11.3添加按鈕到頭部視圖

選擇這兩個(gè)按鈕并打開 自動布局 Align 菜單宝剖。 在 Vertically in Container 選擇常量0.確保 Update Frames 設(shè)置為 None,然后單擊 Add 2 Constraints(圖11.4)歉甚。

圖11.4 對齊(Align)菜單約束

打開 Add New Constraints 菜單并進(jìn)行配置万细,如圖11.5所示。 確保在鍵入它們之后保存 前部(leading) 和 尾部(trailing) 約束的值; 有時(shí)值不會保存纸泄,所以有點(diǎn)棘手赖钞。 完成后,單擊 Add 4 Constraints聘裁。

圖11.5 添加新約束

最后仁烹,連接兩個(gè)按鈕的動作,如圖11.6所示咧虎。

圖11.6連接兩個(gè)動作

構(gòu)建并運(yùn)行應(yīng)用程序以查看界面卓缰。

現(xiàn)在我們來實(shí)現(xiàn) toggleEditingMode(_ :) 方法。 您可以直接修改 UITableViewediting 屬性砰诵。 但是征唬, UIViewController 也有 editing 屬性。 UITableViewController 實(shí)例自動設(shè)置其表視圖的 editing 屬性以匹配自己的 editing 屬性茁彭。 通過在視圖控制器本身設(shè)置 editing 屬性总寒,可以確保界面的其他方面也同時(shí)進(jìn)入或離開編輯模式。例子將在第14章中 UIViewControllereditButtonItem 看到理肺。

要設(shè)置視圖控制器的 isEditing 屬性摄闸,可以調(diào)用 setEditing(_:animated :) 方法。 在 ItemsViewController.swift 中妹萨,實(shí)現(xiàn) toggleEditingMode(_ :)年枕。

@IBAction func toggleEditingMode(_ sender: UIButton) {
??// If you are currently in editing mode...
??if isEditing {
????// Change text of button to inform user of state
????sender.setTitle("Edit", for: .normal)

????// Turn off editing mode
????setEditing(false, animated: true)
??} else {
????// Change text of button to inform user of state
????sender.setTitle("Done", for: .normal)

????// Enter editing mode
????setEditing(true, animated: true)
??}
}

構(gòu)建并運(yùn)行您的應(yīng)用程序。 點(diǎn)擊 Edit 按鈕乎完,UITableView 將進(jìn)入編輯模式(圖11.7)熏兄。

圖11.7 編輯模式下的UITableView

添加行

在運(yùn)行時(shí),有兩個(gè)通用的界面用于在表視圖中添加行树姨。

  • 表格視圖cell上方的按鈕:通常用于添加有詳細(xì)視圖的記錄摩桶。 例如,在 聯(lián)系人(Contacts) 應(yīng)用中帽揪,當(dāng)您遇到新人并想要取消他或她的信息時(shí)硝清,您可以點(diǎn)擊一個(gè)按鈕。
  • 具有綠色加號的cell:通常用于向記錄添加新字段转晰,例如當(dāng)您要在 聯(lián)系人(Contacts) 應(yīng)用程序中為個(gè)人記錄添加生日時(shí)芦拿。 在編輯模式下砾肺,點(diǎn)擊 添加生日(add birthday) 旁邊的綠色加號。

在本練習(xí)中防嗡,您將使用第一個(gè)選項(xiàng)变汪,并在標(biāo)題視圖中創(chuàng)建一個(gè)新按鈕。 當(dāng)點(diǎn)擊此按鈕時(shí)蚁趁,新行將添加到 UITableView裙盾。

ItemsViewController.swift 中,實(shí)現(xiàn) addNewItem(_ :)他嫡。

@IBAction func addNewItem(_ sender: UIButton) {
??// Make a new index path for the 0th section, last row
??let lastRow = tableView.numberOfRows(inSection: 0)
??let indexPath = IndexPath(row: lastRow, section: 0)

??// Insert this new row into the table

??tableView.insertRows(at: [indexPath], with: .automatic)
}

構(gòu)建并運(yùn)行應(yīng)用程序番官。 點(diǎn)擊 Add 按鈕,...應(yīng)用程序崩潰钢属。 控制臺告訴您徘熔,表視圖有內(nèi)部不一致(internal inconsistency) 異常。

記住淆党,最終酷师,UITableViewdataSource 決定了表視圖應(yīng)該顯示的行數(shù)。 插入新行后染乌,表視圖有六行(原來的五行加上新行)山孔。 當(dāng) UITableView 詢問其 dataSource 的行數(shù)時(shí),ItemsViewController 會咨詢該 store 并返回應(yīng)該有五行荷憋。 UITableView 無法解決這種不一致并引發(fā)異常台颠。

您必須確保 UITableView 及其 dataSource 在插入新行之前通過向 ItemStore 中添加 Item 來改變行數(shù)。

ItemsViewController.swift 中勒庄,更新 addNewItem(_ :)串前。

@IBAction func addNewItem(_ sender: UIButton) {
??Make a new index path for the 0th section, last row
??let lastRow = tableView.numberOfRows(inSection: 0)
??let indexPath = IndexPath(row: lastRow, section: 0)

??Insert this new row into the table
??tableView.insertRows(at: [indexPath], with: .automatic)

??Create a new item and add it to the store
??let newItem = itemStore.createItem()

??// Figure out where that item is in the array
??if let index = itemStore.allItems.index(of: newItem) {
????let indexPath = IndexPath(row: index, section: 0)
????// Insert this new row into the table
????tableView.insertRows(at: [indexPath], with: .automatic)
??}
}

運(yùn)行應(yīng)用程序。 點(diǎn)擊 Add 按鈕实蔽,新行將滑動到表的底部位置荡碾。 請記住,視圖對象的作用是將模型對象呈現(xiàn)給用戶; 更新視圖而不更新模型對象沒什么卵用盐须。

現(xiàn)在您可以添加行和 item玩荠,您不再需要將五個(gè)隨機(jī)項(xiàng)目放入 store 的代碼漆腌。

打開 ItemStore.swift 并刪除初始化程序代碼贼邓。

init() {
??for _ in 0..<5 {
????createItem()
??}
}

構(gòu)建并運(yùn)行應(yīng)用程序。 首次啟動應(yīng)用程序時(shí)闷尿,不再有任何行塑径,但您可以通過點(diǎn)擊 Add 按鈕添加一些行。

刪除行

在編輯模式中填具,帶有減號(如圖11.7所示)的紅色圓圈是刪除控件统舀,然后點(diǎn)擊一個(gè)應(yīng)該會刪除該行匆骗。 但是,在這一點(diǎn)上誉简,您實(shí)際上不能刪除該行碉就。 (嘗試看看。)在表視圖刪除一行之前闷串,它會在其數(shù)據(jù)源上調(diào)用關(guān)于建議刪除的方法瓮钥,并等待確認(rèn)。

刪除 cell 時(shí)烹吵,您必須做兩件事情:從 UITableView 中刪除該行碉熄,并從 ItemStore 中刪除與之相關(guān)聯(lián)的 Item。 要將其關(guān)閉肋拔,ItemStore 必須知道如何從其中刪除對象锈津。

ItemStore.swift 中,實(shí)現(xiàn)一個(gè)新的方法來刪除特定的 item凉蜂。

func removeItem(_ item: Item) {
??if let index = allItems.index(of: item) {
????allItems.remove(at: index)
??}
}

你將會實(shí)現(xiàn) tableView(_:commit:forRow :)琼梆,一個(gè) UITableViewDataSource 協(xié)議的方法。(這個(gè)方法在 ItemsViewController 上調(diào)用窿吩,請記住叮叹,盡管 ItemStore 是保存數(shù)據(jù)的地方,而 ItemsViewController 才是表視圖的 dataSource爆存。)

當(dāng)在數(shù)據(jù)源上調(diào)用 tableView(_:commit:forRowAt :) 時(shí)蛉顽,會傳遞兩個(gè)額外的參數(shù)。 第一個(gè)是 UITableViewCellEditingStyle先较,在這種情況下携冤,它是 .delete。 另一個(gè)參數(shù)是表中行的 IndexPath闲勺。

ItemsViewController.swift 中曾棕,實(shí)現(xiàn)此方法使 ItemStore 刪除正確的對象,并通過在表視圖上調(diào)用 deleteRows(at:with :) 方法來確認(rèn)刪除行菜循。

override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
??// If the table view is asking to commit a delete command...
??if editingStyle == .delete {
????let item = itemStore.allItems[indexPath.row]
????// Remove the item from the store
????itemStore.removeItem(item)

????// Also remove that row from the table view with an animation
????tableView.deleteRows(at: [indexPath], with: .automatic)
??}
}

構(gòu)建并運(yùn)行應(yīng)用程序翘地,創(chuàng)建一些行,然后刪除一行癌幕。 它就會消失衙耕。請注意,滑動刪除也可以勺远。

移動行

要更改 UITableView 中的行順序橙喘,您將使用 UITableViewDataSource 協(xié)議中的另一個(gè)方法——tableView(_:moveRowAt:to :)

要?jiǎng)h除一行胶逢,您必須在 UITableView 上調(diào)用 deleteRows(at :)厅瞎,以確認(rèn)刪除饰潜。 但是,移動一行不需要確認(rèn):表視圖會自動移動該行和簸,并通過調(diào)用 tableView(_:moveRowAt:to :) 方法來報(bào)告數(shù)據(jù)源發(fā)生了移動彭雾。 實(shí)現(xiàn)此方法來更新數(shù)據(jù)源以匹配新順序。

但是锁保,在實(shí)現(xiàn)此方法之前冠跷,您需要給 ItemStore 一個(gè)方法來更改其 allItems 數(shù)組中 item 的順序。

ItemStore.swift 中身诺,實(shí)現(xiàn)這個(gè)新方法蜜托。

func moveItem(from fromIndex: Int, to toIndex: Int) {
??if fromIndex == toIndex {
????return
??}

??// Get reference to object being moved so you can reinsert it
??let movedItem = allItems[fromIndex]

??// Remove item from array
??allItems.remove(at: fromIndex)

??// Insert item in array at new location
??allItems.insert(movedItem, at: toIndex)
}

ItemsViewController.swift 中,實(shí)現(xiàn) tableView(_:moveRowAt:to :) 來更新 store霉赡。

override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
??// Update the model
??itemStore.moveItem(from: sourceIndexPath.row, to: destinationIndexPath.row)
}

運(yùn)行你的應(yīng)用程序橄务。 添加幾個(gè) item,然后點(diǎn)擊編輯穴亏,并查看每一行側(cè)面的新的重新排序控件(三條水平線)蜂挪。 觸摸并按住重新排序控件并將該行移動到新位置(圖11.8)。

圖11.8移動一行

請注意嗓化,簡單地實(shí)現(xiàn) tableView(_:moveRowAt:to :) 會導(dǎo)致重新排序控件出現(xiàn)棠涮。 UITableView 可以在運(yùn)行時(shí)詢問其數(shù)據(jù)源是否實(shí)現(xiàn)了 tableView(_:moveRowAt:to :)。 如果是刺覆,則表視圖會在表視圖進(jìn)入編輯模式時(shí)添加重新排序控件严肪。

顯示用戶警報(bào)

在本節(jié)中,您將了解用戶警報(bào)以及配置和顯示用戶警報(bào)的不同方法谦屑。 用戶警報(bào)可以為您的應(yīng)用程序提供更好的用戶體驗(yàn)驳糯,因此您會經(jīng)常使用它們。

警報(bào)通常用于警告用戶一個(gè)重要的動作即將發(fā)生氢橙,同時(shí)給他們機(jī)會取消該動作酝枢。 當(dāng)您要顯示警報(bào)時(shí),您將創(chuàng)建一個(gè)具有首選樣式的 UIAlertController 實(shí)例悍手。 兩種可用的樣式是 UIAlertControllerStyle.actionSheetUIAlertControllerStyle.alert (圖11.9)帘睦。

圖11.9 UIAlertController樣式

.actionSheet 樣式用于向用戶呈現(xiàn)要從中選擇的動作列表。 .alert 類型用于顯示關(guān)鍵信息坦康,要求用戶決定如何繼續(xù)竣付。 這個(gè)區(qū)別可能看起來很微妙,但是如果用戶決定取消選擇涝焙,或者動作不重要的話卑笨,那么一個(gè) .actionSheet 可能是最好的選擇。

您將使用 UIAlertController 來確認(rèn) item 的刪除仑撞。 您將使用 .actionSheet 樣式赤兴,因?yàn)榫瘓?bào)的目的是確認(rèn)或取消可能的破壞性操作。

打開 ItemsViewController.swift 并修改 tableView(_:commit:forRowAt :)隧哮,要求用戶確認(rèn)或取消 刪除 item桶良。

override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {

??// If the table view is asking to commit a delete command...
??if editingStyle == .delete {
????let item = itemStore.allItems[indexPath.row]

????let title = "Delete \(item.name)?"
????let message = "Are you sure you want to delete this item?"

????let ac = UIAlertController(title: title, message: message, preferredStyle: .actionSheet)

????// Remove the item from the store
????itemStore.removeItem(item)

????// Also remove that row from the table view with an animation
????tableView.deleteRows(at: [indexPath], with: .automatic)
??}
}

在確定用戶想要?jiǎng)h除項(xiàng)目之后,您將創(chuàng)建一個(gè)具有適當(dāng)標(biāo)題和消息的 UIAlertController 實(shí)例沮翔,描述將要執(zhí)行的操作陨帆。 此外,您為該警報(bào)指定 .actionSheet 樣式采蚀。

顯示警報(bào)時(shí)用戶可以選擇的動作是 UIAlertAction 的實(shí)例疲牵,您可以添加多個(gè)操作,而不管警報(bào)的樣式榆鼠。 使用 addAction(_ :) 方法將動作添加到 UIAlertController 中纲爸。

tableView(_:commit:forRowAt :) 中的動作工作表中添加必要的操作。

...
let ac = UIAlertController(title: title, message: message, preferredStyle: .actionSheet)

let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
??ac.addAction(cancelAction)

let deleteAction = UIAlertAction(title: "Delete", style: .destructive, handler: { (action) -> Void in
??// Remove the item from the store
??self.itemStore.removeItem(item)

??// Also remove that row from the table view with an animation
??self.tableView.deleteRows(at: [indexPath], with: .automatic)
})
ac.addAction(deleteAction)
...

第一個(gè)動作的標(biāo)題為 “Cancel”妆够,并使用 .cancel 樣式創(chuàng)建识啦。.cancel 樣式會顯示為標(biāo)準(zhǔn)藍(lán)色字體。 此操作將允許用戶退出刪除項(xiàng)目神妹。 處理程序參數(shù)允許在發(fā)生該動作時(shí)執(zhí)行閉包颓哮。 因?yàn)椴恍枰渌麆幼鳎詫?nil 作為參數(shù)傳遞鸵荠。

第二個(gè)動作的標(biāo)題為 “Delete”冕茅,并使用 .dructructive 樣式創(chuàng)建。 因?yàn)槠茐男缘男袨閼?yīng)該被明確標(biāo)注和注意到蛹找,.dructructive 風(fēng)格會產(chǎn)生明亮的紅色文字嵌赠。 如果用戶選擇此動作,則需要?jiǎng)h除 item 和表視圖 cell熄赡。 這一切都在傳遞給動作的構(gòu)造器的 'handle' 閉包中完成姜挺。

現(xiàn)在已經(jīng)添加了動作,可以向用戶顯示警報(bào)控制器彼硫。 因?yàn)?UIAlertControllerUIViewController 的子類炊豪,所以您可以使用 模態(tài)(modally) 將其呈現(xiàn)給用戶。 模態(tài)視圖控制器(modal view controller) 接管整個(gè)屏幕拧篮,直到其完成工作词渤。

要以視圖方式呈現(xiàn)視圖控制器,您可以在其視圖位于屏幕上的視圖控制器上調(diào)用 present(_:animated:completion :)串绩。 要呈現(xiàn)的視圖控制器被傳遞給它缺虐,并且該視圖控制器的視圖接管屏幕。

...
let deleteAction = UIAlertAction(title: "Delete", style: .destructive, handler: { (action) -> Void in
??// Remove the item from the store
??self.itemStore.removeItem(item)

??// Also remove that row from the table view with an animation
??self.tableView.deleteRows(at: [indexPath], with: .automatic)
})
ac.addAction(deleteAction)

// Present the alert controller
present(ac, animated: true, completion: nil)
...

構(gòu)建并運(yùn)行應(yīng)用程序并刪除一個(gè) item礁凡。 將提供一個(gè)動作以供您確認(rèn)刪除(圖11.10)高氮。

圖11.10 刪除 item

設(shè)計(jì)模式

設(shè)計(jì)模式(design pattern) 解決了常見的軟件工程問題慧妄。 設(shè)計(jì)模式不是代碼的實(shí)際代碼段,而是可以在應(yīng)用程序中使用的抽象概念或方法剪芍。 良好的設(shè)計(jì)模式是任何開發(fā)人員有價(jià)值和強(qiáng)大的工具塞淹。

在開發(fā)過程中始終如一地使用設(shè)計(jì)模式可以減少解決問題的精神開銷,從而可以更輕松罪裹,快速地創(chuàng)建復(fù)雜的應(yīng)用程序饱普。 以下是您已經(jīng)使用的一些設(shè)計(jì)模式:

  • 委托模式(Delegation):一個(gè)對象將某些功能委托給另一個(gè)對象。 當(dāng)文本字段的內(nèi)容更改時(shí)状共,您通過 UITextField 使用委托來通知套耕。
  • 數(shù)據(jù)源模式(Data source):數(shù)據(jù)源與委托類似,但不是對另一個(gè)對象做出反應(yīng)峡继,而是在請求時(shí)冯袍,數(shù)據(jù)源負(fù)責(zé)向另一個(gè)對象提供數(shù)據(jù)。 您之前已將數(shù)據(jù)源模式與表視圖一起使用過:每個(gè)表視圖都有一個(gè)數(shù)據(jù)源,它至少負(fù)責(zé)告訴表視圖要顯示多少行以及每個(gè)索引路徑應(yīng)顯示哪個(gè)單元格。
  • Model-View-Controller:應(yīng)用程序中的每個(gè)對象都可以滿足三個(gè)角色之一七婴。 模型對象是數(shù)據(jù)冈爹。 視圖顯示UI。 控制器提供將模型和視圖結(jié)合在一起的膠水。
  • 目標(biāo) - 動作對(Target-action pairs):當(dāng)特定事件發(fā)生時(shí),一個(gè)對象調(diào)用另一個(gè)對象的方法。 目標(biāo)是有一個(gè)方法被調(diào)用的對象资盅,動作是被調(diào)用的方法。 例如踊赠,您使用具有按鈕的目標(biāo)動作對:當(dāng)觸發(fā)事件發(fā)生時(shí)呵扛,將會在另一個(gè)對象(通常是視圖控制器)上調(diào)用一個(gè)方法。

蘋果在使用這些設(shè)計(jì)模式時(shí)非常一致筐带,因此了解和識別它們非常重要今穿。 繼續(xù)閱讀這本書,留意這些模式伦籍! 認(rèn)識它們將幫助您更輕松地學(xué)習(xí)新的課程和框架蓝晒。

青銅挑戰(zhàn):重命名刪除按鈕

刪除行時(shí),會出現(xiàn)一個(gè)確認(rèn)按鈕帖鸦,標(biāo)有 Delete芝薇。 嘗試將此按鈕的標(biāo)簽更改為 Remove

白銀挑戰(zhàn):防止重新排序

表格視圖總是顯示一個(gè)最后一行作儿,表示 “No more items!”(這部分挑戰(zhàn)與上一章的挑戰(zhàn)是一樣的洛二,如果你已經(jīng)完成了,你可以復(fù)制你之前的代碼 )現(xiàn)在,令最后一行不能移動晾嘶。

黃金挑戰(zhàn):真正防止重新排序

完成銀牌挑戰(zhàn)后妓雾,您可能會注意到,即使您不能移動 No more items! 行本身变擒,您仍然可以拖動其下的其他行君珠。 做到這一點(diǎn)——無論什么——No more items! 行永遠(yuǎn)不會被淘汰出最后的位置寝志。 最后娇斑,使它不可被刪除。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末材部,一起剝皮案震驚了整個(gè)濱河市毫缆,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌乐导,老刑警劉巖苦丁,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異物臂,居然都是意外死亡旺拉,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門棵磷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蛾狗,“玉大人,你說我怎么就攤上這事仪媒〕磷溃” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵算吩,是天一觀的道長留凭。 經(jīng)常有香客問我,道長偎巢,這世上最難降的妖魔是什么蔼夜? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮压昼,結(jié)果婚禮上求冷,老公的妹妹穿的比我還像新娘。我一直安慰自己巢音,他們只是感情好遵倦,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著官撼,像睡著了一般梧躺。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天掠哥,我揣著相機(jī)與錄音巩踏,去河邊找鬼。 笑死续搀,一個(gè)胖子當(dāng)著我的面吹牛塞琼,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播禁舷,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼彪杉,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了牵咙?” 一聲冷哼從身側(cè)響起派近,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎洁桌,沒想到半個(gè)月后渴丸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡另凌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年谱轨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吠谢。...
    茶點(diǎn)故事閱讀 40,040評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡土童,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出囊卜,到底是詐尸還是另有隱情娜扇,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布栅组,位于F島的核電站雀瓢,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏玉掸。R本人自食惡果不足惜刃麸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望司浪。 院中可真熱鬧泊业,春花似錦、人聲如沸啊易。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽租谈。三九已至篮奄,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背窟却。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工昼丑, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人夸赫。 一個(gè)月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓菩帝,卻偏偏與公主長得像,于是被迫代替她去往敵國和親茬腿。 傳聞我的和親對象是個(gè)殘疾皇子呼奢,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評論 2 355

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