3atv精品不卡视频,97人人超碰国产精品最新,中文字幕av一区二区三区人妻少妇,久久久精品波多野结衣,日韩一区二区三区精品

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

iOS面试题目及答案总结

發布時間:2024/3/13 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 iOS面试题目及答案总结 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

這是一些常見的筆試問題,總共12道題目。題目標紅了,答案的話是我從網上查來的,大家覺得不標準的可以自行百度。

?

(1)????應用程序啟動時的順序

首先回顧一下應用程序的啟動過程

?

①.先加載Main函數

?

②.在Main函數里的 UIApplicationMain方法中,創建Application對象 創建Application的Delegate對象

?

③.創建主循環,代理對象開始監聽事件

?

④.啟動完畢會調用 didFinishLaunching方法,并在這個方法中創建UIWindow

?

⑤.設置UIWindow的根控制器是誰

?

⑥.如果有storyboard,會根據info.plist中找到應用程序的入口storyboard并加載箭頭所指的控制器

?

⑦.顯示窗口

?

本文考慮的時步驟③之后到步驟⑦結束時將要調用的方法

?

其中有AppDelegate,ViewController,MainView(控制器的View),ChildView(子控件的View)的18個方法

?

AppDelegate中的:

?

1.application:didFinishLaunchingWithOptions:

?

2.applicationDidBecomeActive:

?

ViewController中的:

?

3.loadView

?

4.viewDidLoad

?

5.load

?

6.initialize

?

7.viewWillAppear

?

8.viewWillLayoutSubviews

?

9.viewDidLayoutSubviews

?

10.viewDidAppear

?

MainView(控制器的View)中的:

?

11.initWithCoder(如果沒有storyboard就會調用initWithFrame,這里兩種方法視為一種)

?

12.awakeFromNib

?

13.layoutSubviews

?

14.drawRect

?

ChildView(子控件View)中的:

?

15.initWithCoder(如果沒有storyboard就會調用initWithFrame,這里兩種方法視為一種)

?

16.awakeFromNib

?

17.layoutSubviews

?

18.drawRect

(2)????堆和棧的區別

按管理方式分

對于棧來講,是由系統編譯器自動管理,不需要程序員手動管理

對于堆來講,釋放工作由程序員手動管理,不及時回收容易產生內存泄露

按分配方式分

堆是動態分配和回收內存的,沒有靜態分配的堆

棧有兩種分配方式:靜態分配和動態分配

靜態分配是系統編譯器完成的,比如局部變量的分配

動態分配是有alloc函數進行分配的,但是棧的動態分配和堆是不同的,它的動態分配也由系統編譯器進行釋放,不需要程序員手動管理

一位網友用10個字總結了堆和棧的區別

?

棧是吃了吐 堆是吃了拉

?

(3)????線程和進程的區別

1.1 程序:

?

由源代碼生成的可執行應用。(例如:QQ.APP)

?

1.2 進程:

?

一個正在運行的程序可以看做一個進程。(例如:正在運行的QQ就是一個進程),進程擁有獨立運行所需的全部資源。

?

1.3 線程:

?

程序中獨立運行的代碼段。(例如:接收QQ消息的代碼)

一個進程是由一或多個線程組成。進程只負責資源的調度和分配,線程才是程序真正的執行單元,負責代碼的執行。

?

2. 單線程與多線程有什么區別

?

2.1單線程

?

每個正在運行的程序(即進程),至少包含一個線程,這個線程叫主線程。

主線程在程序啟動時被創建,用于執行main函數。

只有一個主線程的程序,稱作單線程程序。

主線程負責執行程序的所有代碼(UI展現以及刷新,網絡請求,本地存儲等等)。這些代碼只能順序執行,無法并發執行。

?

2.2多線程

?

擁有多個線程的程序,稱作多線程程序。

iOS允許用戶自己開辟新的線程,相對于主線程來講,這些線程,稱作子線程。

可以根據需要開辟若干子線程

子線程和主線程是 都是 獨立的運行單元,各自的執行互不影響,因此能夠并發執行。

?

2.3區別

?

單線程程序:只有一個線程,代碼順序執行,容易出現代碼阻塞(頁面假死)。

多線程程序:有多個線程,線程間獨立運行,能有效的避免代碼阻塞,并且提高程序的運行性能。

注意:iOS中關于UI的添加和刷新必須在主線程中操作。

(4)????如何開啟多線程

在這篇文章中,我將為你整理一下 iOS 開發中幾種多線程方案,以及其使用方法和注意事項。當然也會給出幾種多線程的案例,在實際使用中感受它們的區別。還有一點需要說明的是,這篇文章將會使用 Swift 和 Objective-c 兩種語言講解,雙語幼兒園。OK,let's begin!

?

概述

?

這篇文章中,我不會說多線程是什么、線程和進程的區別、多線程有什么用,當然我也不會說什么是串行、什么是并行等問題,這些我們應該都知道的。

?

在 iOS 中其實目前有 4 套多線程方案,他們分別是:

?

Pthreads

NSThread

GCD

NSOperation& NSOperationQueue

所以接下來,我會一一講解這些方案的使用方法和一些案例。在將這些內容的時候,我也會順帶說一些多線程周邊產品。比如:線程同步、 延時執行、 單例模式 等等。

?

Pthreads

?

其實這個方案不用說的,只是拿來充個數,為了讓大家了解一下就好了。百度百科里是這么說的:

?

POSIX線程(POSIX threads),簡稱Pthreads,是線程的POSIX標準。該標準定義了創建和操縱線程的一整套API。在類Unix操作系統(Unix、Linux、Mac OS X等)中,都使用Pthreads作為操作系統的線程。

簡單地說,這是一套在很多操作系統上都通用的多線程API,所以移植性很強(然并卵),當然在 iOS 中也是可以的。不過這是基于 c語言 的框架,使用起來這酸爽!感受一下:

?

OBJECTIVE-C

?

當然第一步要包含頭文件

?

#import<pthread.h>

然后創建線程,并執行任務

?

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

??? pthread_t thread;

??? //創建一個線程并自動執行

??? pthread_create(&thread, NULL, start,NULL);

}

?

void*start(void *data) {

??? NSLog(@"%@", [NSThreadcurrentThread]);

?

??? return NULL;

}

打印輸出:

?

2015-07-2723:57:21.689 testThread[10616:2644653] <NSThread: 0x7fbb48d33690>{number= 2, name = (null)}

看代碼就會發現他需要 c語言函數,這是比較蛋疼的,更蛋疼的是你需要手動處理線程的各個狀態的轉換即管理生命周期,比如,這段代碼雖然創建了一個線程,但并沒有銷毀。

?

SWIFT

?

很遺憾,在我目前的swift1.2 中無法執行這套方法,原因是這個函數需要傳入一個函數指針CFunctionPointer<T> 類型,但是目前 swift 無法將方法轉換成此類型。聽說 swift 2.0 引入一個新特性 @convention(c), 可以完成 Swift 方法轉換成 c 語言指針的。在這里可以看到

?

那么,Pthreads方案的多線程我就介紹這么多,畢竟做 iOS 開發幾乎不可能用到。但是如果你感興趣的話,或者說想要自己實現一套多線程方案,從底層開始定制,那么可以去搜一下相關資料。

?

NSThread

?

這套方案是經過蘋果封裝后的,并且完全面向對象的。所以你可以直接操控線程對象,非常直觀和方便。但是,它的生命周期還是需要我們手動管理,所以這套方案也是偶爾用用,比如 [NSThread currentThread],它可以獲取當前線程類,你就可以知道當前線程的各種屬性,用于調試十分方便。下面來看看它的一些用法。

?

創建并啟動

?

先創建線程類,再啟動

?

OBJECTIVE-C

?

? // 創建

? NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(run:) object:nil];

?

? // 啟動

? [thread start];

SWIFT

?

? //創建

? let thread = NSThread(target: self, selector:"run:", object: nil)

?

? //啟動

? thread.start()

創建并自動啟動

?

OBJECTIVE-C

?

? [NSThreaddetachNewThreadSelector:@selector(run:) toTarget:self withObject:nil];

SWIFT

?

?NSThread.detachNewThreadSelector("run:", toTarget: self,withObject: nil)

使用NSObject 的方法創建并自動啟動

?

OBJECTIVE-C

?

? [selfperformSelectorInBackground:@selector(run:) withObject:nil];

SWIFT

?

很遺憾 too! 蘋果認為 performSelector: 不安全,所以在 Swift 去掉了這個方法。

?

Note: TheperformSelector: method and related selector-invoking methods are not importedin Swift because they are inherently unsafe.

其他方法

?

除了創建啟動外,NSThread還以很多方法,下面我列舉一些常見的方法,當然我列舉的并不完整,更多方法大家可以去類的定義里去看。

?

OBJECTIVE-C

?

//取消線程

-(void)cancel;

?

//啟動線程

-(void)start;

?

//判斷某個線程的狀態的屬性

@property(readonly, getter=isExecuting) BOOL executing;

@property(readonly, getter=isFinished) BOOL finished;

@property(readonly, getter=isCancelled) BOOL cancelled;

?

//設置和獲取線程名字

-(void)setName:(NSString*)n;

-(NSString*)name;

?

//獲取當前線程信息

+(NSThread *)currentThread;

?

//獲取主線程信息

+(NSThread *)mainThread;

?

//使當前線程暫停一段時間,或者暫停到某個時刻

+(void)sleepForTimeInterval:(NSTimeInterval)time;

+(void)sleepUntilDate:(NSDate *)date;

SWIFT

?

Swift的方法名字和OC的方法名都一樣,我就不浪費空間列舉出來了。

?

其實,NSThread用起來也挺簡單的,因為它就那幾種方法。同時,我們也只有在一些非常簡單的場景才會用 NSThread, 畢竟它還不夠智能,不能優雅地處理多線程中的其他高級概念。所以接下來要說的內容才是重點。

?

GCD

?

GrandCentral Dispatch,聽名字就霸氣。它是蘋果為多核的并行運算提出的解決方案,所以會自動合理地利用更多的CPU內核(比如雙核、四核),最重要的是它會自動管理線程的生命周期(創建線程、調度任務、銷毀線程),完全不需要我們管理,我們只需要告訴干什么就行。同時它使用的也是 c語言,不過由于使用了 Block(Swift里叫做閉包),使得使用起來更加方便,而且靈活。所以基本上大家都使用 GCD 這套方案,老少咸宜,實在是居家旅行、殺人滅口,必備良藥。不好意思,有點中二,咱們繼續。

?

任務和隊列

?

在 GCD 中,加入了兩個非常重要的概念:任務 和 隊列。

?

任務:即操作,你想要干什么,說白了就是一段代碼,在 GCD 中就是一個 Block,所以添加任務十分方便。任務有兩種執行方式:同步執行 和 異步執行,他們之間的區別是 是否會創建新的線程。

?

同步執行:只要是同步執行的任務,都會在當前線程執行,不會另開線程。

?

異步執行:只要是異步執行的任務,都會另開線程,在別的線程執行。

?

更新:

這里說的并不準確,同步(sync) 和 異步(async) 的主要區別在于會不會阻塞當前線程,直到 Block 中的任務執行完畢!

如果是 同步(sync)操作,它會阻塞當前線程并等待 Block 中的任務執行完畢,然后當前線程才會繼續往下運行。

如果是 異步(async)操作,當前線程會直接往下執行,它不會阻塞當前線程。

隊列:用于存放任務。一共有兩種隊列, 串行隊列 和 并行隊列。

?

串行隊列 中的任務會根據隊列的定義 FIFO 的執行,一個接一個的先進先出的進行執行。

?

更新:放到串行隊列的任務,GCD 會 FIFO(先進先出) 地取出來一個,執行一個,然后取下一個,這樣一個一個的執行。

并行隊列 中的任務 根據同步或異步有不同的執行方式。

?

更新:放到并行隊列的任務,GCD 也會 FIFO的取出來,但不同的是,它取出來一個就會放到別的線程,然后再取出來一個又放到另一個的線程。這樣由于取的動作很快,忽略不計,看起來,所有的任務都是一起執行的。不過需要注意,GCD 會根據系統資源控制并行的數量,所以如果任務很多,它并不會讓所有任務同時執行。

雖然很繞,但請看下表:

?

同步執行? 異步執行

串行隊列? 當前線程,一個一個執行? 其他線程,一個一個執行

并行隊列? 當前線程,一個一個執行? 開很多線程,一起執行

創建隊列

?

主隊列:這是一個特殊的 串行隊列。什么是主隊列,大家都知道吧,它用于刷新 UI,任何需要刷新 UI 的工作都要在主隊列執行,所以一般耗時的任務都要放到別的線程執行。

?

? //OBJECTIVE-C

? dispatch_queue_t queue =ispatch_get_main_queue();

?

? //SWIFT

? let queue = ispatch_get_main_queue()

自己創建的隊列:凡是自己創建的隊列都是 串行隊列。 其中第一個參數是標識符,用于 DEBUG 的時候標識唯一的隊列,可以為空。大家可以看xcode的文檔查看參數意義。

?

更新:自己可以創建 串行隊列, 也可以創建 并行隊列。看下面的代碼(代碼已更新),它有兩個參數,第一個上面已經說了,第二個才是最重要的。

第二個參數用來表示創建的隊列是串行的還是并行的,傳入 DISPATCH_QUEUE_SERIAL 或 NULL 表示創建串行隊列。傳入 DISPATCH_QUEUE_CONCURRENT 表示創建并行隊列。

? //OBJECTIVE-C

? //串行隊列

? dispatch_queue_t queue =dispatch_queue_create("tk.bourne.testQueue", NULL);

? dispatch_queue_t queue =dispatch_queue_create("tk.bourne.testQueue", DISPATCH_QUEUE_SERIAL);

? //并行隊列

? dispatch_queue_t queue =dispatch_queue_create("tk.bourne.testQueue",DISPATCH_QUEUE_CONCURRENT);

?

? //SWIFT

? //串行隊列

? let queue =dispatch_queue_create("tk.bourne.testQueue", nil);

? let queue =dispatch_queue_create("tk.bourne.testQueue", DISPATCH_QUEUE_SERIAL)

? //并行隊列

? let queue =dispatch_queue_create("tk.bourne.testQueue",DISPATCH_QUEUE_CONCURRENT)

全局并行隊列:這應該是唯一一個并行隊列, 只要是并行任務一般都加入到這個隊列。這是系統提供的一個并發隊列。

?

? //OBJECTIVE-C

? dispatch_queue_t queue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

?

? //SWIFT

? let queue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

創建任務

?

同步任務: 不會另開線程 改:會阻塞當前線程 (SYNC)

?

OBJECTIVE-C

?

? dispatch_sync(<#queue#>, ^{

????? //code here

????? NSLog(@"%@", [NSThreadcurrentThread]);

? });

SWIFT

?

? dispatch_sync(<#queue#>, { () ->Void in

????? //code here

????? println(NSThread.currentThread())

? })

異步任務:會另開線程 改:不會阻塞當前線程 (ASYNC)

?

OBJECTIVE-C

?

? dispatch_async(<#queue#>, ^{

????? //code here

????? NSLog(@"%@", [NSThreadcurrentThread]);

? });

SWIFT

?

? dispatch_async(<#queue#>, { () ->Void in

????? //code here

????? println(NSThread.currentThread())

? })

更新:

為了更好的理解同步和異步,和各種隊列的使用,下面看兩個示例:

示例一:

以下代碼在主線程調用,結果是什么?

NSLog("之前 - %@", NSThread.currentThread())

dispatch_sync(dispatch_get_main_queue(),{ () -> Void in

??????? NSLog("sync - %@",NSThread.currentThread())

})

NSLog("之后 - %@", NSThread.currentThread())

答案:

只會打印第一句:之前 - <NSThread: 0x7fb3a9e16470>{number = 1, name = main} ,然后主線程就卡死了,你可以在界面上放一個按鈕,你就會發現點不了了。

解釋:

同步任務會阻塞當前線程,然后把 Block 中的任務放到指定的隊列中執行,只有等到 Block 中的任務完成后才會讓當前線程繼續往下運行。

那么這里的步驟就是:打印完第一句后,dispatch_sync 立即阻塞當前的主線程,然后把 Block 中的任務放到 main_queue 中,可是 main_queue 中的任務會被取出來放到主線程中執行,但主線程這個時候已經被阻塞了,所以 Block 中的任務就不能完成,它不完成,dispatch_sync 就會一直阻塞主線程,這就是死鎖現象。導致主線程一直卡死。

?

示例二:

以下代碼會產生什么結果?

?

let queue= dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL)

?

NSLog("之前 - %@", NSThread.currentThread())

?

dispatch_async(queue,{ () -> Void in

??? NSLog("sync之前- %@", NSThread.currentThread())

??? dispatch_sync(queue, { () -> Void in

???????? NSLog("sync - %@",NSThread.currentThread())

??? })

??? NSLog("sync之后- %@", NSThread.currentThread())

})

?

NSLog("之后 - %@", NSThread.currentThread())

?

**答案:**

2015-07-3002:06:51.058 test[33329:8793087] 之前 - <NSThread:0x7fe32050dbb0>{number = 1, name = main}

2015-07-3002:06:51.059 test[33329:8793356] sync之前 - <NSThread:0x7fe32062e9f0>{number = 2, name = (null)}

2015-07-3002:06:51.059 test[33329:8793087] 之后 - <NSThread:0x7fe32050dbb0>{number = 1, name = main}

很明顯 `sync- %@` 和 `sync之后 - %@` 沒有被打印出來!這是為什么呢?我們再來分析一下:

?

>**分析:**

我們按執行順序一步步來哦:

1. 使用 `DISPATCH_QUEUE_SERIAL` 這個參數,創建了一個 **串行隊列**。

2. 打印出 `之前 - %@` 這句。

3.`dispatch_async` 異步執行,所以當前線程不會被阻塞,于是有了兩條線程,一條當前線程繼續往下打印出 `之后 - %@`這句, 另一臺執行 Block 中的內容打印 `sync之前 - %@` 這句。因為這兩條是并行的,所以打印的先后順序無所謂。

4. 注意,高潮來了。現在的情況和上一個例子一樣了。`dispatch_sync`同步執行,于是它所在的線程會被阻塞,一直等到 `sync`里的任務執行完才會繼續往下。于是 `sync` 就高興的把自己Block 中的任務放到 `queue` 中,可誰想`queue` 是一個串行隊列,一次執行一個任務,所以 `sync` 的 Block 必須等到前一個任務執行完畢,可萬萬沒想到的是 `queue` 正在執行的任務就是被 `sync` 阻塞了的那個。于是又發生了死鎖。所以 `sync` 所在的線程被卡死了。剩下的兩句代碼自然不會打印。

?

?

### 隊列組

?

隊列組可以將很多隊列添加到一個組里,這樣做的好處是,當這個組里所有的任務都執行完了,隊列組會通過一個方法通知我們。下面是使用方法,這是一個很實用的功能。

?

######OBJECTIVE-C

?

```objective-c

//1.創建隊列組

dispatch_group_tgroup = dispatch_group_create();

//2.創建隊列

dispatch_queue_tqueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

?

//3.多次使用隊列組的方法執行任務, 只有異步方法

//3.1.執行3次循環

dispatch_group_async(group,queue, ^{

?? for (NSInteger i = 0; i < 3; i++) {

?????? NSLog(@"group-01 - %@",[NSThread currentThread]);

?? }

});

?

//3.2.主隊列執行8次循環

dispatch_group_async(group,dispatch_get_main_queue(), ^{

?? for (NSInteger i = 0; i < 8; i++) {

?????? NSLog(@"group-02 - %@",[NSThread currentThread]);

?? }

});

?

//3.3.執行5次循環

dispatch_group_async(group,queue, ^{

?? for (NSInteger i = 0; i < 5; i++) {

?????? NSLog(@"group-03 - %@",[NSThread currentThread]);

?? }

});

?

//4.都完成后會自動通知

dispatch_group_notify(group,dispatch_get_main_queue(), ^{

?? NSLog(@"完成 -%@", [NSThread currentThread]);

});

SWIFT

?

//1.創建隊列組

let group= dispatch_group_create()

//2.創建隊列

let queue= dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

?

//3.多次使用隊列組的方法執行任務, 只有異步方法

//3.1.執行3次循環

dispatch_group_async(group,queue) { () -> Void in

??? for _ in 0..<3 {

??????? NSLog("group-01 - %@",NSThread.currentThread())

??? }

}

?

//3.2.主隊列執行8次循環

dispatch_group_async(group,dispatch_get_main_queue()) { () -> Void in

??? for _ in 0..<8 {

??????? NSLog("group-02 - %@", NSThread.currentThread())

??? }

}

?

//3.3.執行5次循環

dispatch_group_async(group,queue) { () -> Void in

??? for _ in 0..<5 {

??????? NSLog("group-03 - %@",NSThread.currentThread())

??? }

}

?

//4.都完成后會自動通知

dispatch_group_notify(group,dispatch_get_main_queue()) { () -> Void in

??? NSLog("完成 -%@", NSThread.currentThread())

}

打印結果

?

2015-07-2803:40:34.277 test[12540:3319271] group-03 - <NSThread:0x7f9772536f00>{number = 3, name = (null)}

?

2015-07-2803:40:34.277 test[12540:3319146] group-02 - <NSThread: 0x7f977240ba60>{number= 1, name = main}

?

2015-07-2803:40:34.277 test[12540:3319146] group-02 - <NSThread:0x7f977240ba60>{number = 1, name = main}

?

2015-07-2803:40:34.277 test[12540:3319271] group-03 - <NSThread:0x7f9772536f00>{number = 3, name = (null)}

?

2015-07-2803:40:34.278 test[12540:3319146] group-02 - <NSThread:0x7f977240ba60>{number = 1, name = main}

?

2015-07-2803:40:34.278 test[12540:3319271] group-03 - <NSThread:0x7f9772536f00>{number = 3, name = (null)}

?

2015-07-2803:40:34.278 test[12540:3319271] group-03 - <NSThread:0x7f9772536f00>{number = 3, name = (null)}

?

2015-07-2803:40:34.278 test[12540:3319146] group-02 - <NSThread:0x7f977240ba60>{number = 1, name = main}

?

2015-07-2803:40:34.277 test[12540:3319273] group-01 - <NSThread: 0x7f977272e8d0>{number= 2, name = (null)}

?

2015-07-2803:40:34.278 test[12540:3319271] group-03 - <NSThread:0x7f9772536f00>{number = 3, name = (null)}

?

2015-07-2803:40:34.278 test[12540:3319146] group-02 - <NSThread:0x7f977240ba60>{number = 1, name = main}

?

2015-07-2803:40:34.278 test[12540:3319273] group-01 - <NSThread:0x7f977272e8d0>{number = 2, name = (null)}

?

2015-07-2803:40:34.278 test[12540:3319146] group-02 - <NSThread:0x7f977240ba60>{number = 1, name = main}

?

2015-07-2803:40:34.278 test[12540:3319273] group-01 - <NSThread:0x7f977272e8d0>{number = 2, name = (null)}

?

2015-07-2803:40:34.279 test[12540:3319146] group-02 - <NSThread:0x7f977240ba60>{number = 1, name = main}

?

2015-07-2803:40:34.279 test[12540:3319146] group-02 - <NSThread: 0x7f977240ba60>{number= 1, name = main}

?

2015-07-2803:40:34.279 test[12540:3319146] 完成 - <NSThread:0x7f977240ba60>{number = 1, name = main}

這些就是 GCD 的基本功能,但是它的能力遠不止這些,等講完 NSOperation 后,我們再來看看它的一些其他方面用途。而且,只要你想象力夠豐富,你可以組合出更好的用法。

?

更新:關于GCD,還有兩個需要說的:

func dispatch_barrier_async(_queue: dispatch_queue_t, _ block: dispatch_block_t):

這個方法重點是你傳入的 queue,當你傳入的 queue 是通過 DISPATCH_QUEUE_CONCURRENT 參數自己創建的 queue 時,這個方法會阻塞這個 queue(注意是阻塞 queue ,而不是阻塞當前線程),一直等到這個 queue 中排在它前面的任務都執行完成后才會開始執行自己,自己執行完畢后,再會取消阻塞,使這個 queue 中排在它后面的任務繼續執行。

如果你傳入的是其他的 queue, 那么它就和 dispatch_async 一樣了。

funcdispatch_barrier_sync(_ queue: dispatch_queue_t, _ block: dispatch_block_t):

這個方法的使用和上一個一樣,傳入 自定義的并發隊列(DISPATCH_QUEUE_CONCURRENT),它和上一個方法一樣的阻塞queue,不同的是 這個方法還會 阻塞當前線程。

如果你傳入的是其他的 queue, 那么它就和 dispatch_sync 一樣了。

NSOperation和NSOperationQueue

?

NSOperation是蘋果公司對 GCD 的封裝,完全面向對象,所以使用起來更好理解。 大家可以看到 NSOperation 和 NSOperationQueue 分別對應 GCD 的 任務 和 隊列 。操作步驟也很好理解:

?

將要執行的任務封裝到一個 NSOperation 對象中。

將此任務添加到一個NSOperationQueue 對象中。

然后系統就會自動在執行任務。至于同步還是異步、串行還是并行請繼續往下看:

?

添加任務

?

值得說明的是,NSOperation只是一個抽象類,所以不能封裝任務。但它有 2 個子類用于封裝任務。分別是:NSInvocationOperation 和 NSBlockOperation 。創建一個 Operation 后,需要調用 start 方法來啟動任務,它會 默認在當前隊列同步執行。當然你也可以在中途取消一個任務,只需要調用其 cancel 方法即可。

?

NSInvocationOperation: 需要傳入一個方法名。

?

OBJECTIVE-C

?

? //1.創建NSInvocationOperation對象

? NSInvocationOperation *operation =[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run)object:nil];

?

? //2.開始執行

? [operation start];

SWIFT

?

在 Swift 構建的和諧社會里,是容不下 NSInvocationOperation 這種不是類型安全的敗類的。蘋果如是說。這里有相關解釋

?

NSBlockOperation

?

OBJECTIVE-C

?

? //1.創建NSBlockOperation對象

? NSBlockOperation *operation =[NSBlockOperation blockOperationWithBlock:^{

????? NSLog(@"%@", [NSThreadcurrentThread]);

? }];

?

? //2.開始任務

? [operation start];

SWIFT

?

? //1.創建NSBlockOperation對象

? let operation = NSBlockOperation { () ->Void in

????? println(NSThread.currentThread())

? }

?

? //2.開始任務

? operation.start()

之前說過這樣的任務,默認會在當前線程執行。但是 NSBlockOperation 還有一個方法:addExecutionBlock: ,通過這個方法可以給 Operation 添加多個執行 Block。這樣 Operation 中的任務 會并發執行,它會 在主線程和其它的多個線程 執行這些任務,注意下面的打印結果:

?

OBJECTIVE-C

?

????? //1.創建NSBlockOperation對象

????? NSBlockOperation *operation =[NSBlockOperation blockOperationWithBlock:^{

????????? NSLog(@"%@", [NSThreadcurrentThread]);

????? }];

?

???? ?//添加多個Block

????? for (NSInteger i = 0; i < 5; i++) {

????????? [operation addExecutionBlock:^{

????????????? NSLog(@"第%ld次:%@", i, [NSThread currentThread]);

????????? }];

????? }

?

????? //2.開始任務

????? [operation start];

SWIFT

?

??????? //1.創建NSBlockOperation對象

??????? let operation = NSBlockOperation { ()-> Void in

??????????? NSLog("%@",NSThread.currentThread())

??????? }

?

??????? //2.添加多個Block

??????? for i in 0..<5 {

??????????? operation.addExecutionBlock { ()-> Void in

? ??????????????NSLog("第%ld次 - %@", i,NSThread.currentThread())

??????????? }

??????? }

?

??????? //2.開始任務

??????? operation.start()

打印輸出

?

2015-07-2817:50:16.585 test[17527:4095467] 第2次 - <NSThread: 0x7ff5c9701910>{number = 1, name = main}

?

2015-07-2817:50:16.585 test[17527:4095666] 第1次 - <NSThread: 0x7ff5c972caf0>{number = 4, name = (null)}

?

2015-07-2817:50:16.585 test[17527:4095665] <NSThread: 0x7ff5c961b610>{number = 3,name = (null)}

?

2015-07-2817:50:16.585 test[17527:4095662] 第0次 - <NSThread: 0x7ff5c948d310>{number = 2, name = (null)}

?

2015-07-2817:50:16.586 test[17527:4095666] 第3次 - <NSThread: 0x7ff5c972caf0>{number = 4, name = (null)}

?

2015-07-2817:50:16.586 test[17527:4095467] 第4次 - <NSThread: 0x7ff5c9701910>{number = 1, name = main}

?

?

NOTE:addExecutionBlock 方法必須在 start() 方法之前執行,否則就會報錯:

?

‘***-[NSBlockOperation addExecutionBlock:]: blocks cannot be added after theoperation has started executing or finished'

?

?

NOTE:大家可能發現了一個問題,為什么我在 Swift 里打印輸出使用 NSLog() 而不是 println() 呢?原因是使用 print() / println() 輸出的話,它會簡單地使用流(stream) 的概念,學過 C++ 的都知道。它會把需要輸出的每個字符一個一個的輸出到控制臺。普通使用并沒有問題,可是當多線程同步輸出的時候問題就來了,由于很多 println() 同時打印,就會導致控制臺上的字符混亂的堆在一起,而NSLog() 就沒有這個問題。到底是什么樣子的呢?你可以把上面 NSLog() 改為 println() ,然后一試便知。 更多 NSLog() 與 println() 的區別看這里

?

自定義Operation

?

除了上面的兩種 Operation以外,我們還可以自定義 Operation。自定義Operation 需要繼承 NSOperation 類,并實現其 main() 方法,因為在調用 start() 方法的時候,內部會調用 main() 方法完成相關邏輯。所以如果以上的兩個類無法滿足你的欲望的時候,你就需要自定義了。你想要實現什么功能都可以寫在里面。除此之外,你還需要實現 cancel() 在內的各種方法。所以這個功能提供給高級玩家,我在這里就不說了,等我需要用到時在研究它,到時候可能會再做更新。

?

創建隊列

?

看過上面的內容就知道,我們可以調用一個 NSOperation 對象的 start() 方法來啟動這個任務,但是這樣做他們默認是同步執行 的。就算是 addExecutionBlock 方法,也會在 當前線程和其他線程 中執行,也就是說還是會占用當前線程。這是就要用到隊列 NSOperationQueue 了。而且,按類型來說的話一共有兩種類型:主隊列、其他隊列。只要添加到隊列,會自動調用任務的 start() 方法

?

主隊列

?

細心的同學就會發現,每套多線程方案都會有一個主線程(當然啦,說的是iOS中,像 pthread 這種多系統的方案并沒有,因為 UI線程 理論需要每種操作系統自己定制)。這是一個特殊的線程,必須串行。所以添加到主隊列的任務都會一個接一個地排著隊在主線程處理。

?

//OBJECTIVE-C

NSOperationQueue*queue = [NSOperationQueue mainQueue];

?

//SWIFT

let queue= NSOperationQueue.mainQueue()

其他隊列

?

因為主隊列比較特殊,所以會單獨有一個類方法來獲得主隊列。那么通過初始化產生的隊列就是其他隊列了,因為只有這兩種隊列,除了主隊列,其他隊列就不需要名字了。

?

注意:其他隊列的任務會在其他線程并行執行。

?

OBJECTIVE-C

?

//1.創建一個其他隊列???

NSOperationQueue*queue = [[NSOperationQueue alloc] init];

?

//2.創建NSBlockOperation對象

NSBlockOperation*operation = [NSBlockOperation blockOperationWithBlock:^{

??? NSLog(@"%@", [NSThreadcurrentThread]);

}];

?

//3.添加多個Block

for(NSInteger i = 0; i < 5; i++) {

??? [operation addExecutionBlock:^{

??????? NSLog(@"第%ld次:%@", i, [NSThread currentThread]);

??? }];

}

?

//4.隊列添加任務

[queue addOperation:operation];

SWIFT

?

//1.創建其他隊列

let queue= NSOperationQueue()

?

//2.創建NSBlockOperation對象

letoperation = NSBlockOperation { () -> Void in

??? NSLog("%@",NSThread.currentThread())

}

?

//3.添加多個Block

for i in0..<5 {

??? operation.addExecutionBlock { () -> Voidin

??????? NSLog("第%ld次 - %@", i, NSThread.currentThread())

??? }

}

?

//4.隊列添加任務

queue.addOperation(operation)

打印輸出

?

2015-07-2820:26:28.463 test[18622:4443534] <NSThread: 0x7fd022c3ac10>{number = 5,name = (null)}

?

2015-07-2820:26:28.463 test[18622:4443536] 第2次 - <NSThread: 0x7fd022e36d50>{number = 2, name = (null)}

?

2015-07-2820:26:28.463 test[18622:4443535] 第0次 - <NSThread: 0x7fd022f237f0>{number = 4, name = (null)}

?

2015-07-2820:26:28.463 test[18622:4443533] 第1次 - <NSThread: 0x7fd022d372b0>{number = 3, name = (null)}

?

2015-07-2820:26:28.463 test[18622:4443534] 第3次 - <NSThread: 0x7fd022c3ac10>{number = 5, name = (null)}

?

2015-07-2820:26:28.463 test[18622:4443536] 第4次 - <NSThread: 0x7fd022e36d50>{number = 2, name = (null)}

OK, 這時應該發問了,大家將 NSOperationQueue 與 GCD的隊列 相比較就會發現,這里沒有串行隊列,那如果我想要10個任務在其他線程串行的執行怎么辦?

?

這就是蘋果封裝的妙處,你不用管串行、并行、同步、異步這些名詞。NSOperationQueue 有一個參數maxConcurrentOperationCount 最大并發數,用來設置最多可以讓多少個任務同時執行。當你把它設置為 1 的時候,他不就是串行了嘛!

?

NSOperationQueue還有一個添加任務的方法,- (void)addOperationWithBlock:(void(^)(void))block; ,這是不是和 GCD 差不多?這樣就可以添加一個任務到隊列中了,十分方便。

?

NSOperation有一個非常實用的功能,那就是添加依賴。比如有 3 個任務:A:從服務器上下載一張圖片,B:給這張圖片加個水印,C:把圖片返回給服務器。這時就可以用到依賴了:

?

OBJECTIVE-C

?

//1.任務一:下載圖片

NSBlockOperation*operation1 = [NSBlockOperation blockOperationWithBlock:^{

??? NSLog(@"下載圖片 -%@", [NSThread currentThread]);

??? [NSThread sleepForTimeInterval:1.0];

}];

?

//2.任務二:打水印

NSBlockOperation*operation2 = [NSBlockOperation blockOperationWithBlock:^{

??? NSLog(@"打水印?? - %@", [NSThread currentThread]);

??? [NSThread sleepForTimeInterval:1.0];

}];

?

//3.任務三:上傳圖片

NSBlockOperation*operation3 = [NSBlockOperation blockOperationWithBlock:^{

??? NSLog(@"上傳圖片 -%@", [NSThread currentThread]);

??? [NSThread sleepForTimeInterval:1.0];

}];

?

//4.設置依賴

[operation2addDependency:operation1];????? //任務二依賴任務一

[operation3addDependency:operation2];????? //任務三依賴任務二

?

//5.創建隊列并加入任務

NSOperationQueue*queue = [[NSOperationQueue alloc] init];

[queueaddOperations:@[operation3, operation2, operation1] waitUntilFinished:NO];

SWIFT

?

//1.任務一:下載圖片

letoperation1 = NSBlockOperation { () -> Void in

??? NSLog("下載圖片 -%@", NSThread.currentThread())

??? NSThread.sleepForTimeInterval(1.0)

}

?

//2.任務二:打水印

letoperation2 = NSBlockOperation { () -> Void in

??? NSLog("打水印?? - %@", NSThread.currentThread())

??? NSThread.sleepForTimeInterval(1.0)

}

?

//3.任務三:上傳圖片

letoperation3 = NSBlockOperation { () -> Void in

??? NSLog("上傳圖片 -%@", NSThread.currentThread())

??? NSThread.sleepForTimeInterval(1.0)

}

?

//4.設置依賴

operation2.addDependency(operation1)??? //任務二依賴任務一

operation3.addDependency(operation2)??? //任務三依賴任務二

?

//5.創建隊列并加入任務

let queue= NSOperationQueue()

queue.addOperations([operation3,operation2, operation1], waitUntilFinished: false)

打印結果

?

2015-07-2821:24:28.622 test[19392:4637517] 下載圖片 - <NSThread:0x7fc10ad4d970>{number = 2, name = (null)}

?

2015-07-2821:24:29.622 test[19392:4637515] 打水印 - <NSThread:0x7fc10af20ef0>{number = 3, name = (null)}

?

2015-07-2821:24:30.627 test[19392:4637515] 上傳圖片 - <NSThread:0x7fc10af20ef0>{number = 3, name = (null)}

注意:不能添加相互依賴,會死鎖,比如 A依賴B,B依賴A。

可以使用removeDependency 來解除依賴關系。

可以在不同的隊列之間依賴,反正就是這個依賴是添加到任務身上的,和隊列沒關系。

其他方法

?

以上就是一些主要方法, 下面還有一些常用方法需要大家注意:

?

NSOperation

?

BOOLexecuting; //判斷任務是否正在執行

?

BOOLfinished; //判斷任務是否完成

?

void(^completionBlock)(void); //用來設置完成后需要執行的操作

?

-(void)cancel; //取消任務

?

-(void)waitUntilFinished; //阻塞當前線程直到此任務執行完畢

NSOperationQueue

?

NSUIntegeroperationCount; //獲取隊列的任務數

?

-(void)cancelAllOperations; //取消隊列中所有的任務

?

-(void)waitUntilAllOperationsAreFinished; //阻塞當前線程直到此隊列中的所有任務執行完畢

?

[queuesetSuspended:YES]; // 暫停queue

?

[queuesetSuspended:NO]; // 繼續queue

好啦,到這里差不多就講完了。當然,我講的并不完整,可能有一些知識我并沒有講到,但作為常用方法,這些已經足夠了。不過我在這里只是告訴你了一些方法的功能,只是怎么把他們用到合適的地方,就需要多多實踐了。下面我會說一些關于多線程的案例,是大家更加什么地了解。

?

其他用法

?

在這部分,我會說一些和多線程知識相關的案例,可能有些很簡單,大家早都知道的,不過因為這篇文章講的是多線程嘛,所以應該盡可能的全面嘛。還有就是,我會盡可能的使用多種方法實現,讓大家看看其中的區別。

?

線程同步

?

所謂線程同步就是為了防止多個線程搶奪同一個資源造成的數據安全問題,所采取的一種措施。當然也有很多實現方法,請往下看:

?

互斥鎖 :給需要同步的代碼塊加一個互斥鎖,就可以保證每次只有一個線程訪問此代碼塊。

?

OBJECTIVE-C

?

@synchronized(self){

? //需要執行的代碼塊

}

SWIFT

?

objc_sync_enter(self)

//需要執行的代碼塊

objc_sync_exit(self)

同步執行 :我們可以使用多線程的知識,把多個線程都要執行此段代碼添加到同一個串行隊列,這樣就實現了線程同步的概念。當然這里可以使用 GCD 和 NSOperation 兩種方案,我都寫出來。

?

OBJECTIVE-C

?

?

//GCD

//需要一個全局變量queue,要讓所有線程的這個操作都加到一個queue中

dispatch_sync(queue,^{

??? NSInteger ticket = lastTicket;

??? [NSThread sleepForTimeInterval:0.1];

??? NSLog(@"%ld - %@",ticket,[NSThread currentThread]);

??? ticket -= 1;

??? lastTicket = ticket;

});

?

?

//NSOperation& NSOperationQueue

//重點:1. 全局的 NSOperationQueue, 所有的操作添加到同一個queue中

//?????? 2. 設置 queue 的maxConcurrentOperationCount 為 1

//?????? 3. 如果后續操作需要Block中的結果,就需要調用每個操作的waitUntilFinished,阻塞當前線程,一直等到當前操作完成,才允許執行后面的。waitUntilFinished 要在添加到隊列之后!

?

NSBlockOperation*operation = [NSBlockOperation blockOperationWithBlock:^{

??? NSInteger ticket = lastTicket;

??? [NSThread sleepForTimeInterval:1];

??? NSLog(@"%ld - %@",ticket,[NSThread currentThread]);

??? ticket -= 1;

??? lastTicket = ticket;

}];

?

[queueaddOperation:operation];

?

[operationwaitUntilFinished];

?

//后續要做的事

SWIFT

?

這里的 swift代碼,我就不寫了,因為每句都一樣,只是語法不同而已,照著 OC 的代碼就能寫出 Swift 的。這篇文章已經老長老長了,我就不浪費篇幅了,又不是高中寫作文。

?

延遲執行

?

所謂延遲執行就是延時一段時間再執行某段代碼。下面說一些常用方法。

?

perform

?

OBJECTIVE-C

?

// 3秒后自動調用self的run:方法,并且傳遞參數:@"abc"

[selfperformSelector:@selector(run:) withObject:@"abc" afterDelay:3];

SWIFT

?

之前就已經說過,Swift里去掉了這個方法。

GCD

?

可以使用 GCD 中的 dispatch_after 方法,OC 和 Swift 都可以使用,這里只寫 OC 的,Swift 的是一樣的。

?

OBJECTIVE-C

?

// 創建隊列

dispatch_queue_tqueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

// 設置延時,單位秒

doubledelay = 3;

?

dispatch_after(dispatch_time(DISPATCH_TIME_NOW,(int64_t)(delay * NSEC_PER_SEC)), queue, ^{

? // 3秒后需要執行的任務

});

NSTimer

?

NSTimer 是iOS中的一個計時器類,除了延遲執行還有很多用法,不過這里直說延遲執行的用法。同樣只寫OC 版的,Swift 也是相同的。

?

OBJECTIVE-C

?

[NSTimerscheduledTimerWithTimeInterval:3.0 target:self selector:@selector(run:)userInfo:@"abc" repeats:NO];

單例模式

?

至于什么是單例模式,我也不多說,我只說說一般怎么實現。在 Objective-C 中,實現單例的方法已經很具體了,雖然有別的方法,但是一般都是用一個標準的方法了,下面來看看。

?

OBJECTIVE-C

?

@interfaceTool : NSObject <NSCopying>

?

+(instancetype)sharedTool;

?

@end

?

@implementationTool

?

static id_instance;

?

+(instancetype)sharedTool {

??? static dispatch_once_t onceToken;

??? dispatch_once(&onceToken, ^{

??????? _instance = [[Tool alloc] init];

??? });

?

??? return _instance;

}

?

@end

這里之所以將單例模式,是因為其中用到了 GCD 的 dispatch_once 方法。下面看 Swift 中的單例模式,在Swift中單例模式非常簡單!想知道怎么從 OC 那么復雜的方法變成下面的寫法的,請看這里

?

SWIFT

?

classTool: NSObject {

??? static let sharedTool = Tool()

?

??? // 私有化構造方法,阻止其他對象使用這個類的默認的'()'構造方法

??? private override init() {}

}

從其他線程回到主線程的方法

?

我們都知道在其他線程操作完成后必須到主線程更新UI。所以,介紹完所有的多線程方案后,我們來看看有哪些方法可以回到主線程。

?

NSThread

?

//Objective-C

[selfperformSelectorOnMainThread:@selector(run) withObject:nil waitUntilDone:NO];

?

//Swift

//swift 取消了 performSelector 方法。

GCD

?

//Objective-C

dispatch_async(dispatch_get_main_queue(),^{

?

});

?

//Swift

dispatch_async(dispatch_get_main_queue(),{ () -> Void in

?

})

NSOperationQueue

?

//Objective-C

[[NSOperationQueuemainQueue] addOperationWithBlock:^{

?

}];

?

//Swift

NSOperationQueue.mainQueue().addOperationWithBlock{ () -> Void in

?

}

總結

?

好的吧,總算寫完了,純手敲6k多字,感動死我了。花了兩天,時間跨度有點大,所以可能有些地方上段不接下段或者有的地方不完整,如果你看著比較費力或者有什么地方有問題,都可以在評論區告訴我,我會及時修改的。當然啦,多線程的東西也不止這些,題目也就只是個題目,不要當真。想要了解更多的東西,還得自己去網上挖掘相關資料。多看看官方文檔。實在是編不下去了,大家好好看~。對了,看我寫的這么賣力,不打賞的話得點個喜歡也是極好的。

?

更新:第一次放出來的時候,有很多地方有錯誤,很感謝有朋友提出來了。如果你看到有錯誤的地方,一定記得指出來,這樣對大家都有幫助。還有一點對初學者來說,遇到不懂的方法,最好的辦法就是查看官方文檔,那里是最準確的,就算有幾個單詞不認識,查一下就好了,不會影響對整體的理解。

(5)????同步,異步定義以及iOS中是如何實現同步的

同步:進程之間的關系不是相互排斥臨界資源的關系,而是相互依賴的關系。進一步的說明:就是前一個進程的輸出作為后一個進程的輸入,當第一個進程沒有輸出時第二個進程必須等待。具有同步關系的一組并發進程相互發送的信息稱為消息或事件。

其中并發又有偽并發和真并發,偽并發是指單核處理器的并發,真并發是指多核處理器的并發。

異步:異步和同步是相對的,同步就是順序執行,執行完一個再執行下一個,需要等待、協調運行。異步就是彼此獨立,在等待某事件的過程中繼續做自己的事,不需要等待這一事件完成后再工作。線程就是實現異步的一個方式。異步是讓調用方法的主線程不需要同步等待另一線程的完成,從而可以讓主線程干其它的事情。

?? 異步和多線程并不是一個同等關系,異步是最終目的,多線程只是我們實現異步的一種手段。異步是當一個調用請求發送給被調用者,而調用者不用等待其結果的返回而可以做其它的事情。實現異步可以采用多線程技術或則交給另外的進程來處理。

在IOS中我們一般情況下使用以下三種線程同步代碼方式:

?

第一種和第二種代碼同步的使用方法,一般情況下我們只需要使用NSLock和NSCondition申明2個屬性。然后給此屬性賦對應的值。那么即可作為安全防控的線程手段。

?

同時也可以保證線程的資源安全。

?

1:NSLock方式

?

?

?

[xxxlocklock] //上鎖

?

同步代碼塊

?

[xxxlockunlock]//解鎖

?

?

?

2:NSCondition方式

?

[xxxConditionlock] //上鎖

?

同步代碼塊

?

[xxxConditionunlock]//解鎖

?

?

?

第三種方式:在使用synchronized的時候,括號中我們一般情況下只需要傳一個self即可。同步代碼塊 當有線程進去之后會把括號里面對象的鎖旗標鎖上,其他線程會在外面等著 當進去的線程出去的時候會把鎖打開其余線程再進一個。這樣才能保護線程放問資源的安全性。

?

3:@synchronized( 同一對象){

?

線程執行代碼;

?

}

?

?

?

線程資源防控示例代碼:

?

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

<spanstyle="font-size:10px;">-(void)sellTickets{

????

??? while (YES) {

??????? NSString *name = [NSThreadcurrentThread].name;

//?????? 同步代碼塊 當有線程進去之后會把括號里面對象的鎖旗標鎖上,其他線程會在外面等著當進去的線程出去的時候會把鎖打開 其余線程再進一個

//??????? @synchronized(self){

//??????? [self.myLock lock];

??????? [self.myCondition lock];

??????????? NSLog(@"%@開始賣%d號票",name,self.selledCount+1);

??????????? [NSThread sleepForTimeInterval:.2];

??????????? self.selledCount++;

??????????? NSLog(@"%@賣掉了%d號票,還剩%d張",name,self.selledCount,self.totalCount-self.selledCount);

//???????? [self.myLock unlock];

??????? [self.myCondition unlock];

?

??????? }

//??? }

????

}</span>

(6)????#import,#include,@class區別

1.

#include是C中用來引用文件的關鍵字,而#import是obj-c中用來代替include的關鍵字。#import可以確保同一個文件只能被導入一次,從而避免了使用#include容易引起的重復引用問題,即classA引用了classC,classB也引用了classC,而當classD同時引用classA,classB的時候就會報重復引用的錯誤。

?

2.

#import""與#import<>:#import""實現從當前工作目錄中找要導入的文件,如果沒有再到系統類庫中找,而#import<>是直接從系統類庫中找要導入的文件。

?

3.

#import與@class:

?

@class只是告訴編譯器,后面遇到的這個名稱是一個類名稱,至于這個類是如何實現的暫不用考慮。引入@class主要是用來解決引用死鎖--如果兩個類存在循環依賴關系,即A->B,B->A,如果用#import來相互包含,就會出現編譯錯誤:

Expectedspecifier-qualifier-list before ‘A’或者Expectedspecifier-qualifier-list before ‘B’。

?

一般情況下,在 .h文件中,只需要知道類的名字就可以了,所以用@class,而在 .m文件中通常需要知道類的成員變量即方法,所以要用#import來將類文件導進來。

?

那為什么不在 .h文件中直接用#import來將類文件導入呢,因為如果導入大量的頭文件,編譯器就會花大量的時間來編譯。

?

需要在 .h文件中用#import的情況:

1/如果有繼承關系的要用#import,如,A繼承B,需要在A中將B import進來。

2/使用有category的類,需要在 .h文件中用#import將該類的category導進來。

(7)????Ios中是否有多繼承,是如何實現的

我們都知道objectiveC不能像C++一樣支持多繼承,但是在OC的使用經常會碰到需要使用多繼承的情況。例如,ClassA中有methodA,ClassB中methodB,而現在需要使用這兩個類中的方法。如何按照C++的編程思路,毫無疑問采用多繼承就搞定了,在OC就需要動動腦子了。

?

??????? 其實我們在學習設計模式的時候知道,多繼承的效率不高,而且采用組合的模式可以完全代替繼承模式。那么,這種思路完全可以用在OC中實現多繼承(或許OC拋棄多繼承,就是強迫我們使用更高效的組合設計模式吧!)。下面用實際的代碼來表示組合如何來代替多繼承。

?

?????? 現在ClassC需要繼承ClassA中methodA、ClassB中methodB,具體的代碼實現為:

?

//定義ClassA以及其methodA

@interfaceClassA : NSObject {

}

?

-(void)methodA;

?

@end

//定義ClassB以及其methodB

@interfaceClassB : NSObject {

}

?

-(void)methodB;

?

@end

//定義ClassC以及其需要的methodA,methodB

@interfaceClassC : NSObject {

? ClassA *a;

? ClassB *b;

}

?

-(id)initWithA:(ClassA*)A b:(ClassB *)B;

?

-(void)methodA;

-(void)methodB;

?

@end

?

//注意在ClassC的實現

?

@implementation? ClassC

?

-(id)initWithA:(ClassA*)A b:(ClassB *)B{

?

?????? a=[[ClassA alloc] initWithClassA:A];//[A copy];

?

?????? b=[[ClassB alloc] initWithClassB:B];//[B copy];

}

?

-(void)methodA{

?

????? [a methodA];

}

-(void)methodB{

?

????? [b methodB];

}

?

上面是采用組合的方式實現了多繼承的功能,解決了OC不能多繼承的語法。那么還有其他的方式來實現多繼承嗎?

?

雖然OC在語法上禁止類使用多繼承,但是在協議的遵守上卻允許使用多繼承。所以可以用協議來實現多繼承。但是協議只能提供接口,而沒有提供實現方式,如果只是想多繼承基類的接口,那么遵守多協議無疑是最好的方法,而既需要多繼承接口,又要多繼承其實現,那么協議是無能為力了。多協議遵守比較簡單,具體的實現方式這里就不講了!

(8)????iOS中如何讓一個對象具有拷貝功能

若想令自己所寫的對象具有拷貝功能,則需實現 NSCopying 協議。如果自定義的對象分為可變版本與不可變版本,那么就要同時實現NSCopying與 NSMutableCopying協議。

?

具體步驟:

?

需聲明該類遵從NSCopying 協議

實現NSCopying 協議。該協議只有一個方法:

?- (id)copyWithZone:(NSZone *)zone;

注意:一提到讓自己的類用 copy 修飾符,我們總是想覆寫copy方法,其實真正需要實現的卻是 “copyWithZone” 方法。

?

至于如何重寫帶copy 關鍵字的 setter這個問題,

如果拋開本例來回答的話,如下:

?

-(void)setName:(NSString *)name {

??? //[_name release];

??? _name = [name copy];

}

?

(9)????單例的定義及實現

單例是全局的類實例,存放在全局內存里,不能以任何方式復制,也不會被釋放。實例化的對象始終指向同一塊內存。具體實現方式有兩種,線程鎖和GCD。代碼如下,如有錯誤歡迎大家批評指正:

線程鎖代碼:

static id_instance;

+ (User*)shareInstance {

??? @synchronized(self) {

??????? if (_instance == nil) {

??????????? _instance = [[User alloc] init];

??????? }

??? }

??? return _instance;

}

?

+(id)allocWithZone:(struct _NSZone *)zone {

??? @synchronized(self) {

??????? if (_instance == nil) {

??????????? _instance = [superallocWithZone:zone];

??????? }

??? }

??? return _instance;

}

?

-(id)copyWithZone:(NSZone *)zone? {

??? return _instance;

}

?

GCD代碼:

+(User*)shareInstance {

??? static dispatch_once_t onceToken;

??? dispatch_once(&onceToken, ^{

??????? //onceToken是GCD用來記錄是否執行過,如果已經執行過就不再執行(保證執行一次)

???? ???_instance = [[User alloc] init];

??? });

??? return _instance;

}

?

+(id)allocWithZone:(struct _NSZone *)zone {

??? static dispatch_once_t onceToken;

??? dispatch_once(&onceToken, ^{

??????? //onceToken是GCD用來記錄是否執行過,如果已經執行過就不再執行(保證執行一次)

??????? _instance = [super allocWithZone:zone];

??? });

??? return _instance;

}

?

-(id)copyWithZone:(NSZone *)zone? {

??? return _instance;

}

(10)? 定義一個標準宏MIN,實現返回輸入的兩個數中較小的數字

#define MIN(X,Y) ((X)>(Y)?(Y):(X))

define只會是純替換作用,所以X,Y均需要加括號,以防止X,Y為表達式的情況

(11)? 做過什么優化程序的工作(這個是面試題目,不是筆試題目。)

1. 用ARC管理內存

?

ARC(AutomaticReferenceCounting, 自動引用計數)和iOS5一起發布,它避免了最常見的也就是經常是由于我們忘記釋放內存所造成的內存泄露。它自動為你管理retain和release的過程,所以你就不必去手動干預了。忘掉代碼段結尾的release簡直像記得吃飯一樣簡單。而ARC會自動在底層為你做這些工作。除了幫你避免內存泄露,ARC還可以幫你提高性能,它能保證釋放掉不再需要的對象的內存。

?

現在所有的iOS程序都用ARC了,這條可以忽略。

?

?

?

2. 在正確的地方使用 reuseIdentifier

?

一個開發中常見的錯誤就是沒有給UITableViewCells, UICollectionViewCells,甚至是UITableViewHeaderFooterViews設置正確的reuseIdentifier。

?

為了性能最優化,tableview用tableView:cellForRowAtIndexPath:為rows分配cells的時候,它的數據應該重用自UITableViewCell。一個table view維持一個隊列的數據可重用的UITableViewCell對象。

?

不使用reuseIdentifier的話,每顯示一行table view就不得不設置全新的cell。這對性能的影響可是相當大的,尤其會使app的滾動體驗大打折扣。

?

自iOS6起,除了UICollectionView的cells和補充views,你也應該在header和footerviews中使用reuseIdentifiers。

?

想要使用reuseIdentifiers的話,在一個table view中添加一個新的cell時在data source object中添加這個方法:

?

[objc]view plain copy? 在CODE上查看代碼片派生到我的代碼片

staticNSString*CellIdentifier = @"Cell";?

UITableViewCell*cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifierforIndexPath:indexPath];?

這個方法把那些已經存在的cell從隊列中排除,或者在必要時使用先前注冊的nib或者class創造新的cell。如果沒有可重用的cell,你也沒有注冊一個class或者nib的話,這個方法返回nil。

?

?

?

3.盡量把views設置為透明

?

如果你有透明的Views你應該設置它們的opaque屬性為YES。

?

原因是這會使系統用一個最優的方式渲染這些views。這個簡單的屬性在IB或者代碼里都可以設定。

?

Apple的文檔對于為圖片設置透明屬性的描述是:

?

(opaque)這個屬性給渲染系統提供了一個如何處理這個view的提示。如果設為YES,渲染系統就認為這個view是完全不透明的,這使得渲染系統優化一些渲染過程和提高性能。如果設置為NO,渲染系統正常地和其它內容組成這個View。默認值是YES。

?

在相對比較靜止的畫面中,設置這個屬性不會有太大影響。然而當這個view嵌在scroll view里邊,或者是一個復雜動畫的一部分,不設置這個屬性的話會在很大程度上影響app的性能。

?

你可以在模擬器中用Debug\ColorBlended Layers選項來發現哪些view沒有被設置為opaque。目標就是,能設為opaque的就全設為opaque!

?

這里有一點需要注意,只要是有中文字符的Label,哪怕你設置成不透明,模擬器中這個Label依然會變紅,這個猜測是字符繪制的時候出的問題,這個目前沒找到好的解決方法。

?

?

?

4.避免過于龐大的XIB

?

iOS5中加入的Storyboards(分鏡)正在快速取代XIB。然而XIB在一些場景中仍然很有用。比如你的app需要適應iOS5之前的設備,或者你有一個自定義的可重用的view,你就不可避免地要用到他們。

?

如果你不得不XIB的話,使他們盡量簡單。嘗試為每個Controller配置一個單獨的XIB,盡可能把一個View Controller的view層次結構分散到單獨的XIB中去。

?

需要注意的是,當你加載一個XIB的時候所有內容都被放在了內存里,包括任何圖片。如果有一個不會即刻用到的view,你這就是在浪費寶貴的內存資源了。Storyboards就是另一碼事兒了,storyboard僅在需要時實例化一個view controller.

?

當家在XIB是,所有圖片都被chache,如果你在做OS X開發的話,聲音文件也是。Apple在相關文檔中的記述是:

?

當你加載一個引用了圖片或者聲音資源的nib時,nib加載代碼會把圖片和聲音文件寫進內存。在OS X中,圖片和聲音資源被緩存在named cache中以便將來用到時獲取。在iOS中,僅圖片資源會被存進named caches。取決于你所在的平臺,使用NSImage 或UIImage的imageNamed:方法來獲取圖片資源。

?

這個問題我深有體會,用xib寫的界面加載速度比直接用代碼寫的要慢好多。

?

?

?

5.不要阻塞主線程

?

永遠不要使主線程承擔過多。因為UIKit在主線程上做所有工作,渲染,管理觸摸反應,回應輸入等都需要在它上面完成。

?

一直使用主線程的風險就是如果你的代碼真的block了主線程,你的app會失去反應。

?

大部分阻礙主進程的情形是你的app在做一些牽涉到讀寫外部資源的I/O操作,比如存儲或者網絡。

?

你可以使用NSURLConnection異步地做網絡操作:

?

+(void)sendAsynchronousRequest:(NSURLRequest *)requestqueue:(NSOperationQueue*)queue completionHandler:(void (^)(NSURLResponse*, NSData*,NSError*))handler

?

或者使用像AFNetworking這樣的框架來異步地做這些操作。

?

如果你需要做其它類型的需要耗費巨大資源的操作(比如時間敏感的計算或者存儲讀寫)那就用Grand Central Dispatch,或者NSOperation和 NSOperationQueues.

?

下面代碼是使用GCD的模板

?

[objc]view plain copy? 在CODE上查看代碼片派生到我的代碼片

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{?

??? // switch to a background thread andperform your expensive operation?

??? dispatch_async(dispatch_get_main_queue(),^{?

??????? // switch back to the main thread toupdate your UI?

??? });?

});?

發現代碼中有一個嵌套的dispatch_async嗎?這是因為任何UIKit相關的代碼需要在主線程上進行。

?

?

?

6. 在Image Views中調整圖片大小

?

如果要在UIImageView中顯示一個來自bundle的圖片,你應保證圖片的大小和UIImageView的大小相同。在運行中縮放圖片是很耗費資源的,特別是UIImageView嵌套在UIScrollView中的情況下。

?

如果圖片是從遠端服務加載的你不能控制圖片大小,比如在下載前調整到合適大小的話,你可以在下載完成后,最好是用background thread,縮放一次,然后在UIImageView中使用縮放后的圖片。

?

?

?

7. 選擇正確的Collection

?

學會選擇對業務場景最合適的類或者對象是寫出能效高的代碼的基礎。當處理collections時這句話尤其正確。

?

一些常見collection的總結:

?

· Arrays:有序的一組值。使用index來lookup很快,使用value lookup很慢,插入/刪除很慢。

?

·Dictionaries: 存儲鍵值對。用鍵來查找比較快。

?

· Sets: 無序的一組值。用值來查找很快,插入/刪除很快。因為Set用到了哈希,所以插入刪除查找速度比Array快很多

?

?

?

8. 打開gzip壓縮

?

大量app依賴于遠端資源和第三方API,你可能會開發一個需要從遠端下載XML, JSON, HTML或者其它格式的app。

?

問題是我們的目標是移動設備,因此你就不能指望網絡狀況有多好。一個用戶現在還在edge網絡,下一分鐘可能就切換到了3G。不論什么場景,你肯定不想讓你的用戶等太長時間。

?

減小文檔的一個方式就是在服務端和你的app中打開gzip。這對于文字這種能有更高壓縮率的數據來說會有更顯著的效用。

?

好消息是,iOS已經在NSURLConnection中默認支持了gzip壓縮,當然AFNetworking這些基于它的框架亦然。像Google App Engine這些云服務提供者也已經支持了壓縮輸出。

?

?

?

9. 重用和延遲加載(lazy load) Views

?

更多的view意味著更多的渲染,也就是更多的CPU和內存消耗,對于那種嵌套了很多view在UIScrollView里邊的app更是如此。

?

這里我們用到的技巧就是模仿UITableView和UICollectionView的操作:不要一次創建所有的subview,而是當需要時才創建,當它們完成了使命,把他們放進一個可重用的隊列中。

?

這樣的話你就只需要在滾動發生時創建你的views,避免了不劃算的內存分配。

?

創建views的能效問題也適用于你app的其它方面。想象一下一個用戶點擊一個按鈕的時候需要呈現一個view的場景。有兩種實現方法:

?

1. 創建并隱藏這個view當這個screen加載的時候,當需要時顯示它;

?

2. 當需要時才創建并展示。

?

每個方案都有其優缺點。用第一種方案的話因為你需要一開始就創建一個view并保持它直到不再使用,這就會更加消耗內存。然而這也會使你的app操作更敏感因為當用戶點擊按鈕的時候它只需要改變一下這個view的可見性。

?

第二種方案則相反-消耗更少內存,但是會在點擊按鈕的時候比第一種稍顯卡頓。

?

?

?

10.Cache, Cache, 還是Cache!注意你的緩存

?

一個極好的原則就是,緩存所需要的,也就是那些不大可能改變但是需要經常讀取的東西。

?

我們能緩存些什么呢?一些選項是,遠端服務器的響應,圖片,甚至計算結果,比如UITableView的行高。

?

NSURLConnection默認會緩存資源在內存或者存儲中根據它所加載的HTTP Headers。你甚至可以手動創建一個NSURLRequest然后使它只加載緩存的值。

?

下面是一個可用的代碼段,你可以可以用它去為一個基本不會改變的圖片創建一個NSURLRequest并緩存它:

?

[objc]view plain copy? 在CODE上查看代碼片派生到我的代碼片

+(NSMutableURLRequest *)imageRequestWithURL:(NSURL *)url {?

NSMutableURLRequest*request = [NSMutableURLRequest requestWithURL:url];?

request.cachePolicy= NSURLRequestReturnCacheDataElseLoad;// this will make sure the request alwaysreturns the cached image?

request.HTTPShouldHandleCookies= NO;?

request.HTTPShouldUsePipelining= YES;?

[requestaddValue:@"image/*"forHTTPHeaderField:@"Accept"];?

returnrequest;?

}?

注意你可以通過NSURLConnection 獲取一個URL request, AFNetworking也一樣的。這樣你就不必為采用這條tip而改變所有的networking代碼了。

?

如果你需要緩存其它不是HTTP Request的東西,你可以用NSCache。

?

NSCache和NSDictionary類似,不同的是系統回收內存的時候它會自動刪掉它的內容。

?

?

?

11.權衡渲染方法

?

在iOS中可以有很多方法做出漂亮的按鈕。你可以用整幅的圖片,可調大小的圖片,或者可以用CALayer, CoreGraphics甚至OpenGL來畫它們。當然每個不同的解決方法都有不同的復雜程度和相應的性能。

?

簡單來說,就是用事先渲染好的圖片更快一些,因為如此一來iOS就免去了創建一個圖片再畫東西上去然后顯示在屏幕上的程序。問題是你需要把所有你需要用到的圖片放到app的bundle里面,這樣就增加了體積–這就是使用可變大小的圖片更好的地方了:你可以省去一些不必要的空間,也不需要再為不同的元素(比如按鈕)來做不同的圖。

?

然而,使用圖片也意味著你失去了使用代碼調整圖片的機動性,你需要一遍又一遍不斷地重做他們,這樣就很浪費時間了,而且你如果要做一個動畫效果,雖然每幅圖只是一些細節的變化你就需要很多的圖片造成bundle大小的不斷增大。

?

總得來說,你需要權衡一下利弊,到底是要性能能還是要bundle保持合適的大小。

?

?

?

12.處理內存警告

?

一旦系統內存過低,iOS會通知所有運行中app。在官方文檔中是這樣記述:

?

如果你的app收到了內存警告,它就需要盡可能釋放更多的內存。最佳方式是移除對緩存,圖片object和其他一些可以重創建的objects的strong references.

?

幸運的是,UIKit提供了幾種收集低內存警告的方法:

?

· 在app delegate中使用applicationDidReceiveMemoryWarning:的方法

?

· 在你的自定義UIViewController的子類(subclass)中覆蓋didReceiveMemoryWarning

?

· 注冊并接收 UIApplicationDidReceiveMemoryWarningNotification的通知

?

一旦收到這類通知,你就需要釋放任何不必要的內存使用。

?

例如,UIViewController的默認行為是移除一些不可見的view,它的一些子類則可以補充這個方法,刪掉一些額外的數據結構。一個有圖片緩存的app可以移除不在屏幕上顯示的圖片。

?

這樣對內存警報的處理是很必要的,若不重視,你的app就可能被系統殺掉。

?

然而,當你一定要確認你所選擇的object是可以被重現創建的來釋放內存。一定要在開發中用模擬器中的內存提醒模擬去測試一下。

?

當然,現在iOS設備運行內存越來越大,這一點很難出現了。

?

?

?

13.重用大開銷對象

?

一些objects的初始化很慢,比如NSDateFormatter和NSCalendar。然而,你又不可避免地需要使用它們,比如從JSON或者XML中解析數據。

?

想要避免使用這個對象的瓶頸你就需要重用他們,可以通過添加屬性到你的class里或者創建靜態變量來實現。

?

注意如果你要選擇第二種方法,對象會在你的app運行時一直存在于內存中,和單例(singleton)很相似。

?

下面的代碼說明了使用一個屬性來延遲加載一個date formatter. 第一次調用時它會創建一個新的實例,以后的調用則將返回已經創建的實例:

?

[objc]view plain copy? 在CODE上查看代碼片派生到我的代碼片

// inyour .h or inside a class extension?

@property(nonatomic, strong) NSDateFormatter *formatter;?

// insidethe implementation (.m)?

// Whenyou need, just use self.formatter?

-(NSDateFormatter *)formatter {?

??? if(!_formatter) {?

??????? _formatter = [[NSDateFormatter alloc]init];?

??????? _formatter.dateFormat = @"EEE MMMdd HH:mm:ss Z yyyy";// twitter date format?

??? }?

??? return _formatter;?

}?

還需要注意的是,其實設置一個NSDateFormatter的速度差不多是和創建新的一樣慢的!所以如果你的app需要經常進行日期格式處理的話,你會從這個方法中得到不小的性能提升。

?

?

?

14. 使用Sprite Sheets

?

Sprite sheet可以讓渲染速度加快,甚至比標準的屏幕渲染方法節省內存。

?

?

?

15.避免反復處理數據

?

許多應用需要從服務器加載功能所需的常為JSON或者XML格式的數據。在服務器端和客戶端使用相同的數據結構很重要。在內存中操作數據使它們滿足你的數據結構是開銷很大的。

?

比如你需要數據來展示一個table view,最好直接從服務器取array結構的數據以避免額外的中間數據結構改變。

?

類似的,如果需要從特定key中取數據,那么就使用鍵值對的dictionary。

?

這一點在處理大量數據的時候極為重要,用空間換時間的方法也許是極好的。

?

?

?

16.選擇正確的數據格式

?

從app和網絡服務間傳輸數據有很多方案,最常見的就是JSON和XML。你需要選擇對你的app來說最合適的一個。

?

解析JSON會比XML更快一些,JSON也通常更小更便于傳輸。從iOS5起有了官方內建的JSON deserialization就更加方便使用了。

?

但是XML也有XML的好處,比如使用SAX來解析XML就像解析本地文件一樣,你不需像解析json一樣等到整個文檔下載完成才開始解析。當你處理很大的數據的時候就會極大地減低內存消耗和增加性能。

?

現在基本上都是JSON了。

?

?

?

17.正確設定背景圖片

?

在View里放背景圖片就像很多其它iOS編程一樣有很多方法:

?

使用UIColor的 colorWithPatternImage來設置背景色;

?

在view中添加一個UIImageView作為一個子View。

?

如果你使用全畫幅的背景圖,你就必須使用UIImageView因為UIColor的colorWithPatternImage是用來創建小的重復的圖片作為背景的。這種情形下使用UIImageView可以節約不少的內存:

?

// Youcould also achieve the same result in Interface Builder

?

UIImageView*backgroundView = [[UIImageView alloc] initWithImage:[UIImageimageNamed:@"background"]];

?

[self.viewaddSubview:backgroundView];

?

如果你用小圖平鋪來創建背景,你就需要用UIColor的colorWithPatternImage來做了,它會更快地渲染也不會花費很多內存:

?

self.view.backgroundColor= [UIColor colorWithPatternImage:[UIImage imageNamed:@"background"]];

?

?

?

18. 減少使用Web特性

?

UIWebView很有用,用它來展示網頁內容或者創建UIKit很難做到的動畫效果是很簡單的一件事。

?

但是你可能有注意到UIWebView并不像驅動Safari的那么快。這是由于以JIT compilation為特色的Webkit的Nitro Engine的限制。

?

所以想要更高的性能你就要調整下你的HTML了。第一件要做的事就是盡可能移除不必要的JavaScript,避免使用過大的框架。能只用原生js就更好了。

?

另外,盡可能異步加載例如用戶行為統計script這種不影響頁面表達的javascript。

?

最后,永遠要注意你使用的圖片,保證圖片的符合你使用的大小。使用Sprite sheet提高加載速度和節約內存。

?

?

?

19. 設定Shadow Path

?

如何在一個View或者一個layer上加一個shadow呢,QuartzCore框架是很多開發者的選擇:

?

[objc]view plain copy? 在CODE上查看代碼片派生到我的代碼片

UIView*view = [[UIView alloc] init];?

view.layer.shadowOffset= CGSizeMake(-1.0f, 1.0f);?

view.layer.shadowRadius= 5.0f;?

view.layer.shadowOpacity= 0.6;?

看起來很簡單,對吧。可是,壞消息是使用這個方法也有它的問題… Core Animation不得不先在后臺得出你的圖形并加好陰影然后才渲染,這開銷是很大的。

?

使用shadowPath的話就避免了這個問題:

?

view.layer.shadowPath= [[UIBezierPath bezierPathWithRect:view.bounds] CGPath];

?

使用shadowpath的話iOS就不必每次都計算如何渲染,它使用一個預先計算好的路徑。但問題是自己計算path的話可能在某些View中比較困難,且每當view的frame變化的時候你都需要去updateshadow path.

?

我更喜歡用CALayer自己畫一個陰影出來,這樣可以設置陰影光柵化,節省大量CPU的運算,壞處就是比較消耗內存。因為如果給view的layer設置光柵化的話整個View都會變得模糊。

?

?

?

20. 優化Table View

?

Tableview需要有很好的滾動性能,不然用戶會在滾動過程中發現動畫的瑕疵。

?

為了保證tableview平滑滾動,確保你采取了以下的措施:

?

· 正確使用reuseIdentifier來重用cells

?

· 盡量使所有的view opaque,包括cell自身

?

· 避免漸變,圖片縮放,后臺選人

?

· 緩存行高

?

· 如果cell內現實的內容來自web,使用異步加載,緩存請求結果

?

· 使用shadowPath來畫陰影

?

· 減少subviews的數量

?

· 盡量不使用cellForRowAtIndexPath:,如果你需要用到它,只用一次然后緩存結果

?

· 使用正確的數據結構來存儲數據

?

· 使用rowHeight, sectionFooterHeight和sectionHeaderHeight來設定固定的高,不要請求delegate

?

?

?

21.選擇正確的數據存儲選項

?

當存儲大塊數據時你會怎么做?

?

你有很多選擇,比如:

?

· 使用NSUerDefaults

?

· 使用XML, JSON, 或者 plist

?

· 使用NSCoding存檔

?

· 使用類似SQLite的本地SQL數據庫

?

· 使用 Core Data

?

NSUserDefaults的問題是什么?雖然它很nice也很便捷,但是它只適用于小數據,比如一些簡單的布爾型的設置選項,再大點你就要考慮其它方式了

?

XML這種結構化檔案呢?總體來說,你需要讀取整個文件到內存里去解析,這樣是很不經濟的。使用SAX又是一個很麻煩的事情。

?

NSCoding?不幸的是,它也需要讀寫文件,所以也有以上問題。

?

在這種應用場景下,使用SQLite 或者 Core Data比較好。使用這些技術你用特定的查詢語句就能只加載你需要的對象。

?

在性能層面來講,SQLite和Core Data是很相似的。他們的不同在于具體使用方法。Core Data代表一個對象的graph model,但SQLite就是一個DBMS。Apple在一般情況下建議使用CoreData,但是如果你有理由不使用它,那么就去使用更加底層的SQLite吧。

?

如果你使用SQLite,你可以用FMDB(https://GitHub.com/ccgus/fmdb)這個庫來簡化SQLite的操作,這樣你就不用花很多經歷了解SQLite的C API了。

?

?

?

23. 使用Autorelease Pool

?

NSAutoreleasePool負責釋放block中的autoreleased objects。一般情況下它會自動被UIKit調用。但是有些狀況下你也需要手動去創建它。

?

假如你創建很多臨時對象,你會發現內存一直在減少直到這些對象被release的時候。這是因為只有當UIKit用光了autorelease pool的時候memory才會被釋放。好消息是你可以在你自己的@autoreleasepool里創建臨時的對象來避免這個行為:

?

[objc]view plain copy? 在CODE上查看代碼片派生到我的代碼片

NSArray*urls = <# An array of file URLs #>;?

?? for(NSURL *url in urls) {?

??? @autoreleasepool {?

?????? NSError *error;?

?????? NSString *fileContents = [NSStringstringWithContentsOfURL:url encoding:NSUTF8StringEncodingerror:&error];?

?????? /* Process the string, creating andautoreleasing more objects. */??

??? }?

?? }?

這段代碼在每次遍歷后釋放所有autorelease對象

?

?

?

24. 選擇是否緩存圖片

?

常見的從bundle中加載圖片的方式有兩種,一個是用imageNamed,二是用imageWithContentsOfFile,第一種比較常見一點。

?

既然有兩種類似的方法來實現相同的目的,那么他們之間的差別是什么呢?

?

imageNamed的優點是當加載時會緩存圖片。imageNamed的文檔中這么說:這個方法用一個指定的名字在系統緩存中查找并返回一個圖片對象如果它存在的話。如果緩存中沒有找到相應的圖片,這個方法從指定的文檔中加載然后緩存并返回這個對象。

?

相反的,imageWithContentsOfFile僅加載圖片。

?

下面的代碼說明了這兩種方法的用法:

?

UIImage*img = [UIImage imageNamed:@"myImage"];// caching

?

// or

?

UIImage*img = [UIImage imageWithContentsOfFile:@"myImage"];// no caching

?

那么我們應該如何選擇呢?

?

如果你要加載一個大圖片而且是一次性使用,那么就沒必要緩存這個圖片,用imageWithContentsOfFile足矣,這樣不會浪費內存來緩存它。

?

然而,在圖片反復重用的情況下imageNamed是一個好得多的選擇。

?

?

?

25. 避免日期格式轉換

?

如果你要用NSDateFormatter來處理很多日期格式,應該小心以待。就像先前提到的,任何時候重用NSDateFormatters都是一個好的實踐。

?

然而,如果你需要更多速度,那么直接用C是一個好的方案。Sam Soffes有一個不錯的帖子(http://soff.es/how-to-drastically-improve-your-app-with-an-afternoon-and-instruments)里面有一些可以用來解析ISO-8601日期字符串的代碼,簡單重寫一下就可以拿來用了。

?

嗯,直接用C來搞,看起來不錯了,但是你相信嗎,我們還有更好的方案!

?

如果你可以控制你所處理的日期格式,盡量選擇Unix時間戳。你可以方便地從時間戳轉換到NSDate:

?

-(NSDate*)dateFromUnixTimestamp:(NSTimeInterval)timestamp {

?

return[NSDatedateWithTimeIntervalSince1970:timestamp];

?

}

?

這樣會比用C來解析日期字符串還快!需要注意的是,許多web API會以微秒的形式返回時間戳,因為這種格式在javascript中更方便使用。記住用dateFromUnixTimestamp之前除以1000就好了。

?

?

?

轉載至:http://blog.csdn.net/youshaoduo/article/details/53841078

?

1. 用ARC管理內存

?

ARC(AutomaticReferenceCounting, 自動引用計數)和iOS5一起發布,它避免了最常見的也就是經常是由于我們忘記釋放內存所造成的內存泄露。它自動為你管理retain和release的過程,所以你就不必去手動干預了。忘掉代碼段結尾的release簡直像記得吃飯一樣簡單。而ARC會自動在底層為你做這些工作。除了幫你避免內存泄露,ARC還可以幫你提高性能,它能保證釋放掉不再需要的對象的內存。

?

現在所有的iOS程序都用ARC了,這條可以忽略。

?

?

?

2. 在正確的地方使用 reuseIdentifier

?

一個開發中常見的錯誤就是沒有給UITableViewCells, UICollectionViewCells,甚至是UITableViewHeaderFooterViews設置正確的reuseIdentifier。

?

為了性能最優化,tableview用tableView:cellForRowAtIndexPath:為rows分配cells的時候,它的數據應該重用自UITableViewCell。一個table view維持一個隊列的數據可重用的UITableViewCell對象。

?

不使用reuseIdentifier的話,每顯示一行table view就不得不設置全新的cell。這對性能的影響可是相當大的,尤其會使app的滾動體驗大打折扣。

?

自iOS6起,除了UICollectionView的cells和補充views,你也應該在header和footerviews中使用reuseIdentifiers。

?

想要使用reuseIdentifiers的話,在一個table view中添加一個新的cell時在data source object中添加這個方法:

?

[objc]view plain copy? 在CODE上查看代碼片派生到我的代碼片

staticNSString*CellIdentifier = @"Cell";?

UITableViewCell*cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifierforIndexPath:indexPath];?

這個方法把那些已經存在的cell從隊列中排除,或者在必要時使用先前注冊的nib或者class創造新的cell。如果沒有可重用的cell,你也沒有注冊一個class或者nib的話,這個方法返回nil。

?

?

?

3.盡量把views設置為透明

?

如果你有透明的Views你應該設置它們的opaque屬性為YES。

?

原因是這會使系統用一個最優的方式渲染這些views。這個簡單的屬性在IB或者代碼里都可以設定。

?

Apple的文檔對于為圖片設置透明屬性的描述是:

?

(opaque)這個屬性給渲染系統提供了一個如何處理這個view的提示。如果設為YES,渲染系統就認為這個view是完全不透明的,這使得渲染系統優化一些渲染過程和提高性能。如果設置為NO,渲染系統正常地和其它內容組成這個View。默認值是YES。

?

在相對比較靜止的畫面中,設置這個屬性不會有太大影響。然而當這個view嵌在scroll view里邊,或者是一個復雜動畫的一部分,不設置這個屬性的話會在很大程度上影響app的性能。

?

你可以在模擬器中用Debug\ColorBlended Layers選項來發現哪些view沒有被設置為opaque。目標就是,能設為opaque的就全設為opaque!

?

這里有一點需要注意,只要是有中文字符的Label,哪怕你設置成不透明,模擬器中這個Label依然會變紅,這個猜測是字符繪制的時候出的問題,這個目前沒找到好的解決方法。

?

?

?

4.避免過于龐大的XIB

?

iOS5中加入的Storyboards(分鏡)正在快速取代XIB。然而XIB在一些場景中仍然很有用。比如你的app需要適應iOS5之前的設備,或者你有一個自定義的可重用的view,你就不可避免地要用到他們。

?

如果你不得不XIB的話,使他們盡量簡單。嘗試為每個Controller配置一個單獨的XIB,盡可能把一個View Controller的view層次結構分散到單獨的XIB中去。

?

需要注意的是,當你加載一個XIB的時候所有內容都被放在了內存里,包括任何圖片。如果有一個不會即刻用到的view,你這就是在浪費寶貴的內存資源了。Storyboards就是另一碼事兒了,storyboard僅在需要時實例化一個view controller.

?

當家在XIB是,所有圖片都被chache,如果你在做OS X開發的話,聲音文件也是。Apple在相關文檔中的記述是:

?

當你加載一個引用了圖片或者聲音資源的nib時,nib加載代碼會把圖片和聲音文件寫進內存。在OS X中,圖片和聲音資源被緩存在named cache中以便將來用到時獲取。在iOS中,僅圖片資源會被存進named caches。取決于你所在的平臺,使用NSImage 或UIImage的imageNamed:方法來獲取圖片資源。

?

這個問題我深有體會,用xib寫的界面加載速度比直接用代碼寫的要慢好多。

?

?

?

5.不要阻塞主線程

?

永遠不要使主線程承擔過多。因為UIKit在主線程上做所有工作,渲染,管理觸摸反應,回應輸入等都需要在它上面完成。

?

一直使用主線程的風險就是如果你的代碼真的block了主線程,你的app會失去反應。

?

大部分阻礙主進程的情形是你的app在做一些牽涉到讀寫外部資源的I/O操作,比如存儲或者網絡。

?

你可以使用NSURLConnection異步地做網絡操作:

?

+(void)sendAsynchronousRequest:(NSURLRequest *)requestqueue:(NSOperationQueue*)queue completionHandler:(void (^)(NSURLResponse*,NSData*, NSError*))handler

?

或者使用像AFNetworking這樣的框架來異步地做這些操作。

?

如果你需要做其它類型的需要耗費巨大資源的操作(比如時間敏感的計算或者存儲讀寫)那就用Grand Central Dispatch,或者NSOperation和 NSOperationQueues.

?

下面代碼是使用GCD的模板

?

[objc]view plain copy? 在CODE上查看代碼片派生到我的代碼片

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{?

??? // switch to a background thread andperform your expensive operation?

??? dispatch_async(dispatch_get_main_queue(),^{?

??? ????// switch back to the main thread to updateyour UI?

??? });?

});?

發現代碼中有一個嵌套的dispatch_async嗎?這是因為任何UIKit相關的代碼需要在主線程上進行。

?

?

?

6. 在Image Views中調整圖片大小

?

如果要在UIImageView中顯示一個來自bundle的圖片,你應保證圖片的大小和UIImageView的大小相同。在運行中縮放圖片是很耗費資源的,特別是UIImageView嵌套在UIScrollView中的情況下。

?

如果圖片是從遠端服務加載的你不能控制圖片大小,比如在下載前調整到合適大小的話,你可以在下載完成后,最好是用background thread,縮放一次,然后在UIImageView中使用縮放后的圖片。

?

?

?

7. 選擇正確的Collection

?

學會選擇對業務場景最合適的類或者對象是寫出能效高的代碼的基礎。當處理collections時這句話尤其正確。

?

一些常見collection的總結:

?

· Arrays:有序的一組值。使用index來lookup很快,使用value lookup很慢,插入/刪除很慢。

?

·Dictionaries: 存儲鍵值對。用鍵來查找比較快。

?

· Sets: 無序的一組值。用值來查找很快,插入/刪除很快。因為Set用到了哈希,所以插入刪除查找速度比Array快很多

?

?

?

8. 打開gzip壓縮

?

大量app依賴于遠端資源和第三方API,你可能會開發一個需要從遠端下載XML, JSON, HTML或者其它格式的app。

?

問題是我們的目標是移動設備,因此你就不能指望網絡狀況有多好。一個用戶現在還在edge網絡,下一分鐘可能就切換到了3G。不論什么場景,你肯定不想讓你的用戶等太長時間。

?

減小文檔的一個方式就是在服務端和你的app中打開gzip。這對于文字這種能有更高壓縮率的數據來說會有更顯著的效用。

?

好消息是,iOS已經在NSURLConnection中默認支持了gzip壓縮,當然AFNetworking這些基于它的框架亦然。像Google App Engine這些云服務提供者也已經支持了壓縮輸出。

?

?

?

9. 重用和延遲加載(lazy load) Views

?

更多的view意味著更多的渲染,也就是更多的CPU和內存消耗,對于那種嵌套了很多view在UIScrollView里邊的app更是如此。

?

這里我們用到的技巧就是模仿UITableView和UICollectionView的操作:不要一次創建所有的subview,而是當需要時才創建,當它們完成了使命,把他們放進一個可重用的隊列中。

?

這樣的話你就只需要在滾動發生時創建你的views,避免了不劃算的內存分配。

?

創建views的能效問題也適用于你app的其它方面。想象一下一個用戶點擊一個按鈕的時候需要呈現一個view的場景。有兩種實現方法:

?

1. 創建并隱藏這個view當這個screen加載的時候,當需要時顯示它;

?

2. 當需要時才創建并展示。

?

每個方案都有其優缺點。用第一種方案的話因為你需要一開始就創建一個view并保持它直到不再使用,這就會更加消耗內存。然而這也會使你的app操作更敏感因為當用戶點擊按鈕的時候它只需要改變一下這個view的可見性。

?

第二種方案則相反-消耗更少內存,但是會在點擊按鈕的時候比第一種稍顯卡頓。

?

?

?

10.Cache, Cache, 還是Cache!注意你的緩存

?

一個極好的原則就是,緩存所需要的,也就是那些不大可能改變但是需要經常讀取的東西。

?

我們能緩存些什么呢?一些選項是,遠端服務器的響應,圖片,甚至計算結果,比如UITableView的行高。

?

NSURLConnection默認會緩存資源在內存或者存儲中根據它所加載的HTTP Headers。你甚至可以手動創建一個NSURLRequest然后使它只加載緩存的值。

?

下面是一個可用的代碼段,你可以可以用它去為一個基本不會改變的圖片創建一個NSURLRequest并緩存它:

?

[objc]view plain copy? 在CODE上查看代碼片派生到我的代碼片

+(NSMutableURLRequest *)imageRequestWithURL:(NSURL *)url {?

NSMutableURLRequest*request = [NSMutableURLRequest requestWithURL:url];?

request.cachePolicy= NSURLRequestReturnCacheDataElseLoad;// this will make sure the request alwaysreturns the cached image?

request.HTTPShouldHandleCookies= NO;?

request.HTTPShouldUsePipelining= YES;?

[requestaddValue:@"image/*"forHTTPHeaderField:@"Accept"];?

returnrequest;?

}?

注意你可以通過NSURLConnection 獲取一個URL request, AFNetworking也一樣的。這樣你就不必為采用這條tip而改變所有的networking代碼了。

?

如果你需要緩存其它不是HTTP Request的東西,你可以用NSCache。

?

NSCache和NSDictionary類似,不同的是系統回收內存的時候它會自動刪掉它的內容。

?

?

?

11.權衡渲染方法

?

在iOS中可以有很多方法做出漂亮的按鈕。你可以用整幅的圖片,可調大小的圖片,或者可以用CALayer, CoreGraphics甚至OpenGL來畫它們。當然每個不同的解決方法都有不同的復雜程度和相應的性能。

?

簡單來說,就是用事先渲染好的圖片更快一些,因為如此一來iOS就免去了創建一個圖片再畫東西上去然后顯示在屏幕上的程序。問題是你需要把所有你需要用到的圖片放到app的bundle里面,這樣就增加了體積–這就是使用可變大小的圖片更好的地方了:你可以省去一些不必要的空間,也不需要再為不同的元素(比如按鈕)來做不同的圖。

?

然而,使用圖片也意味著你失去了使用代碼調整圖片的機動性,你需要一遍又一遍不斷地重做他們,這樣就很浪費時間了,而且你如果要做一個動畫效果,雖然每幅圖只是一些細節的變化你就需要很多的圖片造成bundle大小的不斷增大。

?

總得來說,你需要權衡一下利弊,到底是要性能能還是要bundle保持合適的大小。

?

?

?

12.處理內存警告

?

一旦系統內存過低,iOS會通知所有運行中app。在官方文檔中是這樣記述:

?

如果你的app收到了內存警告,它就需要盡可能釋放更多的內存。最佳方式是移除對緩存,圖片object和其他一些可以重創建的objects的strong references.

?

幸運的是,UIKit提供了幾種收集低內存警告的方法:

?

· 在app delegate中使用applicationDidReceiveMemoryWarning:的方法

?

· 在你的自定義UIViewController的子類(subclass)中覆蓋didReceiveMemoryWarning

?

· 注冊并接收 UIApplicationDidReceiveMemoryWarningNotification的通知

?

一旦收到這類通知,你就需要釋放任何不必要的內存使用。

?

例如,UIViewController的默認行為是移除一些不可見的view,它的一些子類則可以補充這個方法,刪掉一些額外的數據結構。一個有圖片緩存的app可以移除不在屏幕上顯示的圖片。

?

這樣對內存警報的處理是很必要的,若不重視,你的app就可能被系統殺掉。

?

然而,當你一定要確認你所選擇的object是可以被重現創建的來釋放內存。一定要在開發中用模擬器中的內存提醒模擬去測試一下。

?

當然,現在iOS設備運行內存越來越大,這一點很難出現了。

?

?

?

13.重用大開銷對象

?

一些objects的初始化很慢,比如NSDateFormatter和NSCalendar。然而,你又不可避免地需要使用它們,比如從JSON或者XML中解析數據。

?

想要避免使用這個對象的瓶頸你就需要重用他們,可以通過添加屬性到你的class里或者創建靜態變量來實現。

?

注意如果你要選擇第二種方法,對象會在你的app運行時一直存在于內存中,和單例(singleton)很相似。

?

下面的代碼說明了使用一個屬性來延遲加載一個date formatter. 第一次調用時它會創建一個新的實例,以后的調用則將返回已經創建的實例:

?

[objc]view plain copy? 在CODE上查看代碼片派生到我的代碼片

// inyour .h or inside a class extension?

@property(nonatomic, strong) NSDateFormatter *formatter;?

// insidethe implementation (.m)?

// Whenyou need, just use self.formatter?

-(NSDateFormatter *)formatter {?

??? if(!_formatter) {?

??????? _formatter = [[NSDateFormatter alloc]init];?

??????? _formatter.dateFormat = @"EEE MMMdd HH:mm:ss Z yyyy";// twitter date format?

??? }?

??? return _formatter;?

}?

還需要注意的是,其實設置一個NSDateFormatter的速度差不多是和創建新的一樣慢的!所以如果你的app需要經常進行日期格式處理的話,你會從這個方法中得到不小的性能提升。

?

?

?

14. 使用Sprite Sheets

?

Spritesheet可以讓渲染速度加快,甚至比標準的屏幕渲染方法節省內存。

?

?

?

15.避免反復處理數據

?

許多應用需要從服務器加載功能所需的常為JSON或者XML格式的數據。在服務器端和客戶端使用相同的數據結構很重要。在內存中操作數據使它們滿足你的數據結構是開銷很大的。

?

比如你需要數據來展示一個table view,最好直接從服務器取array結構的數據以避免額外的中間數據結構改變。

?

類似的,如果需要從特定key中取數據,那么就使用鍵值對的dictionary。

?

這一點在處理大量數據的時候極為重要,用空間換時間的方法也許是極好的。

?

?

?

16.選擇正確的數據格式

?

從app和網絡服務間傳輸數據有很多方案,最常見的就是JSON和XML。你需要選擇對你的app來說最合適的一個。

?

解析JSON會比XML更快一些,JSON也通常更小更便于傳輸。從iOS5起有了官方內建的JSON deserialization就更加方便使用了。

?

但是XML也有XML的好處,比如使用SAX來解析XML就像解析本地文件一樣,你不需像解析json一樣等到整個文檔下載完成才開始解析。當你處理很大的數據的時候就會極大地減低內存消耗和增加性能。

?

現在基本上都是JSON了。

?

?

?

17.正確設定背景圖片

?

在View里放背景圖片就像很多其它iOS編程一樣有很多方法:

?

使用UIColor的 colorWithPatternImage來設置背景色;

?

在view中添加一個UIImageView作為一個子View。

?

如果你使用全畫幅的背景圖,你就必須使用UIImageView因為UIColor的colorWithPatternImage是用來創建小的重復的圖片作為背景的。這種情形下使用UIImageView可以節約不少的內存:

?

// Youcould also achieve the same result in Interface Builder

?

UIImageView*backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"background"]];

?

[self.viewaddSubview:backgroundView];

?

如果你用小圖平鋪來創建背景,你就需要用UIColor的colorWithPatternImage來做了,它會更快地渲染也不會花費很多內存:

?

self.view.backgroundColor= [UIColor colorWithPatternImage:[UIImage imageNamed:@"background"]];

?

?

?

18. 減少使用Web特性

?

UIWebView很有用,用它來展示網頁內容或者創建UIKit很難做到的動畫效果是很簡單的一件事。

?

但是你可能有注意到UIWebView并不像驅動Safari的那么快。這是由于以JIT compilation為特色的Webkit的Nitro Engine的限制。

?

所以想要更高的性能你就要調整下你的HTML了。第一件要做的事就是盡可能移除不必要的JavaScript,避免使用過大的框架。能只用原生js就更好了。

?

另外,盡可能異步加載例如用戶行為統計script這種不影響頁面表達的javascript。

?

最后,永遠要注意你使用的圖片,保證圖片的符合你使用的大小。使用Sprite sheet提高加載速度和節約內存。

?

?

?

19. 設定Shadow Path

?

如何在一個View或者一個layer上加一個shadow呢,QuartzCore框架是很多開發者的選擇:

?

[objc]view plain copy? 在CODE上查看代碼片派生到我的代碼片

UIView*view = [[UIView alloc] init];?

view.layer.shadowOffset= CGSizeMake(-1.0f, 1.0f);?

view.layer.shadowRadius= 5.0f;?

view.layer.shadowOpacity= 0.6;?

看起來很簡單,對吧。可是,壞消息是使用這個方法也有它的問題… Core Animation不得不先在后臺得出你的圖形并加好陰影然后才渲染,這開銷是很大的。

?

使用shadowPath的話就避免了這個問題:

?

view.layer.shadowPath= [[UIBezierPath bezierPathWithRect:view.bounds] CGPath];

?

使用shadowpath的話iOS就不必每次都計算如何渲染,它使用一個預先計算好的路徑。但問題是自己計算path的話可能在某些View中比較困難,且每當view的frame變化的時候你都需要去updateshadow path.

?

我更喜歡用CALayer自己畫一個陰影出來,這樣可以設置陰影光柵化,節省大量CPU的運算,壞處就是比較消耗內存。因為如果給view的layer設置光柵化的話整個View都會變得模糊。

?

?

?

20. 優化Table View

?

Table view需要有很好的滾動性能,不然用戶會在滾動過程中發現動畫的瑕疵。

?

為了保證tableview平滑滾動,確保你采取了以下的措施:

?

· 正確使用reuseIdentifier來重用cells

?

· 盡量使所有的view opaque,包括cell自身

?

· 避免漸變,圖片縮放,后臺選人

?

· 緩存行高

?

· 如果cell內現實的內容來自web,使用異步加載,緩存請求結果

?

· 使用shadowPath來畫陰影

?

· 減少subviews的數量

?

· 盡量不使用cellForRowAtIndexPath:,如果你需要用到它,只用一次然后緩存結果

?

· 使用正確的數據結構來存儲數據

?

· 使用rowHeight, sectionFooterHeight和sectionHeaderHeight來設定固定的高,不要請求delegate

?

?

?

21.選擇正確的數據存儲選項

?

當存儲大塊數據時你會怎么做?

?

你有很多選擇,比如:

?

· 使用NSUerDefaults

?

· 使用XML, JSON, 或者 plist

?

· 使用NSCoding存檔

?

· 使用類似SQLite的本地SQL數據庫

?

· 使用Core Data

?

NSUserDefaults的問題是什么?雖然它很nice也很便捷,但是它只適用于小數據,比如一些簡單的布爾型的設置選項,再大點你就要考慮其它方式了

?

XML這種結構化檔案呢?總體來說,你需要讀取整個文件到內存里去解析,這樣是很不經濟的。使用SAX又是一個很麻煩的事情。

?

NSCoding?不幸的是,它也需要讀寫文件,所以也有以上問題。

?

在這種應用場景下,使用SQLite 或者 Core Data比較好。使用這些技術你用特定的查詢語句就能只加載你需要的對象。

?

在性能層面來講,SQLite和Core Data是很相似的。他們的不同在于具體使用方法。Core Data代表一個對象的graph model,但SQLite就是一個DBMS。Apple在一般情況下建議使用CoreData,但是如果你有理由不使用它,那么就去使用更加底層的SQLite吧。

?

如果你使用SQLite,你可以用FMDB(https://GitHub.com/ccgus/fmdb)這個庫來簡化SQLite的操作,這樣你就不用花很多經歷了解SQLite的C API了。

?

?

?

23. 使用Autorelease Pool

?

NSAutoreleasePool負責釋放block中的autoreleased objects。一般情況下它會自動被UIKit調用。但是有些狀況下你也需要手動去創建它。

?

假如你創建很多臨時對象,你會發現內存一直在減少直到這些對象被release的時候。這是因為只有當UIKit用光了autorelease pool的時候memory才會被釋放。好消息是你可以在你自己的@autoreleasepool里創建臨時的對象來避免這個行為:

?

[objc]view plain copy? 在CODE上查看代碼片派生到我的代碼片

NSArray*urls = <# An array of file URLs #>;?

?? for(NSURL *url in urls) {?

??? @autoreleasepool {?

?????? NSError *error;?

?????? NSString *fileContents = [NSStringstringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];?

?????? /* Process the string, creating andautoreleasing more objects. */??

??? }?

?? }?

這段代碼在每次遍歷后釋放所有autorelease對象

?

?

?

24. 選擇是否緩存圖片

?

常見的從bundle中加載圖片的方式有兩種,一個是用imageNamed,二是用imageWithContentsOfFile,第一種比較常見一點。

?

既然有兩種類似的方法來實現相同的目的,那么他們之間的差別是什么呢?

?

imageNamed的優點是當加載時會緩存圖片。imageNamed的文檔中這么說:這個方法用一個指定的名字在系統緩存中查找并返回一個圖片對象如果它存在的話。如果緩存中沒有找到相應的圖片,這個方法從指定的文檔中加載然后緩存并返回這個對象。

?

相反的,imageWithContentsOfFile僅加載圖片。

?

下面的代碼說明了這兩種方法的用法:

?

UIImage*img = [UIImage imageNamed:@"myImage"];// caching

?

// or

?

UIImage*img = [UIImage imageWithContentsOfFile:@"myImage"];// no caching

?

那么我們應該如何選擇呢?

?

如果你要加載一個大圖片而且是一次性使用,那么就沒必要緩存這個圖片,用imageWithContentsOfFile足矣,這樣不會浪費內存來緩存它。

?

然而,在圖片反復重用的情況下imageNamed是一個好得多的選擇。

?

?

?

25. 避免日期格式轉換

?

如果你要用NSDateFormatter來處理很多日期格式,應該小心以待。就像先前提到的,任何時候重用NSDateFormatters都是一個好的實踐。

?

然而,如果你需要更多速度,那么直接用C是一個好的方案。Sam Soffes有一個不錯的帖子(http://soff.es/how-to-drastically-improve-your-app-with-an-afternoon-and-instruments)里面有一些可以用來解析ISO-8601日期字符串的代碼,簡單重寫一下就可以拿來用了。

?

嗯,直接用C來搞,看起來不錯了,但是你相信嗎,我們還有更好的方案!

?

如果你可以控制你所處理的日期格式,盡量選擇Unix時間戳。你可以方便地從時間戳轉換到NSDate:

?

-(NSDate*)dateFromUnixTimestamp:(NSTimeInterval)timestamp {

?

return[NSDatedateWithTimeIntervalSince1970:timestamp];

?

}

?

這樣會比用C來解析日期字符串還快!需要注意的是,許多web API會以微秒的形式返回時間戳,因為這種格式在javascript中更方便使用。記住用dateFromUnixTimestamp之前除以1000就好了。

(12)? “https:www|.baidu.com”輸出|前后兩部分的字符串

根據字符串中的某個字符(A)來分割字符串

//3.分隔字符串

NSString*string =@"sdfsfsfsAdfsdf";

???

NSArray*array = [string componentsSeparatedByString:@"A"]; //從字符A中分隔成2個元素的數組

NSLog(@"array:%@",array); //結果是adfsfsfs和dfsdf

?

總結

以上是生活随笔為你收集整理的iOS面试题目及答案总结的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

亚洲乱码日产精品bd | 台湾无码一区二区 | 成 人 免费观看网站 | 成人精品天堂一区二区三区 | 免费观看的无遮挡av | 国产激情综合五月久久 | 欧美日韩一区二区三区自拍 | 无码av中文字幕免费放 | 国产成人一区二区三区在线观看 | 国产精品久久久久9999小说 | 精品少妇爆乳无码av无码专区 | 欧美第一黄网免费网站 | 亚洲毛片av日韩av无码 | 精品一区二区三区无码免费视频 | 青草视频在线播放 | 2019nv天堂香蕉在线观看 | 日韩欧美中文字幕在线三区 | 国产疯狂伦交大片 | 国产精品亚洲五月天高清 | 国精品人妻无码一区二区三区蜜柚 | 久久综合狠狠综合久久综合88 | 性色欲网站人妻丰满中文久久不卡 | 76少妇精品导航 | 日本va欧美va欧美va精品 | 无套内射视频囯产 | 午夜性刺激在线视频免费 | 俄罗斯老熟妇色xxxx | 欧美xxxx黑人又粗又长 | 国产午夜福利亚洲第一 | 国产精品毛片一区二区 | 十八禁视频网站在线观看 | 亚洲日韩精品欧美一区二区 | 正在播放老肥熟妇露脸 | 亚洲中文字幕在线无码一区二区 | 无码人中文字幕 | 久久无码人妻影院 | 色婷婷香蕉在线一区二区 | 狂野欧美激情性xxxx | 色 综合 欧美 亚洲 国产 | 波多野结衣高清一区二区三区 | 亚洲无人区午夜福利码高清完整版 | 久久国产精品二国产精品 | 香蕉久久久久久av成人 | 窝窝午夜理论片影院 | 岛国片人妻三上悠亚 | 亚洲乱亚洲乱妇50p | 大乳丰满人妻中文字幕日本 | 又大又黄又粗又爽的免费视频 | 久久综合网欧美色妞网 | 国产性生交xxxxx无码 | 丰腴饱满的极品熟妇 | 国产精品人妻一区二区三区四 | 狠狠躁日日躁夜夜躁2020 | 内射爽无广熟女亚洲 | 日韩精品无码一区二区中文字幕 | 国产区女主播在线观看 | 午夜肉伦伦影院 | 亚洲国产高清在线观看视频 | 牛和人交xxxx欧美 | 大乳丰满人妻中文字幕日本 | 麻豆精产国品 | 日本熟妇乱子伦xxxx | 午夜理论片yy44880影院 | 午夜福利一区二区三区在线观看 | 中文字幕av日韩精品一区二区 | 欧美变态另类xxxx | 国产精品永久免费视频 | 欧洲vodafone精品性 | 国产精品久久久久久无码 | 亚洲熟妇色xxxxx欧美老妇 | 国产人妻大战黑人第1集 | 色一情一乱一伦一区二区三欧美 | 99麻豆久久久国产精品免费 | 国产精品久久福利网站 | 欧美熟妇另类久久久久久不卡 | 亚洲午夜无码久久 | 亚洲欧美精品伊人久久 | 5858s亚洲色大成网站www | 国产农村妇女aaaaa视频 撕开奶罩揉吮奶头视频 | 欧美日韩亚洲国产精品 | 国产深夜福利视频在线 | 无码人妻精品一区二区三区不卡 | 久久综合九色综合97网 | 最新国产乱人伦偷精品免费网站 | 亚洲中文字幕无码中文字在线 | 夜夜躁日日躁狠狠久久av | 亚洲欧美日韩综合久久久 | 狠狠亚洲超碰狼人久久 | 乱码午夜-极国产极内射 | 国内揄拍国内精品人妻 | 中文字幕无线码免费人妻 | 九九热爱视频精品 | 中文无码成人免费视频在线观看 | 玩弄人妻少妇500系列视频 | 国产精品无码久久av | 国产午夜无码精品免费看 | 亚洲一区二区三区含羞草 | 98国产精品综合一区二区三区 | 久久aⅴ免费观看 | 久久综合给合久久狠狠狠97色 | ass日本丰满熟妇pics | 精品无码国产自产拍在线观看蜜 | 亚洲人成人无码网www国产 | 少妇高潮喷潮久久久影院 | 日本一区二区三区免费播放 | 99久久久无码国产aaa精品 | 精品国产一区二区三区av 性色 | 在线观看国产午夜福利片 | 成人免费无码大片a毛片 | 动漫av网站免费观看 | 国产黄在线观看免费观看不卡 | 波多野结衣 黑人 | 黑人玩弄人妻中文在线 | 国产偷国产偷精品高清尤物 | 少妇久久久久久人妻无码 | 狠狠亚洲超碰狼人久久 | 欧美人与禽猛交狂配 | 国产无av码在线观看 | 日韩视频 中文字幕 视频一区 | 亚洲综合精品香蕉久久网 | 国产亚洲精品久久久久久大师 | 日本爽爽爽爽爽爽在线观看免 | 国产av无码专区亚洲a∨毛片 | 亚洲中文字幕无码中文字在线 | 日本熟妇大屁股人妻 | 玩弄少妇高潮ⅹxxxyw | 日本精品久久久久中文字幕 | 日本一区二区更新不卡 | 色综合视频一区二区三区 | 亚洲精品久久久久久久久久久 | 成人欧美一区二区三区 | 亚洲一区二区三区香蕉 | 影音先锋中文字幕无码 | 狂野欧美激情性xxxx | 欧美丰满熟妇xxxx性ppx人交 | 天天躁夜夜躁狠狠是什么心态 | 97精品国产97久久久久久免费 | 久久精品国产大片免费观看 | 鲁大师影院在线观看 | 国产激情艳情在线看视频 | 欧美日韩一区二区三区自拍 | 99精品久久毛片a片 | 国产人妻精品一区二区三区 | 亚洲精品www久久久 | 乱人伦中文视频在线观看 | 国内精品人妻无码久久久影院蜜桃 | 人妻互换免费中文字幕 | 欧美丰满少妇xxxx性 | 在线观看国产一区二区三区 | 在线播放无码字幕亚洲 | 一本久久伊人热热精品中文字幕 | 午夜免费福利小电影 | 成人亚洲精品久久久久 | 国产香蕉尹人视频在线 | 成在人线av无码免观看麻豆 | 日韩精品乱码av一区二区 | 蜜桃av抽搐高潮一区二区 | 狂野欧美性猛交免费视频 | 台湾无码一区二区 | 久久精品一区二区三区四区 | 乱码午夜-极国产极内射 | 久久久www成人免费毛片 | 亚洲中文字幕av在天堂 | 中文字幕 人妻熟女 | 免费中文字幕日韩欧美 | 天天爽夜夜爽夜夜爽 | 天堂亚洲免费视频 | 日本饥渴人妻欲求不满 | 老熟妇乱子伦牲交视频 | 激情内射日本一区二区三区 | 久久熟妇人妻午夜寂寞影院 | 日本乱人伦片中文三区 | 九月婷婷人人澡人人添人人爽 | 日韩精品a片一区二区三区妖精 | 日本肉体xxxx裸交 | 欧洲精品码一区二区三区免费看 | 国产av无码专区亚洲a∨毛片 | 亚洲精品国产品国语在线观看 | 国内综合精品午夜久久资源 | 国产又粗又硬又大爽黄老大爷视 | 亚洲成在人网站无码天堂 | 国产超级va在线观看视频 | 成人片黄网站色大片免费观看 | 麻豆精品国产精华精华液好用吗 | 国产成人精品一区二区在线小狼 | 午夜熟女插插xx免费视频 | 国内精品九九久久久精品 | 国产婷婷色一区二区三区在线 | 一本久道久久综合婷婷五月 | av在线亚洲欧洲日产一区二区 | 欧美 日韩 亚洲 在线 | 奇米影视7777久久精品人人爽 | 性做久久久久久久久 | 久久久中文字幕日本无吗 | 又紧又大又爽精品一区二区 | 亚洲国产精品久久久久久 | 又大又紧又粉嫩18p少妇 | 麻豆果冻传媒2021精品传媒一区下载 | 最新版天堂资源中文官网 | 中文字幕无码日韩欧毛 | 国产又爽又猛又粗的视频a片 | 夜夜高潮次次欢爽av女 | 四虎国产精品一区二区 | 日韩av激情在线观看 | 帮老师解开蕾丝奶罩吸乳网站 | 亚洲熟妇色xxxxx欧美老妇y | 国产97色在线 | 免 | 亚洲の无码国产の无码影院 | 大地资源中文第3页 | 国产乱人伦av在线无码 | 欧美黑人巨大xxxxx | 日日噜噜噜噜夜夜爽亚洲精品 | 天天综合网天天综合色 | 鲁鲁鲁爽爽爽在线视频观看 | 国产成人av免费观看 | 99久久久无码国产精品免费 | a片免费视频在线观看 | 在线a亚洲视频播放在线观看 | 久久久国产精品无码免费专区 | 久久人人爽人人人人片 | 国产人妻人伦精品 | 国产乱人无码伦av在线a | 国产一区二区三区四区五区加勒比 | 国产精品毛片一区二区 | 久久无码中文字幕免费影院蜜桃 | 爆乳一区二区三区无码 | 真人与拘做受免费视频 | 国产精品久久久久7777 | 九一九色国产 | 精品无码国产自产拍在线观看蜜 | 在线天堂新版最新版在线8 | 色综合久久久无码网中文 | 久久精品国产日本波多野结衣 | 国产精品理论片在线观看 | 国产美女精品一区二区三区 | 乱人伦中文视频在线观看 | 九九热爱视频精品 | 国产精品igao视频网 | 一区二区三区乱码在线 | 欧洲 | 亚洲精品午夜国产va久久成人 | 99er热精品视频 | 国产午夜精品一区二区三区嫩草 | 77777熟女视频在线观看 а天堂中文在线官网 | 国产精品无码久久av | 久久久久成人片免费观看蜜芽 | 久久精品国产99精品亚洲 | 亚洲色无码一区二区三区 | 日本熟妇大屁股人妻 | 国产精品.xx视频.xxtv | 精品日本一区二区三区在线观看 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 亚洲色大成网站www国产 | 老头边吃奶边弄进去呻吟 | 超碰97人人做人人爱少妇 | 精品成人av一区二区三区 | 亚洲无人区午夜福利码高清完整版 | 久久久久se色偷偷亚洲精品av | 中国女人内谢69xxxxxa片 | 国産精品久久久久久久 | 丰满人妻翻云覆雨呻吟视频 | 乱码午夜-极国产极内射 | 国内少妇偷人精品视频免费 | 熟妇人妻激情偷爽文 | 欧美国产日韩亚洲中文 | 成人免费无码大片a毛片 | 日日摸夜夜摸狠狠摸婷婷 | aa片在线观看视频在线播放 | 国内精品九九久久久精品 | 国产精品办公室沙发 | 欧洲熟妇色 欧美 | 国产精品99久久精品爆乳 | 国产偷自视频区视频 | 色窝窝无码一区二区三区色欲 | а√天堂www在线天堂小说 | 福利一区二区三区视频在线观看 | 十八禁视频网站在线观看 | 少妇无码av无码专区在线观看 | 纯爱无遮挡h肉动漫在线播放 | 亚洲日韩av一区二区三区中文 | 内射巨臀欧美在线视频 | 国产成人精品视频ⅴa片软件竹菊 | 久久午夜无码鲁丝片午夜精品 | 窝窝午夜理论片影院 | 久久久久久国产精品无码下载 | 欧美野外疯狂做受xxxx高潮 | 中文字幕av伊人av无码av | 人人妻人人澡人人爽欧美一区 | 亚洲男女内射在线播放 | 国产 精品 自在自线 | 色欲久久久天天天综合网精品 | 婷婷五月综合缴情在线视频 | 婷婷丁香六月激情综合啪 | 一本色道久久综合狠狠躁 | 国产三级精品三级男人的天堂 | 日本一卡二卡不卡视频查询 | 色综合久久久久综合一本到桃花网 | 天天综合网天天综合色 | 欧美性生交活xxxxxdddd | 狂野欧美性猛交免费视频 | 亚洲欧美日韩成人高清在线一区 | 2020久久香蕉国产线看观看 | 久久亚洲中文字幕无码 | 亚洲精品成人福利网站 | 亚洲色大成网站www国产 | 亚洲国产日韩a在线播放 | 最近免费中文字幕中文高清百度 | 高清无码午夜福利视频 | 成人一在线视频日韩国产 | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 欧美丰满熟妇xxxx性ppx人交 | 色婷婷综合激情综在线播放 | 日韩精品乱码av一区二区 | 丰满人妻一区二区三区免费视频 | 国产艳妇av在线观看果冻传媒 | 久久久国产精品无码免费专区 | 欧美成人午夜精品久久久 | 131美女爱做视频 | 97久久国产亚洲精品超碰热 | 午夜性刺激在线视频免费 | 日本一卡2卡3卡四卡精品网站 | 成人精品视频一区二区三区尤物 | 婷婷丁香五月天综合东京热 | 伊人久久大香线蕉av一区二区 | 久久人人爽人人爽人人片ⅴ | 鲁鲁鲁爽爽爽在线视频观看 | 亚洲爆乳无码专区 | 老熟妇仑乱视频一区二区 | 青青青爽视频在线观看 | 伊人色综合久久天天小片 | a在线观看免费网站大全 | 国产suv精品一区二区五 | 国产精品久久久久久久9999 | 欧美丰满熟妇xxxx性ppx人交 | 狠狠躁日日躁夜夜躁2020 | 嫩b人妻精品一区二区三区 | 国产又粗又硬又大爽黄老大爷视 | 色噜噜亚洲男人的天堂 | 国产一精品一av一免费 | 奇米影视7777久久精品 | 熟妇人妻无乱码中文字幕 | 国产福利视频一区二区 | 精品人妻人人做人人爽 | 骚片av蜜桃精品一区 | 久久99国产综合精品 | 日本xxxx色视频在线观看免费 | 99久久无码一区人妻 | 免费无码av一区二区 | 成人精品视频一区二区三区尤物 | 亚洲自偷精品视频自拍 | 中文字幕av日韩精品一区二区 | 国产网红无码精品视频 | 无遮挡国产高潮视频免费观看 | 97夜夜澡人人爽人人喊中国片 | 午夜性刺激在线视频免费 | 色老头在线一区二区三区 | 亚洲一区av无码专区在线观看 | 国产午夜福利亚洲第一 | 少妇高潮一区二区三区99 | 中文亚洲成a人片在线观看 | 国内丰满熟女出轨videos | 日日橹狠狠爱欧美视频 | 伊人久久大香线蕉午夜 | 亚洲成色在线综合网站 | 亚洲精品综合一区二区三区在线 | av无码不卡在线观看免费 | 精品国产精品久久一区免费式 | 波多野结衣一区二区三区av免费 | 好爽又高潮了毛片免费下载 | 欧美性生交活xxxxxdddd | 国产精品多人p群无码 | 男女爱爱好爽视频免费看 | 久久亚洲中文字幕无码 | 波多野结衣高清一区二区三区 | 久久亚洲日韩精品一区二区三区 | 久久久婷婷五月亚洲97号色 | av无码久久久久不卡免费网站 | 欧美日韩亚洲国产精品 | 精品国产一区av天美传媒 | 久久精品国产日本波多野结衣 | 精品人妻人人做人人爽夜夜爽 | 国产精品毛片一区二区 | 成人一区二区免费视频 | 婷婷丁香五月天综合东京热 | 亚洲日本va中文字幕 | 伊人久久大香线蕉午夜 | 国产卡一卡二卡三 | 亚洲国产精品久久人人爱 | 午夜福利一区二区三区在线观看 | 人妻体内射精一区二区三四 | 国产九九九九九九九a片 | 婷婷丁香六月激情综合啪 | 久久天天躁狠狠躁夜夜免费观看 | 亚洲色在线无码国产精品不卡 | 色综合久久88色综合天天 | 国产精品人人妻人人爽 | 性做久久久久久久久 | 国产色xx群视频射精 | 少妇无码av无码专区在线观看 | av在线亚洲欧洲日产一区二区 | 99精品国产综合久久久久五月天 | 成熟人妻av无码专区 | 国产三级久久久精品麻豆三级 | 久久天天躁夜夜躁狠狠 | 波多野结衣av一区二区全免费观看 | 丰满少妇人妻久久久久久 | www国产亚洲精品久久网站 | 国产亚洲精品久久久久久国模美 | 又大又硬又黄的免费视频 | 日韩精品乱码av一区二区 | 九月婷婷人人澡人人添人人爽 | 夜精品a片一区二区三区无码白浆 | 久久亚洲精品成人无码 | а天堂中文在线官网 | 国产精品18久久久久久麻辣 | 亚洲 a v无 码免 费 成 人 a v | 国产成人av免费观看 | 久久人人爽人人爽人人片av高清 | 2020久久超碰国产精品最新 | 内射巨臀欧美在线视频 | 人妻少妇精品无码专区二区 | 午夜精品久久久内射近拍高清 | 国产亚洲欧美日韩亚洲中文色 | 少妇无码一区二区二三区 | 欧美成人午夜精品久久久 | 国产又爽又黄又刺激的视频 | 九九久久精品国产免费看小说 | 国产亚洲精品久久久闺蜜 | 特黄特色大片免费播放器图片 | 激情内射日本一区二区三区 | 国产农村乱对白刺激视频 | 欧美 日韩 亚洲 在线 | 人人妻人人澡人人爽欧美一区 | 中文字幕人妻丝袜二区 | 亚洲国产av精品一区二区蜜芽 | 狠狠色噜噜狠狠狠狠7777米奇 | 日韩少妇内射免费播放 | 夫妻免费无码v看片 | 久久久中文久久久无码 | а天堂中文在线官网 | 欧美熟妇另类久久久久久不卡 | 九九综合va免费看 | 精品厕所偷拍各类美女tp嘘嘘 | 国产极品视觉盛宴 | 无码吃奶揉捏奶头高潮视频 | 高清不卡一区二区三区 | 久久综合狠狠综合久久综合88 | 亚洲狠狠色丁香婷婷综合 | 久久精品国产亚洲精品 | 欧美高清在线精品一区 | 全球成人中文在线 | 国产av久久久久精东av | 真人与拘做受免费视频 | 成人无码视频免费播放 | 波多野结衣高清一区二区三区 | 亚洲欧洲日本无在线码 | 欧美阿v高清资源不卡在线播放 | 清纯唯美经典一区二区 | 99久久久国产精品无码免费 | 青青草原综合久久大伊人精品 | 波多野结衣av在线观看 | 最新国产麻豆aⅴ精品无码 | 欧美35页视频在线观看 | 亚洲精品久久久久久久久久久 | 国产一区二区三区精品视频 | 乌克兰少妇xxxx做受 | 最新国产乱人伦偷精品免费网站 | 国产亚av手机在线观看 | 一个人免费观看的www视频 | 麻豆果冻传媒2021精品传媒一区下载 | 51国偷自产一区二区三区 | 国产成人精品久久亚洲高清不卡 | 国精产品一品二品国精品69xx | 搡女人真爽免费视频大全 | 无码人妻精品一区二区三区下载 | 精品无码一区二区三区的天堂 | 男人和女人高潮免费网站 | 国产精品久久久久9999小说 | 久久综合激激的五月天 | 特黄特色大片免费播放器图片 | 国产亚av手机在线观看 | 亚洲精品无码人妻无码 | 国产高清不卡无码视频 | 黑人大群体交免费视频 | 熟妇人妻无码xxx视频 | 99精品视频在线观看免费 | 国产亚洲精品久久久ai换 | 国产精华av午夜在线观看 | 色欲综合久久中文字幕网 | 中文字幕av日韩精品一区二区 | 熟妇人妻激情偷爽文 | 粉嫩少妇内射浓精videos | 福利一区二区三区视频在线观看 | 在线 国产 欧美 亚洲 天堂 | 蜜臀aⅴ国产精品久久久国产老师 | 亚洲欧美精品aaaaaa片 | 国内揄拍国内精品少妇国语 | 天堂亚洲2017在线观看 | 日韩人妻无码一区二区三区久久99 | 欧美第一黄网免费网站 | 激情五月综合色婷婷一区二区 | 欧美日本日韩 | 精品无码国产一区二区三区av | 国产高潮视频在线观看 | 久久久精品成人免费观看 | 国产午夜手机精彩视频 | 国产精品人人爽人人做我的可爱 | а天堂中文在线官网 | 动漫av网站免费观看 | 伊在人天堂亚洲香蕉精品区 | 欧美 日韩 人妻 高清 中文 | 欧美熟妇另类久久久久久多毛 | 久久天天躁夜夜躁狠狠 | 一本久道久久综合狠狠爱 | 日产精品高潮呻吟av久久 | 亚洲欧美国产精品专区久久 | 99久久人妻精品免费二区 | 成人三级无码视频在线观看 | 亚洲国产欧美在线成人 | 伊人久久大香线蕉av一区二区 | 国产内射爽爽大片视频社区在线 | 欧美性生交活xxxxxdddd | 99麻豆久久久国产精品免费 | 午夜精品久久久久久久 | 在线精品亚洲一区二区 | 综合网日日天干夜夜久久 | 无码人妻av免费一区二区三区 | 搡女人真爽免费视频大全 | 亚洲区小说区激情区图片区 | 亚洲欧洲无卡二区视頻 | 国产无遮挡又黄又爽免费视频 | 欧美熟妇另类久久久久久不卡 | 久久久精品欧美一区二区免费 | 夜夜躁日日躁狠狠久久av | 久久久久久久久蜜桃 | 国产av一区二区精品久久凹凸 | 红桃av一区二区三区在线无码av | 四虎永久在线精品免费网址 | 亚洲色大成网站www国产 | 亚洲色欲久久久综合网东京热 | 色噜噜亚洲男人的天堂 | 久久亚洲日韩精品一区二区三区 | 日本免费一区二区三区最新 | 少妇性荡欲午夜性开放视频剧场 | 国产 浪潮av性色四虎 | 少妇被粗大的猛进出69影院 | 大乳丰满人妻中文字幕日本 | 综合激情五月综合激情五月激情1 | 97无码免费人妻超级碰碰夜夜 | 精品无码国产一区二区三区av | 成人欧美一区二区三区黑人 | 久久aⅴ免费观看 | av小次郎收藏 | 国产精品美女久久久久av爽李琼 | 日韩无套无码精品 | 中文字幕乱码中文乱码51精品 | 国产97色在线 | 免 | 国产在线精品一区二区高清不卡 | 久久午夜夜伦鲁鲁片无码免费 | 婷婷五月综合缴情在线视频 | 亚洲色在线无码国产精品不卡 | 国产精品内射视频免费 | 亚洲乱码国产乱码精品精 | 天天做天天爱天天爽综合网 | 国产成人精品久久亚洲高清不卡 | 久久精品视频在线看15 | 黑人玩弄人妻中文在线 | 久久精品99久久香蕉国产色戒 | 国产亚洲美女精品久久久2020 | 秋霞成人午夜鲁丝一区二区三区 | 人妻少妇精品无码专区二区 | 亚洲日本一区二区三区在线 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 亚洲国产成人av在线观看 | 熟女少妇在线视频播放 | 无码精品人妻一区二区三区av | 麻豆精品国产精华精华液好用吗 | √8天堂资源地址中文在线 | 国产精品亚洲а∨无码播放麻豆 | 精品国产精品久久一区免费式 | 中文字幕人妻无码一夲道 | 人妻aⅴ无码一区二区三区 | 免费看少妇作爱视频 | 久久精品无码一区二区三区 | 黄网在线观看免费网站 | 精品国产青草久久久久福利 | 人妻少妇被猛烈进入中文字幕 | 中文字幕乱妇无码av在线 | 99er热精品视频 | 天堂亚洲免费视频 | 免费看男女做好爽好硬视频 | 青青久在线视频免费观看 | 女人高潮内射99精品 | 少妇愉情理伦片bd | 欧美日本精品一区二区三区 | 亚洲日韩精品欧美一区二区 | 亚洲小说春色综合另类 | 人人妻人人澡人人爽欧美一区 | 亚洲s色大片在线观看 | 日韩欧美成人免费观看 | 国产精品.xx视频.xxtv | 亚洲精品中文字幕久久久久 | 欧美成人免费全部网站 | 精品无人国产偷自产在线 | 国产高清av在线播放 | 久久久久人妻一区精品色欧美 | 丰满少妇熟乱xxxxx视频 | 国产av无码专区亚洲a∨毛片 | 一本一道久久综合久久 | 成人精品天堂一区二区三区 | 牛和人交xxxx欧美 | 2020久久超碰国产精品最新 | 国产午夜福利100集发布 | 强奷人妻日本中文字幕 | 爽爽影院免费观看 | 亚洲色欲色欲天天天www | 亚洲欧美综合区丁香五月小说 | 美女黄网站人色视频免费国产 | 老熟女重囗味hdxx69 | 亚洲国产欧美日韩精品一区二区三区 | 狠狠综合久久久久综合网 | 麻豆果冻传媒2021精品传媒一区下载 | 欧美freesex黑人又粗又大 | 国产亚洲日韩欧美另类第八页 | 综合网日日天干夜夜久久 | 色窝窝无码一区二区三区色欲 | 欧美成人午夜精品久久久 | 少妇性l交大片欧洲热妇乱xxx | 国产人妻大战黑人第1集 | 乱人伦人妻中文字幕无码 | 高清无码午夜福利视频 | 好屌草这里只有精品 | 日本乱偷人妻中文字幕 | 欧美日韩一区二区综合 | 丰满妇女强制高潮18xxxx | 国产av无码专区亚洲awww | 精品国偷自产在线视频 | 最新国产乱人伦偷精品免费网站 | 人人妻人人澡人人爽欧美一区 | 欧美熟妇另类久久久久久不卡 | 亚洲中文字幕无码中文字在线 | 日日碰狠狠丁香久燥 | 兔费看少妇性l交大片免费 | 亚洲天堂2017无码中文 | 伊人色综合久久天天小片 | 女人被男人躁得好爽免费视频 | 亚洲中文无码av永久不收费 | 欧美喷潮久久久xxxxx | 国产精品丝袜黑色高跟鞋 | 女人和拘做爰正片视频 | 好男人www社区 | 国产猛烈高潮尖叫视频免费 | 美女黄网站人色视频免费国产 | 无码播放一区二区三区 | 国产超级va在线观看视频 | 色噜噜亚洲男人的天堂 | 在线亚洲高清揄拍自拍一品区 | 色婷婷香蕉在线一区二区 | 国产又粗又硬又大爽黄老大爷视 | 西西人体www44rt大胆高清 | 国产精品久久久久久无码 | 强伦人妻一区二区三区视频18 | 亚洲一区av无码专区在线观看 | 精品无码国产一区二区三区av | 在线视频网站www色 | 国内老熟妇对白xxxxhd | 亚洲成色在线综合网站 | 日本熟妇大屁股人妻 | 日本大乳高潮视频在线观看 | 东京无码熟妇人妻av在线网址 | 麻豆国产人妻欲求不满 | 激情国产av做激情国产爱 | 亚洲精品国产a久久久久久 | 真人与拘做受免费视频 | 亚洲 高清 成人 动漫 | 亚洲精品www久久久 | 婷婷六月久久综合丁香 | 国产精品内射视频免费 | 色欲av亚洲一区无码少妇 | 国精产品一品二品国精品69xx | 亚洲va中文字幕无码久久不卡 | 亚洲天堂2017无码 | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 成 人 网 站国产免费观看 | 人人爽人人爽人人片av亚洲 | 国产精品理论片在线观看 | 久久精品国产日本波多野结衣 | 日韩精品无码一区二区中文字幕 | 九一九色国产 | 国产无遮挡又黄又爽又色 | 国产精品第一区揄拍无码 | 国产成人无码午夜视频在线观看 | 亚洲中文字幕在线观看 | 亚洲自偷精品视频自拍 | 国产美女极度色诱视频www | 天堂а√在线中文在线 | a国产一区二区免费入口 | 性欧美videos高清精品 | 秋霞成人午夜鲁丝一区二区三区 | 啦啦啦www在线观看免费视频 | 欧美丰满少妇xxxx性 | 野狼第一精品社区 | 乱人伦人妻中文字幕无码 | 一本久道久久综合狠狠爱 | 蜜桃视频韩日免费播放 | 色欲综合久久中文字幕网 | 久久久久人妻一区精品色欧美 | 少妇无码av无码专区在线观看 | 久久99精品国产.久久久久 | 久久97精品久久久久久久不卡 | 奇米影视7777久久精品 | 亚洲精品欧美二区三区中文字幕 | 国产亚洲日韩欧美另类第八页 | av香港经典三级级 在线 | 2020久久超碰国产精品最新 | 在线а√天堂中文官网 | 国产精品永久免费视频 | 精品久久综合1区2区3区激情 | 77777熟女视频在线观看 а天堂中文在线官网 | 欧美色就是色 | 久久综合九色综合欧美狠狠 | 国产三级久久久精品麻豆三级 | 永久免费精品精品永久-夜色 | 亚洲精品久久久久久久久久久 | 亚洲精品国产精品乱码视色 | 少妇人妻av毛片在线看 | 黑人巨大精品欧美一区二区 | 欧美亚洲日韩国产人成在线播放 | 一本色道久久综合亚洲精品不卡 | 福利一区二区三区视频在线观看 | 精品亚洲成av人在线观看 | 香蕉久久久久久av成人 | 高清国产亚洲精品自在久久 | 亚洲色www成人永久网址 | 99riav国产精品视频 | 国产精品久久久av久久久 | 亚洲精品无码人妻无码 | 成年美女黄网站色大免费全看 | 97夜夜澡人人爽人人喊中国片 | 午夜理论片yy44880影院 | 国产真实乱对白精彩久久 | 午夜无码区在线观看 | 人人妻人人澡人人爽精品欧美 | 色婷婷欧美在线播放内射 | 在线精品国产一区二区三区 | 最近中文2019字幕第二页 | 奇米影视7777久久精品 | 在线 国产 欧美 亚洲 天堂 | 国产口爆吞精在线视频 | 欧美xxxx黑人又粗又长 | 无码人妻精品一区二区三区下载 | 亚洲精品中文字幕 | 啦啦啦www在线观看免费视频 | 全黄性性激高免费视频 | 久久综合九色综合欧美狠狠 | 一个人看的www免费视频在线观看 | 中文字幕av日韩精品一区二区 | 国产一区二区三区日韩精品 | 窝窝午夜理论片影院 | 久久精品中文字幕一区 | 中文字幕精品av一区二区五区 | 国产三级久久久精品麻豆三级 | 少妇无码一区二区二三区 | 免费无码午夜福利片69 | 曰韩少妇内射免费播放 | 一区二区三区高清视频一 | 性欧美熟妇videofreesex | 东京一本一道一二三区 | 东京热一精品无码av | 久久午夜无码鲁丝片午夜精品 | 国产在线精品一区二区三区直播 | 在线亚洲高清揄拍自拍一品区 | 伦伦影院午夜理论片 | 性欧美videos高清精品 | 人人超人人超碰超国产 | 国产成人无码av在线影院 | 国产又爽又黄又刺激的视频 | 老子影院午夜精品无码 | 国产内射爽爽大片视频社区在线 | 67194成是人免费无码 | 亚洲欧美中文字幕5发布 | 少妇人妻大乳在线视频 | 欧美人与牲动交xxxx | 图片小说视频一区二区 | 精品久久综合1区2区3区激情 | 国产福利视频一区二区 | 麻豆果冻传媒2021精品传媒一区下载 | 国产另类ts人妖一区二区 | 帮老师解开蕾丝奶罩吸乳网站 | 亚洲精品午夜无码电影网 | 无码av最新清无码专区吞精 | 亚洲色成人中文字幕网站 | 亚洲色欲久久久综合网东京热 | 婷婷综合久久中文字幕蜜桃三电影 | 水蜜桃av无码 | 久久久成人毛片无码 | 51国偷自产一区二区三区 | 性生交大片免费看l | 国语精品一区二区三区 | 国产成人无码午夜视频在线观看 | 伦伦影院午夜理论片 | 国产手机在线αⅴ片无码观看 | 国内精品人妻无码久久久影院蜜桃 | 国产欧美亚洲精品a | 国产九九九九九九九a片 | 国内揄拍国内精品人妻 | 国产午夜精品一区二区三区嫩草 | 红桃av一区二区三区在线无码av | 樱花草在线社区www | 日韩精品无码免费一区二区三区 | 午夜成人1000部免费视频 | 国产成人午夜福利在线播放 | 国产欧美亚洲精品a | 国产精品a成v人在线播放 | 久久人妻内射无码一区三区 | 永久黄网站色视频免费直播 | 免费国产黄网站在线观看 | 99精品久久毛片a片 | 国产亚洲视频中文字幕97精品 | 国产特级毛片aaaaaaa高清 | 毛片内射-百度 | 日本一卡2卡3卡四卡精品网站 | aⅴ在线视频男人的天堂 | 久久无码人妻影院 | 丝袜 中出 制服 人妻 美腿 | 婷婷丁香六月激情综合啪 | 亚洲男人av香蕉爽爽爽爽 | 午夜性刺激在线视频免费 | 亚洲一区二区三区无码久久 | 久久97精品久久久久久久不卡 | 在线 国产 欧美 亚洲 天堂 | 熟妇人妻激情偷爽文 | 精品国偷自产在线视频 | 亚洲成a人片在线观看日本 | 奇米影视7777久久精品 | 国产精品久久久久9999小说 | 极品尤物被啪到呻吟喷水 | 国产乱人伦偷精品视频 | 狂野欧美性猛交免费视频 | 人人妻人人澡人人爽欧美一区九九 | 亚洲娇小与黑人巨大交 | av在线亚洲欧洲日产一区二区 | √天堂中文官网8在线 | 偷窥日本少妇撒尿chinese | 中文亚洲成a人片在线观看 | 久久精品一区二区三区四区 | 欧美日韩色另类综合 | 欧美放荡的少妇 | 亚洲区欧美区综合区自拍区 | 国产香蕉97碰碰久久人人 | 荫蒂添的好舒服视频囗交 | 在线观看欧美一区二区三区 | 亚洲s码欧洲m码国产av | 亚洲成av人在线观看网址 | 免费无码一区二区三区蜜桃大 | 亚洲成av人综合在线观看 | 人妻人人添人妻人人爱 | 纯爱无遮挡h肉动漫在线播放 | 双乳奶水饱满少妇呻吟 | 久久精品国产99精品亚洲 | 国産精品久久久久久久 | 日韩av无码一区二区三区 | 最近的中文字幕在线看视频 | 成 人 免费观看网站 | 熟女俱乐部五十路六十路av | 无码国产色欲xxxxx视频 | 日日噜噜噜噜夜夜爽亚洲精品 | 亚洲人成人无码网www国产 | 国产无遮挡又黄又爽又色 | 日日天干夜夜狠狠爱 | 亚洲 欧美 激情 小说 另类 | 国产乱人伦偷精品视频 | 精品乱码久久久久久久 | 强伦人妻一区二区三区视频18 | 国产人妻精品一区二区三区不卡 | 99精品久久毛片a片 | 国产成人综合色在线观看网站 | 久久无码人妻影院 | 国产成人精品三级麻豆 | 玩弄人妻少妇500系列视频 | 欧美freesex黑人又粗又大 | 色综合久久久无码网中文 | 久久精品人人做人人综合 | 人妻少妇精品无码专区动漫 | 人妻与老人中文字幕 | 性欧美videos高清精品 | 无码成人精品区在线观看 | 99久久久无码国产aaa精品 | 黄网在线观看免费网站 | 99riav国产精品视频 | 18精品久久久无码午夜福利 | 理论片87福利理论电影 | 狠狠噜狠狠狠狠丁香五月 | 亚洲日韩av片在线观看 | aⅴ亚洲 日韩 色 图网站 播放 | 亚洲热妇无码av在线播放 | 国产99久久精品一区二区 | av在线亚洲欧洲日产一区二区 | 欧美黑人巨大xxxxx | 国产精品资源一区二区 | 国产成人无码av片在线观看不卡 | 亚洲成av人综合在线观看 | 在线 国产 欧美 亚洲 天堂 | 丝袜 中出 制服 人妻 美腿 | 国产精品亚洲专区无码不卡 | 精品无人区无码乱码毛片国产 | 欧美国产日韩久久mv | 麻豆蜜桃av蜜臀av色欲av | 老太婆性杂交欧美肥老太 | 久久99国产综合精品 | 在线看片无码永久免费视频 | 国产精品久久久久久亚洲毛片 | 久久久中文字幕日本无吗 | 亚洲欧洲中文日韩av乱码 | 亚洲人亚洲人成电影网站色 | 国产高潮视频在线观看 | 成人精品视频一区二区 | 任你躁国产自任一区二区三区 | 亚洲国产精品毛片av不卡在线 | www国产亚洲精品久久久日本 | 久久无码中文字幕免费影院蜜桃 | 人妻体内射精一区二区三四 | 亚洲の无码国产の无码步美 | 一本色道久久综合狠狠躁 | 日日噜噜噜噜夜夜爽亚洲精品 | 成人欧美一区二区三区黑人 | 色五月丁香五月综合五月 | 国内少妇偷人精品视频免费 | 沈阳熟女露脸对白视频 | 日本高清一区免费中文视频 | 四十如虎的丰满熟妇啪啪 | 久久久久久九九精品久 | 99久久婷婷国产综合精品青草免费 | 中文字幕av无码一区二区三区电影 | 激情内射亚州一区二区三区爱妻 | 国产sm调教视频在线观看 | 永久免费精品精品永久-夜色 | 免费国产黄网站在线观看 | 欧美日韩在线亚洲综合国产人 | 久久久久亚洲精品男人的天堂 | 日产精品高潮呻吟av久久 | 97夜夜澡人人爽人人喊中国片 | 少妇性俱乐部纵欲狂欢电影 | 无码人妻丰满熟妇区五十路百度 | 欧美日本精品一区二区三区 | 六月丁香婷婷色狠狠久久 | 大屁股大乳丰满人妻 | 色婷婷av一区二区三区之红樱桃 | 日韩欧美群交p片內射中文 | 少妇性l交大片 | 国产农村妇女高潮大叫 | 亚洲国产精品美女久久久久 | 免费观看激色视频网站 | 97精品人妻一区二区三区香蕉 | 亚洲国产精品久久久天堂 | 西西人体www44rt大胆高清 | 99精品无人区乱码1区2区3区 | 99久久婷婷国产综合精品青草免费 | 少妇人妻偷人精品无码视频 | 国产两女互慰高潮视频在线观看 | 狠狠色丁香久久婷婷综合五月 | 欧美日本精品一区二区三区 | 内射巨臀欧美在线视频 | 色婷婷欧美在线播放内射 | 欧美丰满熟妇xxxx性ppx人交 | 国产精品igao视频网 | 一本久道高清无码视频 | 中文字幕无码免费久久99 | 国产内射爽爽大片视频社区在线 | 男女下面进入的视频免费午夜 | 午夜男女很黄的视频 | 国产偷抇久久精品a片69 | 亚洲精品综合一区二区三区在线 | 少妇人妻大乳在线视频 | 欧美人与牲动交xxxx | 中文字幕久久久久人妻 | 欧美成人免费全部网站 | 伊人久久大香线焦av综合影院 | 女人被男人躁得好爽免费视频 | 国产精品亚洲а∨无码播放麻豆 | 日本乱偷人妻中文字幕 | 一本加勒比波多野结衣 | 大色综合色综合网站 | 三上悠亚人妻中文字幕在线 | 一本无码人妻在中文字幕免费 | 日本爽爽爽爽爽爽在线观看免 | 欧美人与物videos另类 | 国产精品免费大片 | 欧美性生交活xxxxxdddd | 国产精品怡红院永久免费 | 国内精品人妻无码久久久影院 | 亚洲va中文字幕无码久久不卡 | 中文无码成人免费视频在线观看 | 久久久精品欧美一区二区免费 | 亚洲精品国产第一综合99久久 | 无码av最新清无码专区吞精 | 人人妻人人澡人人爽欧美一区九九 | 人人妻人人澡人人爽欧美一区 | 高潮喷水的毛片 | 亚洲国产高清在线观看视频 | 中文亚洲成a人片在线观看 | 国产日产欧产精品精品app | 亚洲国产精品一区二区第一页 | 国产在线无码精品电影网 | 日韩人妻无码中文字幕视频 | 老太婆性杂交欧美肥老太 | 少妇无码吹潮 | 岛国片人妻三上悠亚 | 国产精品高潮呻吟av久久 | 国产精品无码一区二区桃花视频 | 欧美亚洲国产一区二区三区 | 国产真实乱对白精彩久久 | 亚洲欧美国产精品久久 | 欧美黑人乱大交 | 乱码av麻豆丝袜熟女系列 | 国产精品99久久精品爆乳 | 在线看片无码永久免费视频 | 国产精品资源一区二区 | 欧美人与善在线com | 国产亚洲精品久久久闺蜜 | 精品无人国产偷自产在线 | 久久亚洲日韩精品一区二区三区 | 性生交片免费无码看人 | 日韩人妻系列无码专区 | 乱人伦人妻中文字幕无码 | 99久久精品无码一区二区毛片 | 亚洲精品久久久久avwww潮水 | 55夜色66夜色国产精品视频 | 欧美老人巨大xxxx做受 | 4hu四虎永久在线观看 | 国产真实伦对白全集 | 无码一区二区三区在线观看 | 久久精品女人的天堂av | 55夜色66夜色国产精品视频 | 一本久久a久久精品亚洲 | 成人免费无码大片a毛片 | 一本久道久久综合狠狠爱 | 一区二区传媒有限公司 | 国产高清av在线播放 | 亚洲一区二区三区在线观看网站 | 国产97人人超碰caoprom | 人妻少妇被猛烈进入中文字幕 | 纯爱无遮挡h肉动漫在线播放 | 久久视频在线观看精品 | 无码av免费一区二区三区试看 | 免费视频欧美无人区码 | 蜜臀aⅴ国产精品久久久国产老师 | 国产综合色产在线精品 | 免费中文字幕日韩欧美 | 老熟女乱子伦 | 成熟妇人a片免费看网站 | 久久精品国产日本波多野结衣 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 亚洲成熟女人毛毛耸耸多 | 性开放的女人aaa片 | 超碰97人人做人人爱少妇 | 牲欲强的熟妇农村老妇女 | 国产av人人夜夜澡人人爽麻豆 | 色窝窝无码一区二区三区色欲 | 国产精品国产自线拍免费软件 | 精品久久久久香蕉网 | 日本大香伊一区二区三区 | 国产精品二区一区二区aⅴ污介绍 | 国产精品福利视频导航 | 亚洲国产精品无码一区二区三区 | 男人和女人高潮免费网站 | 红桃av一区二区三区在线无码av | 亚洲国产欧美国产综合一区 | 九九在线中文字幕无码 | 99精品视频在线观看免费 | 久久久婷婷五月亚洲97号色 | 99精品无人区乱码1区2区3区 | 午夜福利一区二区三区在线观看 | 狠狠综合久久久久综合网 | 亚洲中文字幕av在天堂 | 成人无码影片精品久久久 | 婷婷丁香六月激情综合啪 | 九九综合va免费看 | 无码人妻出轨黑人中文字幕 | 久久久中文字幕日本无吗 | 无码人妻丰满熟妇区毛片18 | 又大又紧又粉嫩18p少妇 | 久久综合久久自在自线精品自 | 中文字幕无码日韩专区 | 麻豆国产人妻欲求不满 | 中文字幕 亚洲精品 第1页 | 国内精品久久毛片一区二区 | 国产真实乱对白精彩久久 | 久久人人爽人人爽人人片ⅴ | 又黄又爽又色的视频 | 国产sm调教视频在线观看 | 在线观看国产午夜福利片 | 国产精品内射视频免费 | 永久免费观看国产裸体美女 | 鲁一鲁av2019在线 | 成人一在线视频日韩国产 | 伊人久久大香线蕉午夜 | 亚洲成a人片在线观看无码3d | 欧美日韩一区二区综合 | 中文久久乱码一区二区 | 激情亚洲一区国产精品 | 亚洲精品一区二区三区婷婷月 | 欧美精品一区二区精品久久 | 午夜成人1000部免费视频 | 国产人妻大战黑人第1集 | 中文字幕av伊人av无码av | 国产精品久久久久无码av色戒 | 成人三级无码视频在线观看 | 77777熟女视频在线观看 а天堂中文在线官网 | 男女猛烈xx00免费视频试看 | 国产激情艳情在线看视频 | 一个人免费观看的www视频 | 国产成人人人97超碰超爽8 | 国产莉萝无码av在线播放 | 成人无码精品一区二区三区 | 最近免费中文字幕中文高清百度 | 中文字幕亚洲情99在线 | 国产精品二区一区二区aⅴ污介绍 | 亚洲自偷精品视频自拍 | 一区二区传媒有限公司 | 亚洲大尺度无码无码专区 | 在线精品国产一区二区三区 | 中文字幕无码免费久久9一区9 | 亚洲成色在线综合网站 | 久久精品人妻少妇一区二区三区 | 亚洲精品久久久久avwww潮水 | av小次郎收藏 | 中文字幕无码视频专区 | 精品人人妻人人澡人人爽人人 | 小泽玛莉亚一区二区视频在线 | 又大又硬又爽免费视频 | 欧美自拍另类欧美综合图片区 | 欧美日韩视频无码一区二区三 | 性做久久久久久久久 | 永久免费观看美女裸体的网站 | 乱人伦中文视频在线观看 | 亚洲啪av永久无码精品放毛片 | 日日鲁鲁鲁夜夜爽爽狠狠 | 狠狠综合久久久久综合网 | 九九久久精品国产免费看小说 | 成人亚洲精品久久久久软件 | 国产成人综合美国十次 | 99精品视频在线观看免费 | 精品亚洲成av人在线观看 | 蜜桃av蜜臀av色欲av麻 999久久久国产精品消防器材 | 国产成人无码区免费内射一片色欲 | 久久精品中文字幕一区 | 天堂亚洲免费视频 | 乌克兰少妇性做爰 | 无套内谢的新婚少妇国语播放 | 成人亚洲精品久久久久软件 | 日韩亚洲欧美精品综合 | 亚洲国产av精品一区二区蜜芽 | 少妇性l交大片 | 久久综合狠狠综合久久综合88 | 欧美丰满少妇xxxx性 | 中文字幕乱码中文乱码51精品 | 欧美高清在线精品一区 | 宝宝好涨水快流出来免费视频 | 成在人线av无码免费 | 清纯唯美经典一区二区 | 永久免费精品精品永久-夜色 | 国产美女精品一区二区三区 | 天天拍夜夜添久久精品大 | 亚洲精品国产精品乱码不卡 | 色综合久久88色综合天天 | 久久久久99精品成人片 | 午夜丰满少妇性开放视频 | 在线播放免费人成毛片乱码 | 日韩少妇内射免费播放 | 日本www一道久久久免费榴莲 | 精品一区二区三区无码免费视频 | 人妻无码αv中文字幕久久琪琪布 | 老熟妇仑乱视频一区二区 | 亚洲成av人片在线观看无码不卡 | 亚洲国产欧美在线成人 | 又紧又大又爽精品一区二区 | 免费视频欧美无人区码 | 小泽玛莉亚一区二区视频在线 | 丝袜 中出 制服 人妻 美腿 | 爽爽影院免费观看 | 黄网在线观看免费网站 | 国产无套内射久久久国产 | 欧美性生交活xxxxxdddd | 亚洲一区二区三区偷拍女厕 | 国产艳妇av在线观看果冻传媒 | 人人妻人人澡人人爽人人精品浪潮 | 国产亚洲精品久久久久久国模美 | 国产精品国产三级国产专播 | 无码人妻av免费一区二区三区 | 国产福利视频一区二区 | 精品 日韩 国产 欧美 视频 | 亚洲大尺度无码无码专区 | 国产精品多人p群无码 | 在线播放免费人成毛片乱码 | 熟妇女人妻丰满少妇中文字幕 | 亚洲精品一区二区三区四区五区 | 亚洲精品国偷拍自产在线麻豆 | √天堂资源地址中文在线 | 国产激情无码一区二区app | 中文字幕亚洲情99在线 | 国产电影无码午夜在线播放 | 蜜臀av无码人妻精品 | 国内丰满熟女出轨videos | 99riav国产精品视频 | 久久人妻内射无码一区三区 | 蜜臀aⅴ国产精品久久久国产老师 | 国产国产精品人在线视 | 日本高清一区免费中文视频 | 无码av岛国片在线播放 | 我要看www免费看插插视频 | 国产午夜亚洲精品不卡 | 国产激情一区二区三区 | 成人试看120秒体验区 | 在线观看国产午夜福利片 | 国产精品久久久一区二区三区 | 99久久精品国产一区二区蜜芽 | 人妻无码αv中文字幕久久琪琪布 | 精品 日韩 国产 欧美 视频 | 亚洲中文字幕无码中字 | 国产成人精品视频ⅴa片软件竹菊 | 午夜无码区在线观看 | 国产熟女一区二区三区四区五区 | 久久成人a毛片免费观看网站 | 欧美肥老太牲交大战 | 亚洲一区二区三区无码久久 | 一区二区传媒有限公司 | 乌克兰少妇xxxx做受 | 国产无遮挡又黄又爽又色 | 国産精品久久久久久久 | 中国大陆精品视频xxxx | 波多野结衣av一区二区全免费观看 | 午夜丰满少妇性开放视频 | 亚洲自偷自偷在线制服 | 青青草原综合久久大伊人精品 | 人妻尝试又大又粗久久 | 免费看少妇作爱视频 | 国产午夜无码精品免费看 | 图片区 小说区 区 亚洲五月 | 红桃av一区二区三区在线无码av | 国产精品美女久久久 | 亚洲一区二区三区含羞草 | 精品一区二区三区波多野结衣 | 日日天日日夜日日摸 | 国产高清不卡无码视频 | 一本久道久久综合狠狠爱 | 亚洲 a v无 码免 费 成 人 a v | 欧美激情内射喷水高潮 | 欧美大屁股xxxxhd黑色 | 小sao货水好多真紧h无码视频 | 免费乱码人妻系列无码专区 | 亚洲码国产精品高潮在线 | 97精品国产97久久久久久免费 | 色婷婷av一区二区三区之红樱桃 | 国产精品多人p群无码 | 亚洲精品鲁一鲁一区二区三区 | 熟妇人妻无乱码中文字幕 | 精品乱码久久久久久久 | 国产成人综合美国十次 | 国语自产偷拍精品视频偷 | 久久久久亚洲精品中文字幕 | 色一情一乱一伦一视频免费看 | 300部国产真实乱 | 久精品国产欧美亚洲色aⅴ大片 | 欧美精品免费观看二区 | 丰满妇女强制高潮18xxxx | 国产香蕉尹人综合在线观看 | 六月丁香婷婷色狠狠久久 | 亚洲天堂2017无码中文 | 大色综合色综合网站 | 亚洲精品成人av在线 | 少妇人妻偷人精品无码视频 | 日韩精品无码免费一区二区三区 | 狂野欧美激情性xxxx | 少妇人妻av毛片在线看 | 亚洲欧洲中文日韩av乱码 | 亚洲精品鲁一鲁一区二区三区 | 人人妻人人澡人人爽人人精品 | 午夜精品久久久内射近拍高清 | 人人妻人人澡人人爽欧美一区 | 免费无码午夜福利片69 | 日日鲁鲁鲁夜夜爽爽狠狠 | 国产av人人夜夜澡人人爽麻豆 | 草草网站影院白丝内射 | 欧美成人午夜精品久久久 | 欧美三级a做爰在线观看 | 两性色午夜视频免费播放 | 亚洲欧美国产精品专区久久 | 天天av天天av天天透 | 亚洲欧美色中文字幕在线 | 亚洲a无码综合a国产av中文 | 国产乱码精品一品二品 | 欧美人与牲动交xxxx | 欧美 亚洲 国产 另类 | 久久五月精品中文字幕 | 国产精品二区一区二区aⅴ污介绍 | 秋霞成人午夜鲁丝一区二区三区 | 4hu四虎永久在线观看 | 牲欲强的熟妇农村老妇女视频 | 国产亚洲日韩欧美另类第八页 | 少妇邻居内射在线 | 日韩精品久久久肉伦网站 | 欧洲vodafone精品性 | 性啪啪chinese东北女人 | 露脸叫床粗话东北少妇 | 妺妺窝人体色www婷婷 | 免费观看的无遮挡av | 亚洲精品欧美二区三区中文字幕 | 久久精品无码一区二区三区 | 中文字幕无码人妻少妇免费 | 美女扒开屁股让男人桶 | 亚洲一区av无码专区在线观看 | 大乳丰满人妻中文字幕日本 | 久久视频在线观看精品 | 狠狠躁日日躁夜夜躁2020 | 精品无码一区二区三区的天堂 | 俺去俺来也在线www色官网 | 我要看www免费看插插视频 | 亚拍精品一区二区三区探花 | 国产成人精品三级麻豆 | 国产一区二区三区日韩精品 | 蜜臀av无码人妻精品 | 男人扒开女人内裤强吻桶进去 | 国产成人精品无码播放 | 国产色视频一区二区三区 | 性做久久久久久久免费看 | 熟女少妇人妻中文字幕 | 131美女爱做视频 | 色诱久久久久综合网ywww | 国产农村乱对白刺激视频 | 精品欧洲av无码一区二区三区 | 中文字幕无码人妻少妇免费 | 亚洲色无码一区二区三区 | 日本欧美一区二区三区乱码 | 久久久av男人的天堂 | 亚洲国产精华液网站w | 在线播放无码字幕亚洲 | 真人与拘做受免费视频 | 成年美女黄网站色大免费全看 | 日韩精品无码一本二本三本色 | 亚洲成a人一区二区三区 | 麻豆人妻少妇精品无码专区 | 中文久久乱码一区二区 | 国内揄拍国内精品少妇国语 | 久久天天躁夜夜躁狠狠 | 麻豆国产97在线 | 欧洲 | 精品日本一区二区三区在线观看 | 国产成人综合美国十次 | 亚洲日本va中文字幕 | 成人女人看片免费视频放人 | 天天躁夜夜躁狠狠是什么心态 | 亚洲一区二区三区 | 亚洲国产精品无码一区二区三区 | 欧美xxxx黑人又粗又长 | 亚洲欧洲中文日韩av乱码 | 成年女人永久免费看片 | 美女黄网站人色视频免费国产 | 强辱丰满人妻hd中文字幕 | 成人无码精品一区二区三区 | 亚洲精品国产精品乱码不卡 | a片在线免费观看 | 岛国片人妻三上悠亚 | 中国大陆精品视频xxxx | 一区二区三区高清视频一 | 国产极品美女高潮无套在线观看 | 亚洲精品欧美二区三区中文字幕 | 久久国产精品二国产精品 | 无套内谢的新婚少妇国语播放 | 两性色午夜免费视频 | 成人毛片一区二区 | 少妇人妻偷人精品无码视频 | 亚洲无人区午夜福利码高清完整版 | 亚洲一区二区三区播放 | 久久久久成人片免费观看蜜芽 | 国产亚洲精品久久久久久久久动漫 | 亚洲国产精品美女久久久久 | 狠狠躁日日躁夜夜躁2020 | 国产成人精品久久亚洲高清不卡 | 色欲久久久天天天综合网精品 | 国产精品久久久久久亚洲影视内衣 | 人妻少妇被猛烈进入中文字幕 | 久久国产精品萌白酱免费 | 捆绑白丝粉色jk震动捧喷白浆 | 国产精品成人av在线观看 | 妺妺窝人体色www在线小说 | а√天堂www在线天堂小说 | 内射白嫩少妇超碰 | 精品国产一区二区三区av 性色 | 亚洲熟妇色xxxxx亚洲 | 国内揄拍国内精品人妻 | 欧美xxxx黑人又粗又长 | 国内精品人妻无码久久久影院蜜桃 | 欧美性猛交xxxx富婆 | 久久综合网欧美色妞网 | 99视频精品全部免费免费观看 | 精品少妇爆乳无码av无码专区 | 亚洲经典千人经典日产 | 欧美国产日韩亚洲中文 | 强奷人妻日本中文字幕 | 最近的中文字幕在线看视频 | 日本护士xxxxhd少妇 | 亚洲爆乳无码专区 | 久久成人a毛片免费观看网站 | 亚洲成色www久久网站 | 成人影院yy111111在线观看 | 鲁大师影院在线观看 | 动漫av网站免费观看 | 久久zyz资源站无码中文动漫 | 黑人大群体交免费视频 | 99久久婷婷国产综合精品青草免费 | 成人免费无码大片a毛片 | 自拍偷自拍亚洲精品被多人伦好爽 | 疯狂三人交性欧美 | 色一情一乱一伦一视频免费看 | 亚洲成av人影院在线观看 | 色婷婷av一区二区三区之红樱桃 | 国精品人妻无码一区二区三区蜜柚 | www国产亚洲精品久久久日本 | 精品国产av色一区二区深夜久久 | 久久成人a毛片免费观看网站 | 久久亚洲中文字幕精品一区 | 亚洲国产成人a精品不卡在线 | 亚洲熟妇色xxxxx欧美老妇 | 亚洲精品国偷拍自产在线观看蜜桃 | 九月婷婷人人澡人人添人人爽 | 亚洲国产精品一区二区第一页 | 国产乱人伦av在线无码 | 国产手机在线αⅴ片无码观看 | 久久精品国产亚洲精品 | 亚洲欧美日韩成人高清在线一区 | 午夜成人1000部免费视频 | 最近免费中文字幕中文高清百度 | 无码精品国产va在线观看dvd | 日本一卡2卡3卡四卡精品网站 | 一本久道高清无码视频 | 色综合天天综合狠狠爱 | 麻豆av传媒蜜桃天美传媒 | 日日天日日夜日日摸 | 成人精品天堂一区二区三区 | 丰满诱人的人妻3 | 亚洲中文字幕成人无码 | 在教室伦流澡到高潮hnp视频 | 亚洲人成人无码网www国产 | 无码人妻黑人中文字幕 | 欧美第一黄网免费网站 | 亚洲精品国偷拍自产在线麻豆 | 人妻少妇被猛烈进入中文字幕 | 国色天香社区在线视频 | 人人妻人人澡人人爽欧美精品 | 亚洲一区av无码专区在线观看 | 少妇太爽了在线观看 | 5858s亚洲色大成网站www | 狠狠色丁香久久婷婷综合五月 | 色综合久久久久综合一本到桃花网 | 国产精品无码mv在线观看 | 国产一区二区三区日韩精品 | 国产精品国产自线拍免费软件 | 亚洲精品国产精品乱码视色 | 在线看片无码永久免费视频 | 亚洲国精产品一二二线 | 精品国产乱码久久久久乱码 | 无码人妻丰满熟妇区五十路百度 | 亚洲色大成网站www国产 | 国产午夜视频在线观看 | 日本大香伊一区二区三区 | 亚洲成a人片在线观看无码3d | 亚洲 高清 成人 动漫 | 日韩人妻少妇一区二区三区 | 人妻尝试又大又粗久久 | 亚洲一区二区三区国产精华液 | 亚洲精品成人福利网站 | 欧美怡红院免费全部视频 | 国产免费久久久久久无码 | 精品无码国产自产拍在线观看蜜 | 亚洲熟妇自偷自拍另类 | 亚洲色成人中文字幕网站 | 色婷婷综合中文久久一本 | 在线 国产 欧美 亚洲 天堂 | 国产香蕉尹人综合在线观看 | 日韩av无码中文无码电影 | 日本成熟视频免费视频 | 动漫av一区二区在线观看 | 欧美人与物videos另类 | 55夜色66夜色国产精品视频 | 无套内谢的新婚少妇国语播放 | 丝袜足控一区二区三区 | 性色欲网站人妻丰满中文久久不卡 | 300部国产真实乱 | 日本va欧美va欧美va精品 | 亚洲一区二区三区国产精华液 | 98国产精品综合一区二区三区 | 精品久久久久久人妻无码中文字幕 | 亚洲 a v无 码免 费 成 人 a v | www一区二区www免费 | 国产精品美女久久久久av爽李琼 | 人人爽人人爽人人片av亚洲 | 中文字幕中文有码在线 | 久久精品中文字幕一区 | 欧美日韩视频无码一区二区三 | 久久国产劲爆∧v内射 | 国内精品九九久久久精品 | 亚洲国产欧美日韩精品一区二区三区 | 真人与拘做受免费视频一 | 亚洲区欧美区综合区自拍区 | 久久 国产 尿 小便 嘘嘘 | 女人被男人爽到呻吟的视频 | 国产av一区二区三区最新精品 | 牲交欧美兽交欧美 | 伊人久久大香线蕉av一区二区 | 无码av最新清无码专区吞精 | 无码一区二区三区在线观看 | 人妻尝试又大又粗久久 | 久久午夜无码鲁丝片 | 亚洲综合色区中文字幕 | 无码午夜成人1000部免费视频 | 亚洲の无码国产の无码影院 | 性生交大片免费看l | 好男人www社区 | 大肉大捧一进一出好爽视频 | 十八禁视频网站在线观看 | 国产超级va在线观看视频 | 国产欧美亚洲精品a | 日本精品人妻无码77777 天堂一区人妻无码 | 欧美黑人巨大xxxxx | 国产疯狂伦交大片 | 野狼第一精品社区 | 麻豆国产97在线 | 欧洲 | 7777奇米四色成人眼影 | 欧美精品在线观看 | 香港三级日本三级妇三级 | 日本熟妇人妻xxxxx人hd | 粗大的内捧猛烈进出视频 | 久久综合九色综合97网 | 国内精品人妻无码久久久影院 | 国产高清av在线播放 | 国产尤物精品视频 | 亚洲精品一区二区三区婷婷月 | 亚洲精品成a人在线观看 | 久久午夜夜伦鲁鲁片无码免费 | 免费乱码人妻系列无码专区 | 蜜桃视频韩日免费播放 | 六十路熟妇乱子伦 | 少妇无码av无码专区在线观看 | 国产人妻人伦精品1国产丝袜 | 人妻少妇精品无码专区动漫 | 欧美熟妇另类久久久久久多毛 | 奇米影视888欧美在线观看 | 亚洲国产一区二区三区在线观看 | 亚洲男人av香蕉爽爽爽爽 | 午夜精品一区二区三区在线观看 | 国产成人无码av在线影院 | 国产特级毛片aaaaaa高潮流水 | 又色又爽又黄的美女裸体网站 | 欧美人与物videos另类 | 国产精品美女久久久久av爽李琼 | 久久无码专区国产精品s | 亚洲 另类 在线 欧美 制服 | 久久久久久久女国产乱让韩 | 免费看少妇作爱视频 | 日韩欧美成人免费观看 | 国精产品一品二品国精品69xx | 男人扒开女人内裤强吻桶进去 | 中文精品无码中文字幕无码专区 | 无码吃奶揉捏奶头高潮视频 | 无码中文字幕色专区 | 丰满人妻一区二区三区免费视频 | 久精品国产欧美亚洲色aⅴ大片 | 激情综合激情五月俺也去 | 麻豆蜜桃av蜜臀av色欲av | 精品乱码久久久久久久 | 午夜精品一区二区三区在线观看 | 亚洲欧美综合区丁香五月小说 | 97无码免费人妻超级碰碰夜夜 | 欧美人与牲动交xxxx | 夜夜影院未满十八勿进 | 天下第一社区视频www日本 | 婷婷丁香六月激情综合啪 | 99久久精品日本一区二区免费 | 中文字幕人妻无码一夲道 | 国产农村妇女高潮大叫 | 久久国产精品_国产精品 | 一个人免费观看的www视频 | а√天堂www在线天堂小说 | 午夜福利电影 | 伊人色综合久久天天小片 | 娇妻被黑人粗大高潮白浆 | 无码人妻丰满熟妇区五十路百度 | 少妇性俱乐部纵欲狂欢电影 | 国产情侣作爱视频免费观看 | 成人免费视频一区二区 | 少妇性荡欲午夜性开放视频剧场 | 亚洲精品国产第一综合99久久 | 最近的中文字幕在线看视频 | 巨爆乳无码视频在线观看 | 国精产品一品二品国精品69xx | 亚洲精品国偷拍自产在线观看蜜桃 | 成人无码精品1区2区3区免费看 | 亚洲精品国偷拍自产在线观看蜜桃 | 国产精品-区区久久久狼 | 99久久亚洲精品无码毛片 | 曰韩无码二三区中文字幕 | 性生交片免费无码看人 | 国产av一区二区精品久久凹凸 | 无码人妻少妇伦在线电影 | 国产极品美女高潮无套在线观看 | 成人免费无码大片a毛片 | 麻豆蜜桃av蜜臀av色欲av | 人人超人人超碰超国产 | 丝袜 中出 制服 人妻 美腿 | 久热国产vs视频在线观看 | 欧美阿v高清资源不卡在线播放 | 人妻无码αv中文字幕久久琪琪布 | 疯狂三人交性欧美 | 老子影院午夜伦不卡 | 好男人社区资源 | 5858s亚洲色大成网站www | 黑森林福利视频导航 | 亚洲一区二区三区播放 | 精品一区二区三区波多野结衣 | 人人妻人人澡人人爽欧美精品 | 丝袜美腿亚洲一区二区 | yw尤物av无码国产在线观看 | 亚洲狠狠色丁香婷婷综合 | 日韩欧美群交p片內射中文 | 国产精品欧美成人 | 国产午夜视频在线观看 | 亚洲国产精品毛片av不卡在线 | 九九热爱视频精品 | 国产高潮视频在线观看 | 中文字幕人妻无码一夲道 | 丰满护士巨好爽好大乳 | 亚洲熟妇色xxxxx欧美老妇 | 国产成人无码a区在线观看视频app | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 国产舌乚八伦偷品w中 | 99麻豆久久久国产精品免费 | 国产办公室秘书无码精品99 | 欧美成人家庭影院 | 亚洲一区二区三区在线观看网站 | 国产乱人伦偷精品视频 | 性欧美牲交在线视频 | 国产成人综合色在线观看网站 | 人人爽人人澡人人高潮 | 成人亚洲精品久久久久软件 | 亚洲大尺度无码无码专区 | 日本精品高清一区二区 | 欧美国产亚洲日韩在线二区 | 在线观看免费人成视频 | 樱花草在线社区www | 国内精品九九久久久精品 | 精品一二三区久久aaa片 | 国产黑色丝袜在线播放 | 蜜桃视频韩日免费播放 | 国产av人人夜夜澡人人爽麻豆 | 男女下面进入的视频免费午夜 | 99国产精品白浆在线观看免费 | 中文字幕av无码一区二区三区电影 | 国内精品人妻无码久久久影院蜜桃 | 国产在线一区二区三区四区五区 | 国产午夜福利亚洲第一 | 欧美日韩一区二区综合 | 骚片av蜜桃精品一区 | 亚洲爆乳精品无码一区二区三区 | 乌克兰少妇性做爰 | 成人aaa片一区国产精品 | 精品人妻中文字幕有码在线 | 在线观看国产一区二区三区 | 在线观看国产午夜福利片 | 久久久久人妻一区精品色欧美 | 国产偷国产偷精品高清尤物 | 午夜精品一区二区三区在线观看 | ass日本丰满熟妇pics | 人妻夜夜爽天天爽三区 | 国内老熟妇对白xxxxhd | 狠狠亚洲超碰狼人久久 | 国产国产精品人在线视 | 1000部啪啪未满十八勿入下载 |