抽絲剝繭實(shí)現(xiàn)蘋果手機(jī)中的秒表功能

這篇文章主要和大家一起探討下如何實(shí)現(xiàn)蘋果手機(jī)上自帶的秒表功能。在實(shí)現(xiàn)之前筐喳,對(duì)這個(gè)話題感興趣的也可以先跑一跑自己手機(jī)上的秒表蓄氧,分析一下功能,看看自己能不能自主實(shí)現(xiàn)堂氯。如果可以,也希望能在實(shí)現(xiàn)完之后再看我這篇文章晶框,你的實(shí)現(xiàn)方式和我的實(shí)現(xiàn)方式有哪些地方不同?誰的更節(jié)約性能一些呢?以及在細(xì)節(jié)上的處理,有沒有更好的方式漱抓?歡迎與我探討檐迟。

如果覺得實(shí)現(xiàn)有一些難度追迟,那么主要卡在了哪些不知道該怎么處理的實(shí)現(xiàn)上束铭,可以帶著疑惑看這篇文章,希望能給你一些思考和幫助。

當(dāng)然也可以一邊參考我的代碼實(shí)現(xiàn)一邊往下看会通,這個(gè)項(xiàng)目我有傳到github上煤辨,有swift和oc兩個(gè)版本。如果我有講述不清楚的地方且轨,可以參考代碼實(shí)現(xiàn)泳挥,傳送門:stopWatch 希望能幫到你。本篇講述中的代碼使用swift語言嫌变,那么新建一個(gè)項(xiàng)目东涡,和我一起開始吧。

功能分析

以下是操作秒表的視頻,可以先看下胧辽,然后再具體分析我們要實(shí)現(xiàn)的功能。

image

首先進(jìn)行頁面布局的分析凡蚜,從視頻來看人断,比較好確定該使用的控件。頂部使用一個(gè)大的label來實(shí)時(shí)刷新時(shí)間朝蜘。中間是兩個(gè)button恶迈。底部可以使用一個(gè)tabelview來記錄計(jì)次的時(shí)間。如圖所示谱醇,我是使用stroybord來搭建的界面暇仲。

image

拖拽控件,及按鈕的點(diǎn)擊事件到controller中:

    @IBOutlet weak var tableView: UITableView!
    @IBOutlet weak var timeLable: UILabel!
    @IBOutlet weak var resetButton: WSButton!
    @IBOutlet weak var startButton: WSButton!
    
    // 復(fù)位/計(jì)次
    @IBAction func reset(_ sender: WSButton) {

    }
    
    // 開始/停止
     @IBAction func start(_ sender: WSButton) {
      
     }

然后具體分析一下操作的邏輯副渴。當(dāng)點(diǎn)擊右邊的啟動(dòng)按鈕后奈附,頂部的label開始跑動(dòng) 注意按鈕底部也會(huì)同步開始跑動(dòng),但這兩個(gè)時(shí)間是不同的煮剧,頂部的lable是總時(shí)間斥滤,按鈕下面刷新的是此次計(jì)次的時(shí)間。當(dāng)開始啟動(dòng)之后勉盅,點(diǎn)擊右邊的按鈕開始計(jì)次佑颇,會(huì)重新生成一個(gè)計(jì)次,又從零開始跑菇篡。那么之前的計(jì)次就結(jié)束了漩符,并且在tableview中刷新顯示出來。此時(shí)啟動(dòng)按鈕轉(zhuǎn)化成暫停按鈕驱还,點(diǎn)擊這個(gè)按鈕嗜暴,停止計(jì)時(shí)凸克。停止計(jì)時(shí)后,左邊的計(jì)次按鈕由計(jì)次轉(zhuǎn)化為復(fù)位闷沥,點(diǎn)擊復(fù)位萎战,所有記錄的時(shí)間都清零,回歸到原始的狀態(tài)舆逃。具體狀態(tài)如下所示:

初始狀態(tài)蚂维,此時(shí)點(diǎn)擊計(jì)次按鈕無效。因?yàn)槲撮_始啟動(dòng)路狮,無法計(jì)次虫啥。


image

正在運(yùn)行的狀態(tài),點(diǎn)擊計(jì)次可以開始計(jì)次奄妨。


image

暫停狀態(tài)涂籽,點(diǎn)擊啟動(dòng)可以恢復(fù)運(yùn)行。


image

所記錄的時(shí)間當(dāng)中砸抛,最長(zhǎng)的時(shí)間用紅色標(biāo)識(shí)评雌,最短的時(shí)間用綠色標(biāo)識(shí)。


image

總結(jié)一下整體的狀態(tài)變化:

  • 初始狀態(tài)下直焙,也就是未啟動(dòng)之前景东,是無法計(jì)次的,此時(shí)點(diǎn)擊計(jì)次按鈕無效奔誓。
  • 當(dāng)點(diǎn)擊啟動(dòng)后斤吐,左邊按鈕此時(shí)可以開始計(jì)次,啟動(dòng)按鈕也會(huì)變成停止按鈕厨喂。
  • 當(dāng)點(diǎn)擊停止按鈕后曲初,計(jì)次按鈕變成復(fù)位按鈕,停止按鈕變成啟動(dòng)按鈕杯聚。
  • 點(diǎn)擊復(fù)位按鈕,一切回歸初始狀態(tài)抒痒。
  • 在列表所計(jì)次的所有時(shí)間中幌绍,最長(zhǎng)的時(shí)間用紅色標(biāo)識(shí),最短的時(shí)間用綠色標(biāo)識(shí)故响。

模型分析

項(xiàng)目中我是使用的mvc模式傀广,所以分析下model。新建一個(gè)模型類彩届,命名為stopwatchData,讓我們看看這個(gè)類該怎么寫伪冰。

首先需要使用一個(gè)數(shù)組來存儲(chǔ)所有計(jì)次的時(shí)間,我的思路上樟蠕,這里也包括正在計(jì)次的時(shí)間贮聂。以及用一個(gè)bool值來記錄當(dāng)前是否是復(fù)位狀態(tài)靠柑。注意這里是privite(set),只允許內(nèi)部設(shè)置,外部是無法設(shè)置的吓懈。

    private(set) public var times:[Int] = []
    private(set)  var  isReset:Bool = true

基于要突出最大時(shí)間與最小時(shí)間歼冰,改變文字顏色使其顯眼。所以這里我也要計(jì)算出最大時(shí)間與最小時(shí)間耻警,存入模型隔嫡。但時(shí)間是顯示在tableview上的,所有我這里只需記錄下最大與最小時(shí)間所在數(shù)組(times)中的索引甘穿,我在tableview中即可根據(jù)索引來做出相應(yīng)的改變腮恩。同樣這個(gè)兩個(gè)屬性是read-only的,外界只需訪問就行温兼。

這里有一點(diǎn)需要重點(diǎn)說一下秸滴,因?yàn)閿?shù)組(times)里面包括正在運(yùn)行的時(shí)間,這個(gè)時(shí)間還沒結(jié)束確定下來妨托,所以是不參與計(jì)算的缸榛。所以數(shù)組的個(gè)數(shù)必須要2個(gè)以上才開始計(jì)算最大或最小計(jì)次時(shí)間。

    public var maxTimeIndex:Int? {
        get {
            if times.count <= 2 {
                return nil;
            }
            
            var maxIndex = 1
            
            for index in 2..<times.count {
                if(times[index] > times[maxIndex]){
                    maxIndex = index
                }
            }
            return maxIndex
        }
    }
    
    public var minTimeIndex:Int? {
        get {
            if times.count <= 2 {
                return nil;
            }
            
            var minIndex = 1
            
            for index in 2..<times.count {
                if(times[index] < times[minIndex]){
                    minIndex = index
                }
            }
            return minIndex
        }
    }

另外兰伤,當(dāng)我們點(diǎn)擊復(fù)位按鈕時(shí)内颗,需要重置數(shù)據(jù),所以寫一個(gè)reset()來重置數(shù)據(jù)敦腔。里面很簡(jiǎn)單均澳,設(shè)置isResettrue及清空數(shù)組。

    public func reset() {
        isReset = true
        times = []
    }

當(dāng)我們重新開始一次計(jì)次時(shí)符衔,數(shù)組該如何表現(xiàn)出來呢?這里我是在數(shù)組插入一個(gè)元素到首位找前,初始時(shí)間為零。當(dāng)開始計(jì)次后判族,同步更新數(shù)組首元素的值躺盛。

我在這個(gè)方法里寫了一個(gè)回調(diào),方便在重新開啟一個(gè)計(jì)時(shí)后做些事情形帮,參數(shù)默認(rèn)值為nil槽惫。

    public func beginingNewTime(comletion:(() ->())? = nil){
        times.insert(0, at: 0)
        isReset = false
        
        if let comletion = comletion {
            comletion()
        }
    }

下面這個(gè)方法就比較簡(jiǎn)單了,直接更新數(shù)組首元素的值辩撑。

    public func timing(time:Int) {
        times[0] = time
    }

這個(gè)類基本就是這些了界斜。

實(shí)現(xiàn)功能

下面看下controller里面的實(shí)現(xiàn)代碼,首先考慮控制器中需要哪些變量呢合冀?

  • 需要一個(gè)定時(shí)器來刷新時(shí)間各薇,以及一個(gè)咱們之前寫的模型類()
var timer: Timer? 
let data = stopWatchData()
  • 需要一個(gè)totalTime來存儲(chǔ)總時(shí)間,注意當(dāng)值改變時(shí)君躺,會(huì)同步更新頂部label的值峭判。
    var totalTime = 0 {
        willSet{
            timeLable.text = convertTime(seconds: newValue)
        }
    }

這里有一個(gè)方法convertTime(seconds:)开缎,因?yàn)閠otalTime存儲(chǔ)的是一個(gè)整數(shù),當(dāng)計(jì)時(shí)器每隔0.01s刷新時(shí)朝抖,totalTime 加1啥箭。所以將totalTime轉(zhuǎn)化成對(duì)應(yīng)時(shí)間的格式然后才能顯示出來,convertTime(seconds: )方法的實(shí)現(xiàn)如下所示治宣。

    func convertTime(seconds: Int) ->String{
        return String(format: "%02ld:%02ld.%02ld",seconds / 100 / 60, seconds / 100 % 60, seconds % 100)
    }
  • 存儲(chǔ)正在計(jì)次時(shí)間的變量(intervals),這個(gè)值就是啟動(dòng)時(shí)實(shí)時(shí)計(jì)次的時(shí)間急侥。因?yàn)榭偸窃趖ableview的第一行,所以這里先獲取到tableview的首行侮邀,這個(gè)獲取很簡(jiǎn)單坏怪,tableview類中有對(duì)應(yīng)的方法,取首段首行的值即可绊茧,我封裝成timingcell()方法铝宵,如下所示。RecordTimeCell是自定義的cell,稍后再講华畏。
    func timingCell()->RecordTimeCell?{
        return tableView.cellForRow(at: NSIndexPath(row: 0, section: 0) as IndexPath) as? RecordTimeCell
    }

對(duì)應(yīng)的inervals改變時(shí)鹏秋,cell上的值同步更新。

    var intervals = 0 {
        willSet{
            let cell = timingCell()
            cell?.detailTextLabel?.text = convertTime(seconds: newValue)
        }

    }

然后再就是按鈕的狀態(tài)切換亡笑,啟動(dòng)與暫停侣夷,計(jì)次與復(fù)位。我使用UIButton中的selected與normal來切換仑乌。
第一個(gè)是計(jì)時(shí)/復(fù)位按鈕百拓。我是將title設(shè)為復(fù)位作為selected狀態(tài),title設(shè)為計(jì)時(shí)為normal狀態(tài)晰甚。另外衙传,當(dāng)復(fù)位之后,還沒開始計(jì)次時(shí)厕九,計(jì)次按鈕是不能點(diǎn)的蓖捶,所以還當(dāng)設(shè)置一個(gè)disable狀態(tài),并且初始化時(shí)設(shè)置isEnabled為false,不能點(diǎn)擊扁远。

        resetButton.setTitle("計(jì)次", for: .disabled)
        resetButton.isEnabled = false
        resetButton .setBackgroundImage(createImage(UIColor.init(red: 0.08, green: 0.08, blue: 0.08, alpha: 1)), for: .disabled)
        
        resetButton.setTitle("復(fù)位", for: .selected);
        resetButton.setTitleColor(UIColor.white, for: .selected)
        resetButton.setBackgroundImage(createImage(UIColor.gray), for: .selected)
        
        resetButton.setTitle("計(jì)次", for: .normal)
        resetButton.setBackgroundImage(resetButton.backgroundImage(for: .selected), for: .normal)

接下來分析下這個(gè)按鈕的點(diǎn)擊事件腺阳,實(shí)際上里面就是一個(gè)if else 判斷,來分別處理select與normal兩種狀態(tài)穿香。

1 當(dāng)是select狀態(tài)(復(fù)位)時(shí),點(diǎn)擊按鈕, resetVariables()用來重置所有的變量绎速。余下就用來改變按鈕的狀態(tài)皮获,將按鈕設(shè)置成不可點(diǎn)擊,以及取消select狀態(tài)纹冤。

2 當(dāng)按鈕是normal狀態(tài)(計(jì)次)時(shí)洒宝,點(diǎn)擊之后购公,這時(shí)會(huì)重新計(jì)算一段時(shí)間,所以將intervals 重置為0雁歌,并且調(diào)用模型中的方法beginingNewTime()宏浩,在前面有說到,調(diào)用beginNewTime方法靠瞎,會(huì)在模型中的數(shù)組首位添加一個(gè)新的元素比庄。這樣就保證了模型中的數(shù)據(jù)也在實(shí)時(shí)更新。

3 無論是點(diǎn)擊復(fù)位還是計(jì)次乏盐,最后調(diào)用tableviwtableView.reloadData()刷新數(shù)據(jù)佳窑。

    @IBAction func reset(_ sender: WSButton) {
        if sender.isSelected { // 復(fù)位
            
            resetVariables()
            
            sender.isEnabled = false
            sender.isSelected = false
        } else { // 計(jì)次
            intervals = 0
            data.beginingNewTime()
        }
        
        // 最后刷新顯示的數(shù)據(jù)
        tableView.reloadData()
    }

這里給出resetVariables()方法,比較簡(jiǎn)單父能。

    func resetVariables(){
        totalTime = 0
        intervals = 0
        data.reset()
    }

第二個(gè)是啟動(dòng)/暫停按鈕神凑,我是將title設(shè)為啟動(dòng)作為normal狀態(tài),title設(shè)為停止時(shí)作為selected狀態(tài)何吝。

        startButton.setTitle("啟動(dòng)", for: .normal)
        startButton.setTitleColor(UIColor.init(red: 64 / 255.0, green: 203 / 255.0, blue: 96 / 255.0, alpha: 1), for: .normal)
        
        startButton.setBackgroundImage(createImage(UIColor.init(red: 74 / 255.0, green: 16 / 255.0, blue: 17 / 255.0, alpha: 1)), for: .selected)
        startButton.setTitle("停止", for: .selected)
        startButton.setTitleColor(.red, for: .selected);

我會(huì)著重講一下這個(gè)按鈕的點(diǎn)擊事件溉委,這里面處理的邏輯或許稍微有些復(fù)雜,請(qǐng)保持耐心爱榕,我會(huì)講述的細(xì)致一些瓣喊。

這里面可以分成4部分,首行代碼加另外3個(gè)if判斷呆细。

1 首行代碼是狀態(tài)切換型宝。當(dāng)是select狀態(tài)時(shí),狀態(tài)取反絮爷,取消select狀態(tài)趴酣。當(dāng)不是select狀態(tài)時(shí),狀態(tài)取反坑夯,變成select狀態(tài)岖寞。

2 當(dāng)點(diǎn)擊的是停止時(shí)(isSelected = true),狀態(tài)取反后變成啟動(dòng)(isSelect = flase)柜蜈,那么此時(shí)切換計(jì)次/復(fù)位按鈕應(yīng)該為復(fù)位仗谆,設(shè)置resetButton.isSelected = true,變成復(fù)位的狀態(tài)淑履。然后停止掉定時(shí)器隶垮,然后再return掉,結(jié)束這個(gè)方法秘噪。

第二步處理了點(diǎn)擊停止狸吞。3~4都是要處理當(dāng)點(diǎn)擊啟動(dòng)時(shí)該做哪些操作。

3.使用模型中的isReset判斷當(dāng)前是否是復(fù)位了,如果是蹋偏,當(dāng)點(diǎn)擊啟動(dòng)之后便斥,就要調(diào)用data.beginingNewTime() 重新開啟一個(gè)計(jì)次,并且左邊的復(fù)位/計(jì)次按鈕 從不可點(diǎn)擊變成可點(diǎn)擊計(jì)次的狀態(tài)。如果不是復(fù)位威始,那么當(dāng)點(diǎn)擊啟動(dòng)后枢纠,左邊按鈕要切換成可復(fù)位的狀態(tài)。

4.第四步用來開啟定時(shí)器黎棠,并且在定時(shí)器的刷新回調(diào)里面更新數(shù)據(jù)晋渺。注意這里調(diào)用了模型中的timing(time:)方法,傳入intervals葫掉,實(shí)時(shí)更新模型些举。

    @IBAction func start(_ sender: WSButton) {
    
        // 1
        sender.isSelected = !sender.isSelected
        
        // 2
        if !sender.isSelected { // 點(diǎn)擊停止
            resetButton.isSelected = true
            timer?.invalidate()
            timer = nil
            return
        }
        
        // 3
        if data.isReset {
            data.beginingNewTime {
                self.tableView.reloadData()
                self.resetButton.isEnabled = true
            }
        } else {
            resetButton.isSelected = false
        } 
        
        // 4
        if timer == nil {
            timer = Timer.init(timeInterval: 0.01, repeats: true, block: { [weak self] _ in
                self?.totalTime += 1
                self?.intervals += 1
                self?.data.timing(time: self!.intervals)
            })
            RunLoop.current.add(self.timer!, forMode: .commonModes)
        }
    }

另外要說的就是tableview了,比較常規(guī)的操作俭厚,這里就不做過多介紹了户魏。值得注意的是,這里cell的樣式使用value1就可滿足挪挤。

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return data.times.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        var cell = tableView.dequeueReusableCell(withIdentifier: "cell") as? RecordTimeCell
        
        if cell == nil {
            cell = RecordTimeCell.init(style: .value1, reuseIdentifier: "cell")
        }
        cell?.recordTime(with: data, indexPath)
         
        return cell!;
    }

接下來看看自定義的cell,里面有一個(gè)方法recordTime(with data: indexPath:)叼丑,傳入模型以及indexPath,indexPath用來取模型數(shù)組中的數(shù)據(jù)。另外根據(jù)模型中的maxTimeIndexminTimeIndex來確定是哪個(gè)cell,并對(duì)應(yīng)的修改cell上文本的顏色扛门。

代碼如下:

    public func recordTime( with data:stopWatchData, _ indexPath:IndexPath){
        
        textLabel?.textColor = UIColor.white
        detailTextLabel?.textColor = UIColor.white
        
        textLabel?.text = "計(jì)次\(data.times.count - indexPath.row)"
        let time = data.times[indexPath.row]
        detailTextLabel?.text = convertTime(seconds: time)
        
        if indexPath.row == data.maxTime{
            textLabel?.textColor = UIColor.red
            detailTextLabel?.textColor = UIColor.red
        }
        
        if indexPath.row == data.minTime{
            textLabel?.textColor = UIColor.green
            detailTextLabel?.textColor = UIColor.green
        }
    }

自此功能基本上就實(shí)現(xiàn)完成了鸠信,如果能耐心看到這里,不妨再往下看看论寨,接下來要說的是項(xiàng)目中的一些細(xì)節(jié)星立,主要有三個(gè)。

1葬凳, 要設(shè)置定時(shí)器的模式為commonmode绰垂,如果不設(shè)置的話,當(dāng)滑動(dòng)tableview時(shí)火焰,會(huì)停止計(jì)時(shí)劲装。

2,我們的按鈕是一個(gè)正方形昌简,如下圖占业。我們?cè)O(shè)置cornerRadius后才變成一個(gè)圓形,手機(jī)屏幕上顯示的是如下圖的紅色區(qū)域纯赎,但如果點(diǎn)擊圓形周圍的藍(lán)色部分谦疾,還是可以響應(yīng)事件的。

image

那么如何才能讓這一部分藍(lán)色區(qū)域不再響應(yīng)事件呢犬金?

比較簡(jiǎn)單念恍,這里可以自定義UIBUtton,并且重寫是否響應(yīng)事件的方法碎紊。

override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
        
        if super.point(inside: point, with: event) {
            let path = UIBezierPath.init(ovalIn: self.bounds)
            return path.contains(point)
        }
        
        return false
    }

3 第三個(gè)問題時(shí),頂部的label更新數(shù)據(jù)時(shí)會(huì)產(chǎn)生抖動(dòng)樊诺。

image

而蘋果手機(jī)上數(shù)字是很穩(wěn)定,不會(huì)抖動(dòng)的音同。

image

這個(gè)問題該如何解決呢词爬?老實(shí)說,我也思考了很久权均,我嘗試過使用NSMutableAttributeString來加大數(shù)字之間的間隔顿膨,發(fā)現(xiàn)并沒有效果。后來才發(fā)現(xiàn)叽赊,需要設(shè)置其他的字體才不會(huì)抖動(dòng)恋沃,使用系統(tǒng)默認(rèn)的字體是會(huì)抖動(dòng)的。我在項(xiàng)目中使用的是Helvetica Neue必指。

我的講述結(jié)束了囊咏。

如果還有什么疑惑,歡迎在評(píng)論區(qū)提問塔橡,也可以在github上提issue梅割,當(dāng)然我更加歡迎加我個(gè)人微信:WSAlonely。希望你能幫助我發(fā)現(xiàn)實(shí)現(xiàn)過程中的問題:)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末葛家,一起剝皮案震驚了整個(gè)濱河市户辞,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌癞谒,老刑警劉巖底燎,帶你破解...
    沈念sama閱讀 219,039評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異弹砚,居然都是意外死亡双仍,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門迅栅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來殊校,“玉大人,你說我怎么就攤上這事读存∥鳎” “怎么了?”我有些...
    開封第一講書人閱讀 165,417評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵让簿,是天一觀的道長(zhǎng)敬察。 經(jīng)常有香客問我,道長(zhǎng)尔当,這世上最難降的妖魔是什么莲祸? 我笑而不...
    開封第一講書人閱讀 58,868評(píng)論 1 295
  • 正文 為了忘掉前任蹂安,我火速辦了婚禮,結(jié)果婚禮上锐帜,老公的妹妹穿的比我還像新娘田盈。我一直安慰自己,他們只是感情好缴阎,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評(píng)論 6 392
  • 文/花漫 我一把揭開白布允瞧。 她就那樣靜靜地躺著,像睡著了一般蛮拔。 火紅的嫁衣襯著肌膚如雪述暂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,692評(píng)論 1 305
  • 那天建炫,我揣著相機(jī)與錄音畦韭,去河邊找鬼。 笑死肛跌,一個(gè)胖子當(dāng)著我的面吹牛艺配,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播惋砂,決...
    沈念sama閱讀 40,416評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼妒挎,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了西饵?” 一聲冷哼從身側(cè)響起酝掩,我...
    開封第一講書人閱讀 39,326評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎眷柔,沒想到半個(gè)月后期虾,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,782評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡驯嘱,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評(píng)論 3 337
  • 正文 我和宋清朗相戀三年镶苞,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鞠评。...
    茶點(diǎn)故事閱讀 40,102評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡茂蚓,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出剃幌,到底是詐尸還是另有隱情聋涨,我是刑警寧澤,帶...
    沈念sama閱讀 35,790評(píng)論 5 346
  • 正文 年R本政府宣布负乡,位于F島的核電站牍白,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏抖棘。R本人自食惡果不足惜茂腥,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評(píng)論 3 331
  • 文/蒙蒙 一狸涌、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧最岗,春花似錦帕胆、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至诊杆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間何陆,已是汗流浹背晨汹。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留贷盲,地道東北人淘这。 一個(gè)月前我還...
    沈念sama閱讀 48,332評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像巩剖,于是被迫代替她去往敵國和親铝穷。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評(píng)論 2 355