【總結(jié)回顧】iOS Apprentice Tutorial 2:Checklists(五)

這是***【總結(jié)回顧】iOS Apprentice Tutorial 2:Checklists ***系列的第五篇文章岸梨,前幾篇文章請(qǐng)見(一) 抒蚜、(二)涮总、(三)寻歧、(四)掌栅。

本篇文章總結(jié)本書的第七、八章( Saving and loading the checklist items码泛、Multiple checklists)中的重點(diǎn)內(nèi)容猾封,從126頁(yè)到172頁(yè)。第七章以數(shù)據(jù)持久化的內(nèi)容為主噪珊,第八章主要是增加了一個(gè)嵌套清單晌缘,之前已經(jīng)學(xué)過(guò)如何創(chuàng)建 table view controller,作者盡可能地用另外一種方法實(shí)現(xiàn)同樣的效果痢站。

50. 數(shù)據(jù)持久化三件事

1) 找到可以存放文件的路徑磷箕,創(chuàng)建文件。

找到路徑首頁(yè)要了解一下iOS的沙盒機(jī)制阵难,每個(gè)App都有自己的文件目錄岳枷,不能進(jìn)入其他App的文件目錄里。沙盒機(jī)制能夠保護(hù)手機(jī)不受手機(jī)病毒的干擾呜叫。

所以空繁,App可以存儲(chǔ)數(shù)據(jù)的文件目錄名字為“Document”,Document里的內(nèi)容會(huì)和iTunes或iCloud同步朱庆。當(dāng)發(fā)布新的版本后盛泡,Document里的內(nèi)容仍然在。App目錄里除了Document之外還有其他的文件夾娱颊?有傲诵,Library和tmp兩個(gè)文件夾凯砍。Library里都是是cache文件,和偏好設(shè)置文件掰吕。Library是由系統(tǒng)控制管理的果覆。tmp文件夾里都是臨時(shí)文件反症,tmp里的文件都會(huì)時(shí)不時(shí)地被系統(tǒng)清理刪除垒迂。

所以,我們就把數(shù)據(jù)存儲(chǔ)到Document里凰慈。

那么菱属,接下來(lái)需要的做2件事情:找路徑钳榨、創(chuàng)建存儲(chǔ)文件

    //找路徑
    func documentsDirectory() -> String {
        let paths = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
        return paths[0]
    }

    //在找到的路徑里創(chuàng)建文件
    func dataFilePath() -> String {
        return(documentsDirectory() as NSString).stringByAppendingPathComponent("某某.plist")
    }

注意:.DocumentDirectoryDocumentationDirectory的區(qū)別。

我們創(chuàng)建的文件的擴(kuò)展名為.plist纽门,plist表示Property List 薛耻,是XML文件格式,能夠存儲(chǔ)結(jié)構(gòu)化數(shù)據(jù)赏陵。

2)把 數(shù)據(jù) 存放到文件中饼齿,每當(dāng)用戶改變了數(shù)據(jù)時(shí),改變后的數(shù)據(jù)也能同步存放到數(shù)據(jù)中蝙搔。

我們保存數(shù)據(jù)需要用到 NSCoder缕溉,可以將數(shù)據(jù)儲(chǔ)到結(jié)構(gòu)化格式文件里。將對(duì)象轉(zhuǎn)換成文件吃型,再將文件轉(zhuǎn)換回來(lái)的過(guò)程证鸥,就是 Serialization(序列化)。

  func saveChecklists() {
    let data = NSMutableData()
    let archiver = NSKeyedArchiver(forWritingWithMutableData: data)
    archiver.encodeObject(lists, forKey: "Checklists")
    archiver.finishEncoding()
    data.writeToFile(dataFilePath(), atomically: true)
  }

方法saveChecklists()用了兩步將 items 數(shù)組轉(zhuǎn)換成了二進(jìn)制數(shù)據(jù):
a. NSKeyedArchiver能將數(shù)組和 ChecklistItem 轉(zhuǎn)換成二進(jìn)制文件然后寫入對(duì)應(yīng)的文件里勤晚。

b. data放置在NSMutableData對(duì)象里枉层,然后將自己寫入文件所在的路徑中

最后一點(diǎn),NSKeyedArchiver知道如何encode一個(gè)數(shù)組對(duì)象赐写,但是并不了解 ChecklistItem鸟蜡,所以,需要讓 ChecklistItem 遵守 NSCoding 協(xié)議才可以挺邀。也就是說(shuō)揉忘,凡是NSKeyedArchiver要encode的對(duì)象,都要遵守 NSCoding 協(xié)議悠夯。或者說(shuō)躺坟,你想讓某個(gè)對(duì)象使用 NSCoder 系統(tǒng)沦补,就要讓這個(gè)對(duì)象遵守 NSCoding 協(xié)議。有關(guān) NSCoding 的知識(shí)點(diǎn)請(qǐng)見 #53咪橙。

3)應(yīng)用啟動(dòng)時(shí)能夠加載數(shù)據(jù)(取數(shù)據(jù))夕膀。

  func loadChecklists() {
    let path = dataFilePath()
    if NSFileManager.defaultManager().fileExistsAtPath(path) {
      if let data = NSData(contentsOfFile: path) {
        let unarchiver = NSKeyedUnarchiver(forReadingWithData: data)
        lists = unarchiver.decodeObjectForKey("Checklists") as! [Checklist]
        unarchiver.finishDecoding()
      }
    }
  }

51. NSCoding 協(xié)議

協(xié)議里有兩個(gè)方法是必須要實(shí)現(xiàn)的:

  • func encodeWithCoder(aCoder: NSCoder) 用來(lái)saving 或者 encoding 對(duì)象虚倒。(存)
  • init?(coder aDecoder: NSCoder)初始化方法,用于創(chuàng)建新的對(duì)象产舞,通過(guò)從 plist 文件里 loading 或者 decoding 對(duì)象來(lái)創(chuàng)建對(duì)象魂奥。(取)
  func encodeWithCoder(aCoder: NSCoder) {
    aCoder.encodeObject(name, forKey: "Name")
    aCoder.encodeObject(items, forKey: "Items")
  }

當(dāng)NSKeyedArchiver嘗試encodeChecklistItem對(duì)象時(shí)易猫,NSKeyedArchiver會(huì)給ChecklistItem發(fā)送encodeWithCoder(coder)消息耻煤。

  required init?(coder aDecoder: NSCoder) {
    name = aDecoder.decodeObjectForKey("Name") as! String
    items = aDecoder.decodeObjectForKey("Items") as! [ChecklistItem]
    super.init()
  }

52. 調(diào)試bug小技巧

有時(shí)候出現(xiàn)bug時(shí),Xcode會(huì)轉(zhuǎn)換到 debugger 情景下准颓,顯示哪一行代碼導(dǎo)致了程序崩潰哈蝇。不過(guò)有時(shí)候會(huì)顯示是 AppDelegate 的問(wèn)題,如下圖:

這對(duì)改bug來(lái)說(shuō)可沒(méi)有什么幫助攘已。那怎么辦呢炮赦?見下圖:

Breakpoint navigator -> 點(diǎn)擊 +

然后再次 Run,Xcode就會(huì)顯示真正導(dǎo)致crash的代碼行了样勃。

53.題外話

  • 作者推薦了一個(gè)Mac軟件:TextWrangler吠勘。
  • 在Xcode里如果遇到看不懂的方法,按住Alt/Option鍵峡眶,點(diǎn)擊這個(gè)代碼即可出現(xiàn)幫助信息剧防。
  • 幫你區(qū)分兩個(gè)文件中代碼異同的小工具:Xcode -> Open Developer Tool -> FileMerge

54. Initializers 構(gòu)造器

在創(chuàng)建新的對(duì)象時(shí),才需要 init 方法幌陕。比如:當(dāng)用戶點(diǎn)擊+時(shí)诵姜,用init()來(lái)創(chuàng)建 ChecklistItem,用init?(coder) 將 ChecklistItems存儲(chǔ)到硬盤上搏熄。

init() 的標(biāo)準(zhǔn)步驟:

init() {
    //給常量或變量實(shí)例賦值
    super.init()
    //其他初始化代碼棚唆,比如調(diào)用方法,寫在這里就好心例。必須在super.init()之后宵凌,不然報(bào)錯(cuò)
}

init 方法不用 func 關(guān)鍵詞開頭。

override initrequired init?止后, 一個(gè)對(duì)象A是對(duì)象B的子類瞎惫,如果要在對(duì)象A里添加init方法,前面需要有 override或者required译株,比如:

  init(name: String) {
    self.name = name
    super.init()
  }

  override init() {
    super.init()
  }

當(dāng)init有問(wèn)號(hào)時(shí)瓜喇,表示當(dāng) init 失敗時(shí),會(huì)返回nil歉糜。如果plist文件里沒(méi)有足夠的信息乘寒,decoding一個(gè)對(duì)象就會(huì)失敗。

當(dāng)你聲明一個(gè)變量或者常量時(shí)匪补,需要給常量或變量一個(gè)初始值伞辛。

如果聲明了變量烂翰,卻沒(méi)有給出初始值,只給出了類型蚤氏,比如:

var checked: Bool

這樣的話甘耿,必須要在init方法里給變量賦值。不然竿滨,Swift會(huì)報(bào)錯(cuò)(Optional 類型的變量除外)佳恬。

在給所有的變量常量實(shí)例都賦值后,就可以調(diào)用 super.init() 方法來(lái)初始化這個(gè)對(duì)象的superclass(父類)姐呐。之后殿怜,就可以寫其他初始化代碼,比如調(diào)用某些方法曙砂,必須在super.init()之后头谜,不然報(bào)錯(cuò)。

雖然 Swift 的初始化規(guī)則看起來(lái)比較復(fù)雜鸠澈,還好柱告,要你你忘了提供init方法,編譯器會(huì)提示你的笑陈。

最后以 table view controller 舉例际度, table view controller 和很多其他的對(duì)象一樣,會(huì)有多個(gè) init 方法:

  • init?(coder):view controller 自動(dòng)從 storyboard 中載入
  • init(nibName, bundle):你想手動(dòng)從一個(gè)nib文件中載入 view controller
  • init(style):你想不使用 storyboard 或 nib 來(lái)創(chuàng)建 table view controller涵妥。
required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

注意到 init?(coder)的參數(shù)有些奇怪了嗎乖菱,外部標(biāo)簽和內(nèi)部標(biāo)簽和其他的方法不太一樣。coder標(biāo)簽是方法名字的一部分蓬网,方法參數(shù)是aDecoder窒所。
當(dāng)年調(diào)用super.init方法,用coder標(biāo)簽表示super的初始化方法的參數(shù)帆锋,從aDecoder來(lái)的對(duì)象作為參數(shù)的值吵取。這句話可能不太好理解,可能是翻譯錯(cuò)了锯厢,附上原文:

When you call super.init, you use the label coder to refer to the parameter of super's init method, and the object from aDecoder as that parameter's value.

總結(jié)一下 init 方法三步驟:
1)確保實(shí)例變量有值
2)調(diào)用 superclass 的 init()皮官,
3)調(diào)用其他的方法

55. 創(chuàng)建 table view cell 的四種方法

方法一:使用 prototype cells

在storyboard中找到cell,輸入identifier:ChecklistItem实辑,然后寫代碼:

let cell = tableView.dequeueReusableCellWithIdentifier("ChecklistItem", forIndexPath: indexPath)

注意dequeueReusableCellWithIdentifier方法里有參數(shù)forIndexPath捺氢,只能用在 prototype cells 中。

方法二:使用靜態(tài)cell(static cells)

已經(jīng)確定有哪些cell剪撬,而且內(nèi)容不會(huì)變動(dòng)摄乒。

方法三:使用nib文件

nib,也就是XIB,有點(diǎn)像是迷你型的storyboard缺狠,里面包含定制的 UITableViewCell 對(duì)象。

方法四:手動(dòng)創(chuàng)建


    let cellIdentifier = "Cell"
    if let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) {
      return cell
    } else {
      return UITableViewCell(style: .Default, reuseIdentifier: cellIdentifier)
    }

注意dequeueReusableCellWithIdentifier方法里沒(méi)有參數(shù)萍摊。

這樣可能不太深刻挤茄,實(shí)際使用的時(shí)候是什么樣子呢?如下:

func cellForTableView(tableView: UITableView) -> UITableViewCell {
    let cellIdentifier = "Cell"

    if let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) {
        return cell
    } else {
        return UITableViewCell(style: .Default, reuseIdentifier: cellIdentifier)
    }
}
 
  override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = cellForTableView(tableView)

    let checklist = lists[indexPath.row]
    cell.textLabel!.text = checklist.name
    cell.accessoryType = .DetailDisclosureButton
    
    return cell
  }

總之冰木,對(duì)于 UITabieViewCell穷劈,我有一個(gè)忠告:
盡可能的復(fù)用cell(reuse cells)
盡可能的復(fù)用cell(reuse cells)
盡可能的復(fù)用cell(reuse cells)
重要的事情說(shuō)三遍。

56. 新方法之點(diǎn)擊跳轉(zhuǎn)界面的同時(shí)傳值(一)

首先踊沸,storyboard中歇终,黃點(diǎn)拖動(dòng)(見下圖),輸入Identifier:ShowChecklist逼龟。

然后寫代碼:

  override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

    performSegueWithIdentifier("ShowChecklist", sender: nil)
  }

上面代碼中有 sender评凝,借用sender可以傳值(這個(gè)功能是重點(diǎn),省時(shí)省力好幫手)腺律,如下:

  override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    let checklist = lists[indexPath.row]
    performSegueWithIdentifier("ShowChecklist", sender: checklist)
  }

理解這兩行代碼非常關(guān)鍵奕短。

當(dāng)然,還不能忘了 prepare?ForSegue(sender) 方法匀钧。

override func prepareForSegue(sender: UIStoryboardSegue, sender: AnyObject?) {
   if segue.identifier == "ShowChecklist" {
       let controller = segue.destinationViewController as! ChecklistViewController {
           controller.checklist = sender as! Checklist //看翎碑,用上 sender 了!
       }
   }
}

當(dāng)然了之斯,ChecklistViewController里一定要聲明(聲明里為什么要有嘆號(hào)日杈,在后面會(huì)提及):

var checklist: Checklist!

好了,上面就是所有的步驟了佑刷。

接下來(lái)說(shuō)一下上述步驟中涉及的一些知識(shí)點(diǎn)莉擒,先看圖,看看實(shí)際上 perform 一個(gè) sugue 涉及多少步驟项乒,然后講解知識(shí)點(diǎn):


  • 調(diào)用順序啰劲。viewDidLoad()prepareForSegue()之后調(diào)用,也就是說(shuō)檀何,先調(diào)用prepareForSegue()蝇裤,然后再調(diào)用viewDidLoad()
  • checklist為什么要有嘆號(hào)频鉴。加一個(gè)嘆號(hào)可以允許 checklist 暫時(shí)為 nil 直到 viewDidLoad() 被調(diào)用栓辜。

在#59里,會(huì)介紹另外一種也就是第三種跳轉(zhuǎn)頁(yè)面并且傳值的方法垛孔。

57. 創(chuàng)建自己的構(gòu)造器(init 方法)

var list = Checklist()
list.name = "Name of the checklist"

想把上面的兩行變成下面這一行藕甩,該怎么做呢?

list = Checklist(name: "Name of the checklist")

需要寫一個(gè)自己的 init 方法周荐,讓 name 作為一個(gè)參數(shù):

init(name: String) {
    self.name = name
    super.init()
}

這個(gè)構(gòu)造器的作用就是把參數(shù) name 賦值給實(shí)例變量(self.name)狭莱。
self.name 指的是當(dāng)前 Checklist 對(duì)象的變量 name僵娃。

創(chuàng)建這個(gè)構(gòu)造器的好久就是,可以保證每次我創(chuàng)建新的 Checklist 對(duì)象時(shí)腋妙,都一定會(huì)有 name 屬性默怨。

58. Type Cast(類型檢查)

類型檢查的目的是讓 Swift 把某個(gè)值擁有不同的數(shù)據(jù)類型。

59. 新方法之點(diǎn)擊跳轉(zhuǎn)界面的同時(shí)傳值(二)

點(diǎn)擊 cell 里的 Accessory骤素,除了用 storyboard 之外匙睹,還可以用:

  override func tableView(tableView: UITableView, accessoryButtonTappedForRowWithIndexPath indexPath: NSIndexPath) {

  }

點(diǎn)擊 cell 的 Accessory 跳轉(zhuǎn)界面并且傳值的方法如下:
先到 storyboard 中找到你要跳轉(zhuǎn)的目的地界面,然后如下圖济竹;


在 Storyboard ID 中輸入對(duì)應(yīng)的 Identity痕檬,然后寫代碼:

  override func tableView(tableView: UITableView, accessoryButtonTappedForRowWithIndexPath indexPath: NSIndexPath) {
    let navigationController = storyboard!.instantiateViewControllerWithIdentifier("ListDetailNavigationController") as! UINavigationController
    
    let controller = navigationController.topViewController as! ListDetailViewController
    controller.delegate = self
    
    let checklist = dataModel.lists[indexPath.row]
    controller.checklistToEdit = checklist
    
    presentViewController(navigationController, animated: true, completion: nil)
  }

其中關(guān)鍵代碼兩行:

let navigationController = storyboard!.instantiateViewControllerWithIdentifier("ListDetailNavigationController") as! UINavigationController

 presentViewController(navigationController, animated: true, completion: nil)

這個(gè)方法非常好用~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市送浊,隨后出現(xiàn)的幾起案子梦谜,更是在濱河造成了極大的恐慌,老刑警劉巖袭景,帶你破解...
    沈念sama閱讀 219,110評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件改淑,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡浴讯,警方通過(guò)查閱死者的電腦和手機(jī)朵夏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)榆纽,“玉大人仰猖,你說(shuō)我怎么就攤上這事∧巫眩” “怎么了饥侵?”我有些...
    開封第一講書人閱讀 165,474評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)衣屏。 經(jīng)常有香客問(wèn)我躏升,道長(zhǎng),這世上最難降的妖魔是什么狼忱? 我笑而不...
    開封第一講書人閱讀 58,881評(píng)論 1 295
  • 正文 為了忘掉前任膨疏,我火速辦了婚禮,結(jié)果婚禮上钻弄,老公的妹妹穿的比我還像新娘佃却。我一直安慰自己,他們只是感情好窘俺,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,902評(píng)論 6 392
  • 文/花漫 我一把揭開白布饲帅。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪灶泵。 梳的紋絲不亂的頭發(fā)上育八,一...
    開封第一講書人閱讀 51,698評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音赦邻,去河邊找鬼单鹿。 笑死,一個(gè)胖子當(dāng)著我的面吹牛深纲,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播劲妙,決...
    沈念sama閱讀 40,418評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼湃鹊,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了镣奋?” 一聲冷哼從身側(cè)響起币呵,我...
    開封第一講書人閱讀 39,332評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎侨颈,沒(méi)想到半個(gè)月后余赢,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,796評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡哈垢,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,968評(píng)論 3 337
  • 正文 我和宋清朗相戀三年妻柒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片耘分。...
    茶點(diǎn)故事閱讀 40,110評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡举塔,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出求泰,到底是詐尸還是另有隱情央渣,我是刑警寧澤,帶...
    沈念sama閱讀 35,792評(píng)論 5 346
  • 正文 年R本政府宣布渴频,位于F島的核電站芽丹,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏卜朗。R本人自食惡果不足惜拔第,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,455評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望场钉。 院中可真熱鬧楼肪,春花似錦、人聲如沸惹悄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至暂殖,卻和暖如春价匠,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背呛每。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工踩窖, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人晨横。 一個(gè)月前我還...
    沈念sama閱讀 48,348評(píng)論 3 373
  • 正文 我出身青樓洋腮,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親手形。 傳聞我的和親對(duì)象是個(gè)殘疾皇子啥供,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,047評(píng)論 2 355

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

  • *面試心聲:其實(shí)這些題本人都沒(méi)怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個(gè)offer,總結(jié)起來(lái)就是把...
    Dove_iOS閱讀 27,150評(píng)論 30 470
  • 代碼創(chuàng)建UIWindow對(duì)象 Xcode7之后使用代碼創(chuàng)建UIWindow對(duì)象: //創(chuàng)建UIWindow對(duì)象 s...
    云之君兮鵬閱讀 1,317評(píng)論 0 2
  • 這本書看了幾遍也記不清了,總之好多遍库糠,第一遍照著書中的代碼敲了一遍伙狐,結(jié)果還出現(xiàn)了好多bug,刪掉重新敲瞬欧,沒(méi)有問(wèn)題之...
    sing_crystal閱讀 907評(píng)論 4 5
  • 都因?yàn)槟?我相信世間有一種熱情像太陽(yáng)一樣贷屎! 都是因?yàn)槟?我相信世間有一種溫柔像月亮一樣! 愛的世界有你艘虎! 就沒(méi)有地...
    劉文娟閱讀 411評(píng)論 0 1
  • 最近幾年唉侄,發(fā)現(xiàn)自己的淚點(diǎn)低了很多…不知道是年紀(jì)大了,對(duì)生活野建、生命的感慨多了還是怎么了…很容易被感動(dòng)美旧,也很容易因?yàn)橐?..
    筱淼渺閱讀 150評(píng)論 0 0