亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統(tǒng) > iOS > 正文

iOS優(yōu)化UITableViewCell高度計算的一些事兒

2019-10-21 18:39:22
字體:
供稿:網(wǎng)友

我是前言

這篇文章是我和我們團隊最近對 UITableViewCell 利用 AutoLayout 自動高度計算和 UITableView 滑動優(yōu)化的一個總結(jié)。
我們也在維護一個開源的擴展,UITableView+FDTemplateLayoutCell,讓高度計算這個事情變的前所未有的簡單,也受到了很多星星的支持,github鏈接請戳我

這篇總結(jié)你可以讀到:

  • UITableView高度計算和估算的機制
  • 不同iOS系統(tǒng)在高度計算上的差異
  • iOS8 self-sizing cell
  • UITableView+FDTemplateLayoutCell如何用一句話解決高度問題
  • UITableView+FDTemplateLayoutCell中對RunLoop的使用技巧

UITableViewCell高度計算

rowHeight

UITableView是我們再熟悉不過的視圖了,它的 delegate 和 data source 回調(diào)不知寫了多少次,也不免遇到 UITableViewCell 高度計算的事。UITableView 詢問 cell 高度有兩種方式。
一種是針對所有 Cell 具有固定高度的情況,通過:

self.tableView.rowHeight = 88;

上面的代碼指定了一個所有 cell 都是 88 高度的 UITableView,對于定高需求的表格,強烈建議使用這種(而非下面的)方式保證不必要的高度計算和調(diào)用。rowHeight屬性的默認(rèn)值是 44,所以一個空的 UITableView 顯示成那個樣子。

另一種方式就是實現(xiàn) UITableViewDelegate 中的:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { // return xxx}

需要注意的是,實現(xiàn)了這個方法后,rowHeight 的設(shè)置將無效。所以,這個方法適用于具有多種 cell 高度的 UITableView。

estimatedRowHeight

這個屬性 iOS7 就出現(xiàn)了, 文檔是這么描述它的作用的:

If the table contains variable height rows, it might be expensive to calculate all their heights when the table loads. Using estimation allows you to defer some of the cost of geometry calculation from load time to scrolling time.

恩,聽上去蠻靠譜的。我們知道,UITableView 是個 UIScrollView,就像平時使用 UIScrollView 一樣,加載時指定 contentSize 后它才能根據(jù)自己的 bounds、contentInset、contentOffset 等屬性共同決定是否可以滑動以及滾動條的長度。而 UITableView 在一開始并不知道自己會被填充多少內(nèi)容,于是詢問 data source 個數(shù)和創(chuàng)建 cell,同時詢問 delegate 這些 cell 應(yīng)該顯示的高度,這就造成它在加載的時候浪費了多余的計算在屏幕外邊的 cell 上。和上面的 rowHeight 很類似,設(shè)置這個估算高度有兩種方法:

self.tableView.estimatedRowHeight = 88;// or- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath { // return xxx}

有所不同的是,即使面對種類不同的 cell,我們依然可以使用簡單的 estimatedRowHeight 屬性賦值,只要整體估算值接近就可以,比如大概有一半 cell 高度是 44, 一半 cell 高度是 88, 那就可以估算一個 66,基本符合預(yù)期。

說完了估算高度的基本使用,可以開始吐槽了:

  1. 設(shè)置估算高度后,contentSize.height 根據(jù)“cell估算值 x cell個數(shù)”計算,這就導(dǎo)致滾動條的大小處于不穩(wěn)定的狀態(tài),contentSize 會隨著滾動從估算高度慢慢替換成真實高度,肉眼可見滾動條突然變化甚至“跳躍”。
  2. 若是有設(shè)計不好的下拉刷新或上拉加載控件,或是 KVO 了 contentSize 或 contentOffset 屬性,有可能使表格滑動時跳動。
  3. 估算高度設(shè)計初衷是好的,讓加載速度更快,那憑啥要去侵害滑動的流暢性呢,用戶可能對進入頁面時多零點幾秒加載時間感覺不大,但是滑動時實時計算高度帶來的卡頓是明顯能體驗到的,個人覺得還不如一開始都算好了呢(iOS8更過分,即使都算好了也會邊劃邊計算)

iOS8 self-sizing cell

具有動態(tài)高度內(nèi)容的 cell 一直是個頭疼的問題,比如聊天氣泡的 cell, frame 布局時代通常是用數(shù)據(jù)內(nèi)容反算高度:

CGFloat height = textHeightWithFont() + imageHeight + topMargin + bottomMargin + ...;

供 UITableViewDelegate 調(diào)用時很可能是個 cell 的類方法:

@interface BubbleCell : UITableViewCell+ (CGFloat)heightWithEntity:(id)entity;@end

各種魔法 margin 加上耦合了屏幕寬度。

AutoLayout 時代好了不少,提供了-systemLayoutSizeFittingSize:的 API,在 contentView 中設(shè)置約束后,就能計算出準(zhǔn)確的值;缺點是計算速度肯定沒有手算快,而且這是個實例方法,需要維護專門為計算高度而生的 template layout cell,它還要求使用者對約束設(shè)置的比較熟練,要保證 contentView 內(nèi)部上下左右所有方向都有約束支撐,設(shè)置不合理的話計算的高度就成了0。

這里還不得不提到一個 UILabel 的蛋疼問題,當(dāng) UILabel 行數(shù)大于0時,需要指定 preferredMaxLayoutWidth 后它才知道自己什么時候該折行。這是個“雞生蛋蛋生雞”的問題,因為 UILabel 需要知道 superview 的寬度才能折行,而 superview 的寬度還依仗著子 view 寬度的累加才能確定。這個問題好像到 iOS8 才能夠自動解決(不過我們找到了解決方案)

回到正題,iOS8 WWDC 中推出了 self-sizing cell 的概念,旨在讓 cell 自己負(fù)責(zé)自己的高度計算,使用 frame layout 和 auto layout 都可以享受到:

iOS優(yōu)化,UITableViewCell,高度計算

這個特性首先要求是 iOS8,要是最低支持的系統(tǒng)版本小于8的話,還得針對老版本單寫套老式的算高(囧),不過用的 API 到不是新面孔:

self.tableView.estimatedRowHeight = 213;self.tableView.rowHeight = UITableViewAutomaticDimension;

這里又不得不吐槽了,自動計算 rowHeight 跟 estimatedRowHeight 到底是有什么仇,如果不加上估算高度的設(shè)置,自動算高就失效了- -

PS:iOS8 系統(tǒng)中 rowHeight 的默認(rèn)值已經(jīng)設(shè)置成了 UITableViewAutomaticDimension,所以第二行代碼可以省略。

問題:

  • 這個自動算高在 push 到下一個頁面或者轉(zhuǎn)屏?xí)r會出現(xiàn)高度特別詭異的情況,不過現(xiàn)在的版本修復(fù)了。
  • 求一個能讓最低支持 iOS8 的公司- -

iOS8抽風(fēng)的算高機制

相同的代碼在 iOS7 和 iOS8 上滑動順暢程度完全不同,iOS8 莫名奇妙的卡。很大一部分原因是 iOS8 上的算高機制大不相同,這是我做的小測試:

iOS優(yōu)化,UITableViewCell,高度計算

研究后發(fā)現(xiàn)這么多次額外計算有下面的原因:

  • 不開啟高度估算時,UITableView 上來就要對所有 cell 調(diào)用算高來確定 contentSize
  • dequeueReusableCellWithIdentifier:forIndexPath: 相比不帶 “forIndexPath” 的版本會多調(diào)用一次高度計算
  • iOS7 計算高度后有”緩存“機制,不會重復(fù)計算;而 iOS8 不論何時都會重新計算 cell 高度

iOS8 把高度計算搞成這個樣子,從 WWDC 也倒是能找到點解釋,cell 被認(rèn)為隨時都可能改變高度(如從設(shè)置中調(diào)整動態(tài)字體大?。悦看位瑒映鰜砗蠖家匦掠嬎愀叨?。

說了這么多,究竟有沒有既能省去算高煩惱,又能保證順暢的滑動,還能支持 iOS6+ 的一站式解決方案呢?

UITableView+FDTemplateLayoutCell

使用 UITableView+FDTemplateLayoutCell 無疑是解決算高問題的最佳實踐之一,既有 iOS8 self-sizing 功能簡單的 API,又可以達(dá)到 iOS7 流暢的滑動效果,還保持了最低支持 iOS6。
使用起來大概是這樣:

#import <UITableView+FDTemplateLayoutCell.h>- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return [tableView fd_heightForCellWithIdentifier:@"identifer" cacheByIndexPath:indexPath configuration:^(id cell) { // 配置 cell 的數(shù)據(jù)源,和 "cellForRow" 干的事一致,比如: cell.entity = self.feedEntities[indexPath.row]; }];}

寫完上面的代碼后,你就已經(jīng)使用到了:

  • 和每個 UITableViewCell ReuseID 一一對應(yīng)的 template layout cell
    這個 cell 只為了參加高度計算,不會真的顯示到屏幕上;它通過 UITableView 的 -dequeueCellForReuseIdentifier: 方法 lazy 創(chuàng)建并保存,所以要求這個 ReuseID 必須已經(jīng)被注冊到了 UITableView 中,也就是說,要么是 Storyboard 中的原型 cell,要么就是使用了 UITableView 的 -registerClass:forCellReuseIdentifier: 或 -registerNib:forCellReuseIdentifier:其中之一的注冊方法。
  • 根據(jù) autolayout 約束自動計算高度
    使用了系統(tǒng)在 iOS6 就提供的 API:-systemLayoutSizeFittingSize:
  • 根據(jù) index path 的一套高度緩存機制
    計算出的高度會自動進行緩存,所以滑動時每個 cell 真正的高度計算只會發(fā)生一次,后面的高度詢問都會命中緩存,減少了非常可觀的多余計算。
  • 自動的緩存失效機制
    無須擔(dān)心你數(shù)據(jù)源的變化引起的緩存失效,當(dāng)調(diào)用如-reloadData,-deleteRowsAtIndexPaths:withRowAnimation:等任何一個觸發(fā) UITableView 刷新機制的方法時,已有的高度緩存將以最小的代價執(zhí)行失效。如刪除一個 indexPath 為 [0:5] 的 cell 時,[0:0] ~ [0:4] 的高度緩存不受影響,而 [0:5] 后面所有的緩存值都向前移動一個位置。自動緩存失效機制對 UITableView 的 9 個公有 API 都進行了分別的處理,以保證沒有一次多余的高度計算。
  • 預(yù)緩存機制
    預(yù)緩存機制將在 UITableView 沒有滑動的空閑時刻執(zhí)行,計算和緩存那些還沒有顯示到屏幕中的 cell,整個緩存過程
    全沒有感知,這使得完整列表的高度計算既沒有發(fā)生在加載時,又沒有發(fā)生在滑動時,同時保證了加載速度和滑動流暢性,下文會著重講下這塊的實現(xiàn)原理。

我們在設(shè)計這個工具的 API 時斟酌了非常長的時間,既要保證功能的強大,也要保證接口的精簡,一行調(diào)用背后隱藏著很多功能。

這一套緩存機制能對滑動起多大影響呢?除了肉眼能明顯的感知到外,我還做了個小測試:

一個有 54 個內(nèi)容和高度不同 cell 的 table view,從頭滑動到尾,再從尾滑動到頭,iOS8 系統(tǒng)下,iPhone6,使用 Time Profiler 監(jiān)測算高函數(shù)所花費的時間:

未使用緩存API、未使用估算,共花費 877 ms:

iOS優(yōu)化,UITableViewCell,高度計算

使用緩存API、開啟估算,共花費 77 ms:

iOS優(yōu)化,UITableViewCell,高度計算

測試數(shù)據(jù)的精度先不管,從量級上就差了一個數(shù)量級,說實話自己也沒想到差距有這么大- -

同時,工具也順手解決了-preferredMaxLayoutWidth的問題,在計算高度前向 contentView 加了一條和 table view 寬度相同的寬度約束,強行讓 contentView 內(nèi)部的控件知道了自己父 view 的寬度,再反算自己被外界約束的寬度,破除“雞生蛋蛋生雞”的問題,這里比較 tricky,就不展開說了。下面說說利用 RunLoop 預(yù)緩存的實現(xiàn)。

利用RunLoop空閑時間執(zhí)行預(yù)緩存任務(wù)

FDTemplateLayoutCell 的高度預(yù)緩存是一個優(yōu)化功能,它要求頁面處于空閑狀態(tài)時才執(zhí)行計算,當(dāng)用戶正在滑動列表時顯然不應(yīng)該執(zhí)行計算任務(wù)影響滑動體驗。

一般來說,這個功能要耦合 UITableView 的滑動狀態(tài)才行,但這種實現(xiàn)十分不優(yōu)雅且可能破壞外部的 delegate 結(jié)構(gòu),但好在我們還有RunLoop這個工具,了解它的運行機制后,可以用很簡單的代碼實現(xiàn)上面的功能。

空閑RunLoopMode

在曾經(jīng)的 RunLoop 線下分享會中介紹了 RunLoopMode 的概念。

當(dāng)用戶正在滑動 UIScrollView 時,RunLoop 將切換到 UITrackingRunLoopMode 接受滑動手勢和處理滑動事件(包括減速和彈簧效果),此時,其他 Mode (除 NSRunLoopCommonModes 這個組合 Mode)下的事件將全部暫停執(zhí)行,來保證滑動事件的優(yōu)先處理,這也是 iOS 滑動順暢的重要原因。

當(dāng) UI 沒在滑動時,默認(rèn)的 Mode 是 NSDefaultRunLoopMode(同 CF 中的 kCFRunLoopDefaultMode),同時也是 CF 中定義的 “空閑狀態(tài) Mode”。當(dāng)用戶啥也不點,此時也沒有什么網(wǎng)絡(luò) IO 時,就是在這個 Mode 下。

用RunLoopObserver找準(zhǔn)時機

注冊 RunLoopObserver 可以觀測當(dāng)前 RunLoop 的運行狀態(tài),并在狀態(tài)機切換時收到通知:

  • RunLoop開始
  • RunLoop即將處理Timer
  • RunLoop即將處理Source
  • RunLoop即將進入休眠狀態(tài)
  • RunLoop即將從休眠狀態(tài)被事件喚醒
  • RunLoop退出

因為“預(yù)緩存高度”的任務(wù)需要在最無感知的時刻進行,所以應(yīng)該同時滿足:

  • RunLoop 處于“空閑”狀態(tài) Mode
  • 當(dāng)這一次 RunLoop 迭代處理完成了所有事件,馬上要休眠時

使用 CF 的帶 block 版本的注冊函數(shù)可以讓代碼更簡潔:

CFRunLoopRef runLoop = CFRunLoopGetCurrent();CFStringRef runLoopMode = kCFRunLoopDefaultMode;CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(kCFAllocatorDefault, kCFRunLoopBeforeWaiting, true, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity _) { // TODO here});CFRunLoopAddObserver(runLoop, observer, runLoopMode);

在其中的 TODO 位置,就可以開始任務(wù)的收集和分發(fā)了,當(dāng)然,不能忘記適時的移除這個 observer

分解成多個RunLoop Source任務(wù)

假設(shè)列表有 20 個 cell,加載后展示了前 5 個,那么開啟估算后 table view 只計算了這 5 個的高度,此時剩下 15 個就是“預(yù)緩存”的任務(wù),而我們并不希望這 15 個計算任務(wù)在同一個 RunLoop 迭代中同步執(zhí)行,這樣會卡頓 UI,所以應(yīng)該把它們分別分解到 15 個 RunLoop 迭代中執(zhí)行,這時就需要手動向 RunLoop 中添加 Source 任務(wù)(由應(yīng)用發(fā)起和處理的是 Source 0 任務(wù))
Foundation 層沒對 RunLoopSource 提供直接構(gòu)建的 API,但是提供了一個間接的、既熟悉又陌生的 API:

- (void)performSelector:(SEL)aSelector  onThread:(NSThread *)thr  withObject:(id)arg  waitUntilDone:(BOOL)wait   modes:(NSArray *)array;

這個方法將創(chuàng)建一個 Source 0 任務(wù),分發(fā)到指定線程的 RunLoop 中,在給定的 Mode 下執(zhí)行,若指定的 RunLoop 處于休眠狀態(tài),則喚醒它處理事件,簡單來說就是“睡你xx,起來嗨!”

于是,我們用一個可變數(shù)組裝載當(dāng)前所有需要“預(yù)緩存”的 index path,每個 RunLoopObserver 回調(diào)時都把第一個任務(wù)拿出來分發(fā):

NSMutableArray *mutableIndexPathsToBePrecached = self.fd_allIndexPathsToBePrecached.mutableCopy;CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(kCFAllocatorDefault, kCFRunLoopBeforeWaiting, true, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity _) { if (mutableIndexPathsToBePrecached.count == 0) { CFRunLoopRemoveObserver(runLoop, observer, runLoopMode); CFRelease(observer); // 注意釋放,否則會造成內(nèi)存泄露 return; } NSIndexPath *indexPath = mutableIndexPathsToBePrecached.firstObject; [mutableIndexPathsToBePrecached removeObject:indexPath]; [self performSelector:@selector(fd_precacheIndexPathIfNeeded:)   onThread:[NSThread mainThread]  withObject:indexPath  waitUntilDone:NO   modes:@[NSDefaultRunLoopMode]];});

這樣,每個任務(wù)都被分配到下個“空閑” RunLoop 迭代中執(zhí)行,其間但凡有滑動事件開始,Mode 切換成 UITrackingRunLoopMode,所有的“預(yù)緩存”任務(wù)的分發(fā)和執(zhí)行都會自動暫定,最大程度保證滑動流暢。

PS: 預(yù)緩存功能因為下拉刷新的沖突和不明顯的收益已經(jīng)廢棄

開始使用UITableView+FDTemplateLayoutCell

如果你覺得這個工具能幫得到你,整合到工程也十分簡單。

使用 cocoapods:

pod search UITableView+FDTemplateLayoutCell

寫這篇文章時的最新版本為 1.2,去除了前一個版本的黑魔法,增加了預(yù)緩存功能。

歡迎使用和支持這個工具,有 bug 請隨時反饋哦~

再復(fù)習(xí)下 github 地址: https://github.com/forkingdog/UITableView-FDTemplateLayoutCell

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對VEVB武林網(wǎng)的支持。


注:相關(guān)教程知識閱讀請移步到IOS開發(fā)頻道。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
中文字幕久精品免费视频| 国产对白在线播放| 国产欧美一区二区三区在线看蜜臀| 综合久久五月天| 欧美日韩一区二区在线免费观看| 久久婷婷五月综合色丁香| 韩国精品视频| 日韩国产在线一| 国产情侣小视频| 国产一区二区伦理| 久久久免费观看视频| 欧美一区二区| 九九热99久久久国产盗摄| 欧美极品第一页| 女同性恋一区二区三区| 裸体丰满少妇做受久久99精品| 亚洲一区二区免费| 亚洲最新视频在线观看| 国产精品99精品久久免费| 欧美白嫩的18sex少妇| 亚洲人成电影在线观看网| 91人妻一区二区三区蜜臀| 在线观看日韩毛片| 激情综合五月天| 久久精品国产一区二区电影| 美女精品视频一区| 欧美经典一区二区| 夜夜夜操操操| 亚洲国产精品视频在线观看| 欧美激情区在线播放| 久久99精品网久久| 国产午夜亚洲精品午夜鲁丝片| 日本aa大片在线播放免费看| 国产成人综合网站| 日韩片在线观看| 日韩av卡一卡二| 国内毛片久久| 成人国产精品一区| 蜜臀久久99精品久久一区二区| 亚洲国产精品v| 欧美视频1区| 香蕉国产成人午夜av影院| 欧美丰满少妇xxxx| 男男一级淫片免费播放| 999精品嫩草久久久久久99| 国产专区在线播放| 人妻av无码一区二区三区| 成人一区二区三区中文字幕| 永久免费网站视频在线观看| 国产精品18| 午夜欧美精品久久久久久久| 91偷拍一区二区三区精品| 黄色仓库视频网站| 国内在线高清免费视频| 国产中文字幕乱人伦在线观看| 亚洲色偷精品一区二区三区| 国外成人在线视频| 精品一区二区电影| 免费a v网站| 精品国产乱码久久久久久蜜臀| 97se视频在线观看| 伊人网av在线| 精品成人a区在线观看| 亚洲第一区第二区| 男人搞女人网站| 丰满少妇又爽又紧又丰满电影| 91久久在线视频| 在线看片你懂的| 婷婷国产成人精品视频| 亚洲精品女人| 欧美猛烈性xbxbxbxb| 黄频网站在线观看| 成人免费一区二区三区| 在线播放国产一区| 中文字幕av高清| 亚洲影视资源| 久草资源站在线观看| 深田えいみ中文字幕99久久| 四虎影视最新网站入口在线观看| 国产精品久久久久久亚洲毛片| www.成人影院| 91小视频网站| 水蜜桃免费高清视频在线播放| 国产精品一区二区av| 国产精品精品国产| 大香伊人久久精品一区二区| 久久久com| 91国在线产| 污黄色在线观看| 亚洲精品免费播放| 蜜桃视频在线观看91| 国产又黄又粗又猛又爽的视频| 免费无码毛片一区二三区| 少妇毛片一区二区三区| 99re只有精品| 性欧美成人播放77777| 亚洲人成网亚洲欧洲无码| 精品av中文字幕在线毛片| 国产一区二区三区不卡视频网站| 伊人网视频在线| 欧美色图一区| 免费成人蒂法网站| 国产午夜精品理论片| 成人影院天天5g天天爽无毒影院| 毛片在线能看| 91福利视频在线观看| 欧美性生交大片免费| 午夜伦欧美伦电影理论片| 亚洲欧美日韩图片| 亚洲一区精品在线观看| 国产日韩精品在线看| 欧美日韩免费精品| 91精品国产欧美日韩| jizz18欧美18| 免费看亚洲片| 久久尤物电影视频在线观看| 亚洲午夜日本在线观看| 色婷婷一区二区| 中文字幕久久精品| 亚洲欧美另类图片| 日韩欧美高清一区二区三区| 久久综合色天天久久综合图片| 中午字幕在线观看| 久久综合综合久久| 午夜免费欧美电影| 国产精品国产精品88| 一区二区三区四区国产精品| 日本簧片在线观看| 18视频在线观看| 久久亚洲欧洲| 国产免费色视频| 91高清视频在线免费观看| 欧美成人家庭影院| 电影亚洲精品噜噜在线观看| 涩涩视频免费看| 欧美三级网站| 2018国产精品视频| 视频在线观看免费影院欧美meiju| 在线观看免费黄视频| 精品久久久久久国产91| 亚洲日本理论电影| 亚洲精品aⅴ中文字幕乱码| 色嗨嗨av一区二区三区| 国产免费一区二区视频| 中文字幕一精品亚洲无线一区| 在线视频婷婷| 亚洲国产欧美一区二区三区丁香婷| 国产综合久久久| 91在线观看免费高清完整版在线观看| 91视频在线免费| 色婷婷一区二区三区av免费看| 成人免费在线电影网| 日韩精品色哟哟| 涩涩视频网站在线观看| 亚洲精品写真福利| 天堂网avav| 久久天堂电影网| 日韩精品999| 123区在线| 日韩不卡视频一区二区| 偷拍欧美精品| 欧美日韩一区二| 久草亚洲一区| 国产精品国产三级国产普通话对白| 另类小说视频一区二区| 欧美日韩国产另类一区| 日韩大片在线免费观看| 亚洲成av人片在线观看香蕉| 国产一区二区三区自拍| 国产成人精彩在线视频九色| 不卡一区2区| 97超碰欧美中文字幕| 欧美日韩激情在线观看| 成人在线tv视频| 亚洲国产精品999| 午夜国产精品理论片久久影院| 一本久道久久综合无码中文| 一区二区三区四区欧美日韩| 直接看的黄色网址| 最新欧美精品一区二区三区| 国产乱码一区二区| 日韩影院免费视频| 亚洲成人av在线影院| 97超级碰碰碰| 欧美a级理论片| 亚州av综合色区无码一区| 国产精品大片wwwwww| 久久男女视频| 亚洲a v网站| 亚洲高清在线视频| 日本丰满少妇裸体自慰| 国产风韵犹存在线视精品| 久久在线视频| 日日噜噜夜夜狠狠视频| 国产 欧美 日韩 在线| 2023欧美最顶级a∨艳星| 人人妻人人澡人人爽欧美一区双| 97人人模人人爽视频一区二区| 国产精品videossex久久发布| 午夜影院免费在线| 亚洲中国最大av网站| 日本中文字幕一区| 午夜国产一区二区三区| 91精品国产一区二区三区香蕉| 日韩精品一二三四| 激情亚洲网站| 国产精品资源| 午夜成年女人毛片免费观看| 天天综合狠狠精品| 亚洲国产精品日韩| 精品人妻一区二区三区含羞草| 亚洲黄色成人久久久| 69av在线| 美女网站免费观看视频| 在线观看国产日韩| 成人免费淫片在线费观看| 亚洲一区二区三| 精品欧美一区二区久久久伦| www.爱久久| 亚洲日产av中文字幕| 久久久久久国产免费| 人人妻人人澡人人爽人人欧美一区| 午夜欧美大尺度福利影院在线看| 久草成色在线| 日韩免费av一区二区三区| 亚洲一二三区在线观看| 在线观看免费视频你懂的| 狠狠v欧美v日韩v亚洲ⅴ| 亚洲第一网站男人都懂| 深田えいみ中文字幕99久久| 日韩理论片一区二区| 成人午夜网址| 日本一区二区三区视频在线观看| 国产精品一区视频| 日韩精品在线电影| 国产高清在线视频| 久久综合之合合综合久久| 美女精品视频| 欧美日韩一区二区三区| 国产精品久久| 黄色录像1级片| 欧美午夜激情在线| 中文字幕在线中文字幕二区| 久久精品亚洲7777影院| 一本色道久久亚洲综合精品蜜桃| 国产亚洲一区二区在线| 色悠久久久久综合先锋影音下载| 欧美日韩一级片网站| 亚洲天堂av一区二区三区| 国产精品污视频| www.蜜臀av| 久久精品网站视频| 99re6热只有精品免费观看| 男人天堂中文字幕| 国产一区在线视频| 777久久久精品| 日韩美女av在线| 国产精品9区| 好吊操视频这里只有精品| 日韩av在线资源| 日本一本高清视频| 国产欧美视频在线| 欧美日韩和欧美的一区二区| 日韩激情视频在线| 色视频www在线播放国产成人| 欧美黑人性猛交xxx| 日本欧美一二三区| 羞羞视频在线观看一区二区| 欧美草逼视频| 爱情电影网av一区二区| 久久在线91| 97精品国产福利一区二区三区| 97视频免费在线| 中文字幕免费高清视频| 欧美不卡视频| 亚洲激情二区| 国产高清视频网站| 国产白袜脚足j棉袜在线观看| 97色伦图片97综合影院| av成人在线电影| 3d动漫精品啪啪| 无码国精品一区二区免费蜜桃| 欧美xxxxxxxx| 亚洲五月激情网| 国产亚洲午夜高清国产拍精品| 欧美久久天堂| 亚洲乱码一区二区三区| 亚洲国产三级| 国产成人一区二区三区影院在线| 黄色动漫网站| 国产精品电影一区二区三区| 欧美精品九九| 91黑丝高跟在线| 人人妻人人澡人人爽欧美一区双| 91麻豆国产自产在线观看亚洲| 国产精品久久久久久久一区探花| 欧美人妖视频| 久久在线观看免费| 青青草原成人网| 亚洲一区二区三区在线视频| 小小的日本在线观看免费色网| 国产精品青草久久久久福利99| 亚洲午夜精品久久| 1024国产在线| julia中文字幕一区二区99在线| 国产不卡一区二区三区在线观看| 久久久在线免费观看| 五月婷婷综合在线| 久久久亚洲欧洲日产国码aⅴ| 精品国产乱码久久久久久蜜臀网站| 成人欧美精品久久久久影院| 99久久夜色精品国产亚洲| 视频一区视频二区视频三区高| 日韩成人短视频| 国产91对白刺激露脸在线观看| 亚洲啪av永久无码精品放毛片| 久久免费精品一区二区| 免费99精品国产自在在线| ****av在线网毛片| 欧美777四色影| 24小时免费看片在线观看| 免费91视频| 亚洲人免费视频| 欧美精品一区二区三区四区五区| 国产精品一卡二卡在线观看| caoporn超碰国产公开| 欧美性猛交xxxx黑人| 痴汉一区二区三区|