iOS-UITableView性能優(yōu)化

1.最常用的就是cell的重用溜嗜, 注冊重用標(biāo)識符
它的原理是设易,根據(jù)cell高度和tableView大小,確定界面上能顯示幾個cell侦铜,例如界面上只能顯示6個cell专甩,那么這6個cell都是單獨創(chuàng)建的而不是根據(jù)重用標(biāo)識符去緩存中找到的。當(dāng)你開始滑動tableView時钉稍,第一個cell開始漸漸消失涤躲,第七個cell開始顯示的時候,會創(chuàng)建第七個cell嫁盲,而不是用第一個cell去顯示在第七個cell位置篓叶,因為有可能第一個cell顯示了一半,而第7個cell也顯示了一半羞秤,這個時候第一個cell還沒有被放入緩存中缸托,緩存中沒有可利用的cell。所以實際上創(chuàng)建了7個cell瘾蛋。當(dāng)滑動tableView去顯示第八個cell的時候俐镐,這時緩存中已經(jīng)有第一個cell,那么系統(tǒng)會直接從緩存中拿出來而不是創(chuàng)建哺哼,這樣就算有100個cell的數(shù)據(jù)需要顯示佩抹,實際也只消耗7個cell的內(nèi)存。

  • 重用
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSString *identifier = @"CellIdentifier";//標(biāo)識符
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];//沖緩沖池中取出同樣標(biāo)識的cell
    if(cell == nil)
    {
        //緩沖池中沒有時取董,創(chuàng)建新的
        cell = [[UITableViewCell alloc]init........];
    }
return cell;
}
  • 如果cell內(nèi)部顯示的內(nèi)容來自web棍苹,使用異步加載,緩存結(jié)果請求茵汰。

  • 盡量少在cellForRowAtIndexPath中設(shè)置數(shù)據(jù)枢里,假如有100個數(shù)據(jù),那么cellForRowAtIndexPath會執(zhí)行100次蹂午,但實際屏幕顯示卻只有幾個栏豺。這樣會大量消耗時間,可以在willDisplayCell里進(jìn)行數(shù)據(jù)的設(shè)置豆胸,因為willDisplayCell只會在cell將要顯示時調(diào)用奥洼,屏幕顯示幾個cell才會調(diào)用⊥砗可以大大減少數(shù)據(jù)設(shè)置時間

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//不要去設(shè)置cell的數(shù)據(jù)
}
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
//當(dāng)cell要顯示時才去設(shè)置需要顯示的cell對應(yīng)的數(shù)據(jù)
}


2.避免cell的重新布局

  • 創(chuàng)建cell的時候就完成布局灵奖,在后期設(shè)置cell屬性的時候盡量少去添加移除cell內(nèi)部控件的布局,盡量用hidden控制搬泥,在那種界面變動較大的界面或者控件較多的界面桑寨,盡量用多個 注冊重用標(biāo)識符或者不用cell來代表,這樣減少內(nèi)部重新布局帶來的計算忿檩,雖然多個重用標(biāo)識符會帶來內(nèi)存變多尉尾,但相比讓用戶感覺界面流暢,這點犧牲是有必要的燥透。

  • 各個信息都是根據(jù)之前算好的布局進(jìn)行繪制的沙咏。需要異步繪制辨图。重寫drawRect方法就不需要異步繪制了,因為drawRect本來就是異步繪制的肢藐。圖文混排的繪制故河,coreText繪制。

3.提前計算并緩存cell的屬性及內(nèi)容

  • 當(dāng)我們創(chuàng)建cell的數(shù)據(jù)源方法時吆豹,編譯器并不是先創(chuàng)建cell 再定cell的高度
  • 而是先根據(jù)內(nèi)容一次確定每一個cell的高度鱼的,高度確定后,再創(chuàng)建要顯示的cell痘煤,滾動時凑阶,每當(dāng)cell進(jìn)入憑虛都會計算高度,提前估算高度告訴編譯器衷快,編譯器知道高度后宙橱,緊接著就會創(chuàng)建cell,這時再調(diào)用高度的具體計算方法蘸拔,這樣可以防止浪費時間去計算顯示以外的cell
  • cell內(nèi)部盡量少計算师郑。比如文字的寬度,圖片的寬高等调窍,盡量在model設(shè)置前就計算好cell的高度宝冕。而不要在cell內(nèi)部去進(jìn)行計算,阻塞線程.(加入cell高度計算比較復(fù)雜邓萨,可以設(shè)置一個類似與cell內(nèi)部計算的view,在創(chuàng)建model數(shù)據(jù)的時候猬仁,用這個view預(yù)先計算出cell的高度,而不是在cell內(nèi)部或者tableView:heightForRowAtIndexPath方法里去計算先誉,設(shè)置cell數(shù)據(jù)的時候高度直接從model里拿出。view的計算可以用異步線程去計算的烁,但是不能讓用戶等待cell刷新時間過長)

4.使用局部更新

  • 如果只是更新某組的話褐耳,使用reloadSection進(jìn)行局部更新
  • 如果目標(biāo)行與當(dāng)前行相差超過指定行數(shù),只在目標(biāo)滾動范圍的前后制定n行加載渴庆。滾動很快時铃芦,只加載目標(biāo)范圍內(nèi)得cell,這樣按需加載襟雷,極大地提高了流暢性

5.減少cell中控件的數(shù)量

  • 盡量使cell得布局大致相同刃滓,不同風(fēng)格的cell可以使用不用的重用標(biāo)識符,初始化時添加控件(見仁見智哈耸弄,看個人對界面的分析領(lǐng)會)
  • 不適用的可以先隱藏

6.緩存行高

estimatedHeightForRow不能和HeightForRow里面的layoutIfNeed同時存在咧虎,這兩者同時存在才會出現(xiàn)“竄動”的bug。所以我的建議是:只要是固定行高就寫預(yù)估行高來減少行高調(diào)用次數(shù)提升性能计呈。如果是動態(tài)行高就不要寫預(yù)估方法了砰诵,用一個行高的緩存字典來減少代碼的調(diào)用次數(shù)即可

7.使用不透明視圖

  • 不透明的視圖可以極大地提高渲染的速度征唬。因此如非必要,可以將table cell及其子視圖的opaque屬性設(shè)為YES(默認(rèn)值UIButton內(nèi)部的label的opaque默認(rèn)值都是NO])茁彭。
  • Cell中不要使用clearColor总寒,無背景色,透明度也不要設(shè)置為0理肺。
  • 關(guān)于opaque

Opaque該屬性為BOOL值摄闸,UIView的默認(rèn)值是YES,但UIButton等子類的默認(rèn)值都是NO妹萨。opaque表示當(dāng)前UIView是否不透明年枕,不過搞笑的是事實上它卻決定不了當(dāng)前UIView是不是不透明,比如你將opaque設(shè)為NO眠副,該UIView照樣是可見的(是否可見是由alpha或hidden屬性決定的)画切,照理說為NO就表示透明,那就應(yīng)該是不可見的呀囱怕?

顯示器中的每個像素點都可以顯示一個由RGBA顏色空間組成的色值霍弹,比如有紅色和綠色兩個圖層色塊,對于沒有交叉的部分娃弓,即純紅色和綠色部分來說典格,對應(yīng)位置的像素點只需要簡單的顯示紅或綠,對應(yīng)的RGBA為(1台丛,0耍缴,0,1)和(0挽霉,1防嗡,0,1)就行了侠坎,負(fù)責(zé)圖形顯示的GPU需要很小的計算量就可以確定像素點對應(yīng)的顯示內(nèi)容蚁趁。

問題是紅色和綠色還有相交的一塊,其相交的顏色為黃色实胸。這里的黃色是怎么來的呢他嫡?原來,GPU會通過圖層一和圖層二的顏色進(jìn)行圖層混合庐完,計算出混合部分的顏色,最理想情況的計算公式如下:

R = S + D * ( 1 – Sa )

其中门躯,R表示混合結(jié)果的顏色,S是源顏色(位于上層的紅色圖層一),D是目標(biāo)顏色(位于下層的綠色圖層二)窒升,Sa是源顏色的alpha值,即透明度饱须。公式中所有的S和D顏色都假定已經(jīng)預(yù)先乘以了他們的透明度台谊。

知道圖層混合的基本原理以后,再回到正題說說opaque屬性的作用锅铅。當(dāng)UIView的opaque屬性被設(shè)為YES以后,按照上面的公式盐须,也就是Sa的值為1玩荠,這個時候公式就變成了:

R = S

即不管D為什么,結(jié)果都一樣贼邓。因此GPU將不會做任何的計算合成阶冈,不需要考慮它下方的任何東西(因為都被它遮擋住了),而是簡單從這個層拷貝塑径。這節(jié)省了GPU相當(dāng)大的工作量女坑。由此看來,opaque屬性的真實用處是給繪圖系統(tǒng)提供一個性能優(yōu)化開關(guān)统舀!

按照前面的邏輯匆骗,當(dāng)opaque屬性被設(shè)為YES時,GPU就不會再利用圖層顏色合成公式去合成真正的色值誉简。因此碉就,如果opaque被設(shè)置成YES,而對應(yīng)UIView的alpha屬性不為1.0的時候闷串,就會有不可預(yù)料的情況發(fā)生铝噩,這一點蘋果在官方文檔中有明確的說明:

An opaque view is expected to fill its bounds with entirely opaque content—that is, the content should have an alpha value of 1.0. If the view is opaque and either does not fill its bounds or contains wholly or partially transparent content,the results are unpredictable. You should always set the value of this property to NO if the view is fully or partially transparent.

  • 舉例
    比如,如果當(dāng)前我們擁有一個和屏幕大小一致的單一圖層窿克,那么屏幕上的每一個像素相當(dāng)于圖層中的一個像素,這個時候毛甲,我們在這個圖層上放置一個完全不透明的圖層年叮,那么GPU將會把上面的圖層合成到下面的圖層當(dāng)中,由于上面的是一個完全不透明的圖層玻募,所以上面的圖層會部份遮蓋掉下面的圖層只损,而在遮蓋掉的矩形區(qū)域內(nèi),GPU會直接使用上面圖層的像素來顯示。如果我們最底的圖層上放置的是一個有透明度的圖層跃惫,那么在這個矩形區(qū)域里叮叹,GPU需要混合上下兩個圖層來計算出在屏幕上顯示出來的像素的RGB值。若在同一個區(qū)域內(nèi)爆存,存在著多個有透明度的圖層蛉顽,那么GPU需要更多的計算才能得出最終像素的RGB值。而我們要做的就是避免像素混合先较,盡可能地為視圖設(shè)置背景色携冤,且設(shè)置opaque為YES,這會大大減少GPU的計算闲勺。
    這種顏色的混合需要消耗一定的GPU曾棕,在實際開發(fā)中遠(yuǎn)不止2層翘地。如果只顯示最上層衙耕,建議最上次透明度為1和opaque為YES.這樣GPU就不會計算其他層的layer,減少計算臭杰。
//以下這種處理方式會出現(xiàn)UILabel出現(xiàn)未知的邊框渴杆,解決辦法有2種
1.讓uilbale的寬高都為正數(shù)
2.設(shè)置UILabel的邊框顏色為自己的背景顏色磁奖。
這2種辦法雖然可以解決比搭,但是在按鈕中時身诺,點擊按鈕會出現(xiàn)邊框


//IOS8以后UILabel的底圖層變成了_UILabelLayer
//如果label的內(nèi)容是中文霉赡,label實際渲染區(qū)域要大于label的size
//所以只要UILabel中含有中文穴亏,比如會造成像素混合增加GPU的計算。
//cell中的UILabel和button里的label沒有設(shè)置background棠涮,都是默認(rèn)的严肪。
//要不造成像素混合诬垂,需要讓UILabel有背景结窘,并設(shè)置masksToBounds來排除像素混合

self.label.background = self.contentView.background;
self.label.layer.masksToBounds = YES;
  • 注意 :maskTobounds與cornerRadius結(jié)合才會離屏渲染隧枫,單獨使用不會造成離屏渲染

8.cell動畫和繪制

重用時官脓,它內(nèi)部繪制的內(nèi)容并不會被自動清除卑笨,因此你可能需要調(diào)用setNeedsDisplayInRect:或setNeedsDisplay方法仑撞。

CPU與GPU的說明
CPU就是做繪制的操作把內(nèi)容放到緩存里隧哮,GPU負(fù)責(zé)從緩存里讀取數(shù)據(jù)然后渲染到屏幕上沮翔。CPU將準(zhǔn)備好的bitmap放到RAM里采蚀,GPU去搬這快內(nèi)存到VRAM中處理榆鼠。 而這個過程GPU所能承受的極限大概在16.7ms完成一幀的處理璧眠,所以最開始提到的60fps其實就是GPU能處理的最高頻率袁滥。 GPU是圖形硬件灾螃,主要的工作是混合紋理并算出像素的RGB值腰鬼,這是一個非常復(fù)雜的計算過程熄赡,計算的過程越復(fù)雜彼硫,所需要消耗的時間就越長拧篮,GPU的使用率就越高串绩,這并不是一個好的現(xiàn)像辛蚊,而我們需要做的是減少GPU的計算量痊土。

如果不需要動畫效果,最好不要使用insertRowsAtIndexPaths:withRowAnimation:方法紊浩,而是直接調(diào) 用reloadData方法
利用預(yù)渲染加速iOS設(shè)備的圖像顯示

  • 當(dāng)圖片下載完成后坊谁,如果cell是可見的口芍,還需要更新圖像
NSArray *indexPaths = [self.tableView indexPathsForVisibleRows];
for (NSIndexPath *visibleIndexPath in indexPaths) {
if (indexPath == visibleIndexPath) { 
MyTableViewCell *cell = (MyTableViewCell *)[self.tableView cellForRowAtIndexPath:indexPath];
cell.image = image; 
[cell setNeedsDisplayInRect:imageRect]; break; 
}
}// 也可不遍歷鬓椭,直接與頭尾相比較,看是否在中間即可翘瓮。

insertRowsAtIndexPaths:withRowAnimation:方法资盅,插入新行需要在主線程執(zhí)行呵扛,而一次插入很多行的話(例如50行)今穿,會長時間阻塞主線程烫堤。而換成reloadData方法的話鸽斟,瞬間就處理完了富蓄。

9.減少視圖的數(shù)目

textLabel立倍、detailTextLabel和imageView等view口注,而你還可以自定義一些視圖放在它的contentView里寝志。然而view是很大的對象,創(chuàng)建它會消耗較多資源毫缆,并且也影響渲染的性能苦丁。如果你的table cell包含圖片旺拉,且數(shù)目較多,使用默認(rèn)的UITableViewCell會非常影響性能蒂秘。奇怪的是,使用自定義的view规丽,而非預(yù)定義的view,明顯會快些冰抢。

10.不要阻塞主線程

出現(xiàn)這種現(xiàn)象的原因就是主線程執(zhí)行了耗時很長的函數(shù)或方法挎扰,在其執(zhí)行完畢前遵倦,無法繪制屏幕和響應(yīng)用戶請求梧躺。其中最常見的就是網(wǎng)絡(luò)請求了掠哥,它通常都需要花費數(shù)秒的時間秃诵,而你不應(yīng)該讓用戶等待那么久菠净。
解決辦法就是使用多線程嗤练,讓子線程去執(zhí)行這些函數(shù)或方法。這里面還有一個學(xué)問霜大,當(dāng)下載線程數(shù)超過2時战坤,會顯著影響主線程的性能。因此在使用ASIHTTPRequest時碟嘴,可以用一個NSOperationQueue來維護(hù)下載請求娜扇,并將其maxConcurrentOperationCount設(shè)為2雀瓢。而NSURLRequest則可以配合GCD來實現(xiàn)玉掸,或者使用NSURLConnection的setDelegateQueue:方法司浪。
當(dāng)然啊易,在不需要響應(yīng)用戶請求時认罩,也可以增加下載線程數(shù),以加快下載速度:

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
    if (!decelerate) {
        queue.maxConcurrentOperationCount = 5;
    }
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    queue.maxConcurrentOperationCount = 5;
}

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
    queue.maxConcurrentOperationCount = 2;
}

11.cell內(nèi)部圖片處理
UIImage類方法總結(jié)

假如內(nèi)存里有一張400x400的圖片,要放到100x100的imageview里劫拗,如果不做任何處理页慷,直接丟進(jìn)去酒繁,問題就大了州袒,這意味著,GPU需要對大圖進(jìn)行縮放到小的區(qū)域顯示,需要做像素點的sampling菇存,這種smapling的代價很高依鸥,又需要兼顧pixel alignment贱迟。計算量會飆升关筒。
OpenGL ES是直接調(diào)用底層的GPU進(jìn)行渲染;Core Graphics是一個基于CPU的繪制引擎睡榆;

    //重新繪制圖片
    //按照imageWidth, imageHeight指定寬高開始繪制圖片
    UIGraphicsBeginImageContext(CGSizeMake(imageWidth, imageHeight));
    //把image原圖繪制成指定寬高
    [image drawInRect:CGRectMake(0,0,imageWidth,  imageHeight)];
    //從繪制中獲取指定寬高的圖片
    UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
    //結(jié)束繪制
    UIGraphicsEndImageContext();

RunLoop開始塘揣,RunLoop是一個60fps的回調(diào)亲铡,也就是說每16.7ms繪制一次屏幕奖蔓,也就是我們需要在這個時間內(nèi)完成view的緩沖區(qū)創(chuàng)建吆鹤,view內(nèi)容的繪制這些是CPU的工作疑务;然后把緩沖區(qū)交給GPU渲染知允,這里包括了多個View的拼接(Compositing),紋理的渲染(Texture)等等温鸽,最后Display到屏幕上嗤朴。但是如果你在16.7ms內(nèi)做的事情太多,導(dǎo)致CPU股缸,GPU無法在指定時間內(nèi)完成指定的工作敦姻,那么就會出現(xiàn)卡頓現(xiàn)象镰惦,也就是丟幀旺入。

  • 圓角圖片處理
  • 1.直接在原圖上層覆蓋一個內(nèi)部透明圓的圖片茵瘾。(目前來說最優(yōu)的方式)
  • 2.重新繪制圖片(雖然重新繪制后會減少渲染的計算拗秘,但還是會影響渲染雕旨。這種方式只是把GPU的壓力轉(zhuǎn)義到了CPU上。負(fù)載平衡)凡涩。下面是繪制圖片的方法
//根據(jù)size 和 radius 把image重新繪制突照。
-(UIImage *)getCornerRadius:(UIImage *)image size:(CGSize)size radius:(int)r
{
    int w = size.width;
    int h = size.height;
    int radius = r;

    UIImage *img = image;
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(NULL, w, h, 8, 4 * w, colorSpace, kCGImageAlphaPremultipliedFirst);
    CGRect rect = CGRectMake(0, 0, w, h);

    CGContextBeginPath(context);
    addRoundedRectToPath(context, rect, radius, radius);
    CGContextClosePath(context);
    CGContextClip(context);
    CGContextDrawImage(context, CGRectMake(0, 0, w, h), img.CGImage);
    CGImageRef imageMasked = CGBitmapContextCreateImage(context);
    img = [UIImage imageWithCGImage:imageMasked];

    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);
    CGImageRelease(imageMasked);
    return img;
}


static void addRoundedRectToPath(CGContextRef context, CGRect rect, float ovalWidth,
                                 float ovalHeight)
{
    float fw, fh;
    
    if (ovalWidth == 0 || ovalHeight == 0)
    {
        CGContextAddRect(context, rect);
        return;
    }
    
    CGContextSaveGState(context);
    CGContextTranslateCTM(context, CGRectGetMinX(rect), CGRectGetMinY(rect));
    CGContextScaleCTM(context, ovalWidth, ovalHeight);
    fw = CGRectGetWidth(rect) / ovalWidth;
    fh = CGRectGetHeight(rect) / ovalHeight;
    
    CGContextMoveToPoint(context, fw, fh/2);  // Start at lower right corner
    CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1);  // Top right corner
    CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1); // Top left corner
    CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1); // Lower left corner
    CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1); // Back to lower right
    
    CGContextClosePath(context);
    CGContextRestoreGState(context);
}

當(dāng)然這里圓角的處理最好還是使用不透明的mask來遮罩座慰。既能不用因為繪制造成CPU計算,而多余區(qū)域的渲染造成GPU的計算翠拣。

Tip:復(fù)制下YY大神說的話和Demo

目前有些第三方微博客戶端(比如 VVebo版仔、墨客等),使用了一種方式來避免高速滑動時 Cell 的繪制過程,相關(guān)實現(xiàn)見這個項目:VVeboTableViewDemo蛮粮。它的原理是益缎,當(dāng)滑動時,松開手指后然想,立刻計算出滑動停止時 Cell 的位置莺奔,并預(yù)先繪制那個位置附近的幾個 Cell,而忽略當(dāng)前滑動中的 Cell变泄。這個方法比較有技巧性令哟,并且對于滑動性能來說提升也很大屏富,唯一的缺點就是快速滑動中會出現(xiàn)大量空白內(nèi)容。如果你不想實現(xiàn)比較麻煩的異步繪制但又想保證滑動的流暢性乐严,這個技巧是個不錯的選擇艾扮。

滾動時調(diào)整視圖的繪制行為

滾動會導(dǎo)致數(shù)個視圖在短時間內(nèi)更新,如果視圖的繪制代碼沒有被適當(dāng)調(diào)整,滾動時的性能會非常低,造成卡頓。相對于去考慮如何讓cell視圖內(nèi)部布局簡單控件數(shù)量少,應(yīng)該更加傾向于滾動開始時改變cell視圖顯示方式夏志。例如當(dāng)滑動時暫時性的減少需要顯示的內(nèi)容溉贿,或者滾動時改變cell視圖顯示的方式,比如圖片抢蚀、視頻僅顯示占位圖等屋休。當(dāng)滾動停止時织堂,在將cell視圖顯示狀態(tài)返回到前一狀態(tài)。

參考資料:UITableView性能優(yōu)化與卡頓問題

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末捕发,一起剝皮案震驚了整個濱河市法挨,隨后出現(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)我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著益楼,像睡著了一般禽翼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上生均,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天,我揣著相機(jī)與錄音腥刹,去河邊找鬼马胧。 笑死,一個胖子當(dāng)著我的面吹牛衔峰,可吹牛的內(nèi)容都是我干的佩脊。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼垫卤,長吁一口氣:“原來是場噩夢啊……” “哼威彰!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起穴肘,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤歇盼,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后评抚,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體豹缀,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年慨代,在試婚紗的時候發(fā)現(xiàn)自己被綠了邢笙。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡侍匙,死狀恐怖氮惯,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情想暗,我是刑警寧澤妇汗,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站说莫,受9級特大地震影響铛纬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜唬滑,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一告唆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧晶密,春花似錦擒悬、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春僧凤,著一層夾襖步出監(jiān)牢的瞬間畜侦,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工躯保, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留旋膳,地道東北人。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓途事,卻偏偏與公主長得像验懊,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子尸变,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,979評論 2 355

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