青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

羅朝輝(飄飄白云)

關(guān)注嵌入式操作系統(tǒng),移動(dòng)平臺(tái),圖形開發(fā)。-->加微博 ^_^

  C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
  85 隨筆 :: 0 文章 :: 169 評(píng)論 :: 0 Trackbacks

 [深入淺出Cocoa]之消息(二)-詳解動(dòng)態(tài)方法決議(Dynamic Method Resolution)

羅朝輝 (http://www.cnblogs.com/kesalin/)

本文遵循“署名-非商業(yè)用途-保持一致”創(chuàng)作公用協(xié)議
 

序言

如果我們?cè)?Objective C 中向一個(gè)對(duì)象發(fā)送它無法處理的消息,會(huì)出現(xiàn)什么情況呢?根據(jù)前文《深入淺出Cocoa之消息》的介紹,我們知道發(fā)送消息是通過 objc_send(id, SEL, ...) 來實(shí)現(xiàn)的,它會(huì)首先在對(duì)象的類對(duì)象的 cache,method list 以及父類對(duì)象的 cache, method list 中依次查找 SEL 對(duì)應(yīng)的 IMP;如果沒有找到且實(shí)現(xiàn)了動(dòng)態(tài)方法決議機(jī)制就會(huì)進(jìn)行決議,如果沒有實(shí)現(xiàn)動(dòng)態(tài)方法決議機(jī)制或決議失敗且實(shí)現(xiàn)了消息轉(zhuǎn)發(fā)機(jī)制就會(huì)進(jìn)入消息轉(zhuǎn)發(fā)流程,否則程序 crash。也就是說如果同時(shí)提供了動(dòng)態(tài)方法決議和消息轉(zhuǎn)發(fā),那么動(dòng)態(tài)方法決議先于消息轉(zhuǎn)發(fā),只有當(dāng)動(dòng)態(tài)方法決議依然無法正確決議 selector 的實(shí)現(xiàn),才會(huì)嘗試進(jìn)行消息轉(zhuǎn)發(fā)。在前文中,我并沒有詳細(xì)講解動(dòng)態(tài)方法決議,因此本文將詳細(xì)介紹之。

本文代碼下載:點(diǎn)此下載

一,向一個(gè)對(duì)象發(fā)送該對(duì)象無法處理的消息

如下代碼:

@interface Foo : NSObject

-(void)Bar;

@end

@implementation Foo

-(void)Bar
{
    NSLog(@" >> Bar() in Foo");
}

@end

/////////////////////////////////////////////////
#import "Foo.h"

int main (int argc, const char * argv[])
{

    @autoreleasepool {
        
        Foo * foo = [[Foo alloc] init];
        
        [foo Bar];
        
        [foo MissMethod];
        
        [foo release];
    }
    return 0;
}

在編譯時(shí),XCode 會(huì)提示警告:

Instance method '-MissMethod' not found (return type defaults to 'id')

如果,我們忽視該警告運(yùn)行之,一定會(huì) crash:

>> Bar() in Foo
-[Foo MissMethod]: unrecognized selector sent to instance 0x10010c840
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Foo MissMethod]: unrecognized selector sent to instance 0x10010c840'
*** Call stack at first throw:
......
terminate called after throwing an instance of 'NSException'

下劃線部分就是造成 crash 的原因:對(duì)象無法處理 MissMethod 對(duì)應(yīng)的 selector,也就是沒有相應(yīng)的實(shí)現(xiàn)。

 

二,動(dòng)態(tài)方法決議

Objective C 提供了一種名為動(dòng)態(tài)方法決議的手段,使得我們可以在運(yùn)行時(shí)動(dòng)態(tài)地為一個(gè) selector 提供實(shí)現(xiàn)。我們只要實(shí)現(xiàn) +resolveInstanceMethod: 和/或 +resolveClassMethod: 方法,并在其中為指定的 selector  提供實(shí)現(xiàn)即可(通過調(diào)用運(yùn)行時(shí)函數(shù) class_addMethod 來添加)。這兩個(gè)方法都是 NSObject 中的類方法,其原型為:

+ (BOOL)resolveClassMethod:(SEL)name;
+ (BOOL)resolveInstanceMethod:(SEL)name;

參數(shù) name 是需要被動(dòng)態(tài)決議的 selector;返回值文檔中說是表示動(dòng)態(tài)決議成功與否。但在上面的例子中(不涉及消息轉(zhuǎn)發(fā)的情況下),如果在該函數(shù)內(nèi)為指定的 selector  提供實(shí)現(xiàn),無論返回 YES 還是 NO,編譯運(yùn)行都是正確的;但如果在該函數(shù)內(nèi)并不真正為 selector 提供實(shí)現(xiàn),無論返回 YES 還是 NO,運(yùn)行都會(huì) crash,道理很簡(jiǎn)單,selector 并沒有對(duì)應(yīng)的實(shí)現(xiàn),而又沒有實(shí)現(xiàn)消息轉(zhuǎn)發(fā)。resolveInstanceMethod 是為對(duì)象方法進(jìn)行決議,而 resolveClassMethod 是為類方法進(jìn)行決議。

下面我們用動(dòng)態(tài)方法決議手段來修改上面的代碼:

//
//  Foo.m
//  DeepIntoMethod
//
//  Created by 飄飄白云 on 12-11-13.
//  Copyright (c) 2012年 kesalin@gmail.com All rights reserved.
//

#import "Foo.h"
#include <objc/runtime.h>

void dynamicMethodIMP(id self, SEL _cmd) {
    NSLog(@" >> dynamicMethodIMP");
}

@implementation Foo

-(void)Bar
{
    NSLog(@" >> Bar() in Foo");
}

+ (BOOL)resolveInstanceMethod:(SEL)name
{   
    NSLog(@" >> Instance resolving %@", NSStringFromSelector(name));
    
    if (name == @selector(MissMethod)) {
        class_addMethod([self class], name, (IMP)dynamicMethodIMP, "v@:");
        return YES;
    }
    
    return [super resolveInstanceMethod:name];
}

+ (BOOL)resolveClassMethod:(SEL)name
{
    NSLog(@" >> Class resolving %@", NSStringFromSelector(name));
    
    return [super resolveClassMethod:name];
}

@end

在前文《深入淺出Cocoa之消息》中已經(jīng)介紹過 Objective C 中的方法其實(shí)就是至少帶有兩個(gè)參數(shù)(self 和 _cmd)的普通 C 函數(shù),因此在上面的代碼中提供這樣一個(gè) C 函數(shù) dynamicMethodIMP,讓它來充當(dāng)對(duì)象方法 MissMethod 這個(gè) selector 的動(dòng)態(tài)實(shí)現(xiàn)。因?yàn)?MissMethod 是被對(duì)象所調(diào)用,所以它被認(rèn)為是一個(gè)對(duì)象方法,因而應(yīng)該在 resolveInstanceMethod 方法中為其提供實(shí)現(xiàn)。通過調(diào)用

class_addMethod([self class], name, (IMP)dynamicMethodIMP, "v@:"); 

就能在運(yùn)行期動(dòng)態(tài)地為 name 這個(gè) selector 添加實(shí)現(xiàn):dynamicMethodIMP。class_addMethod 是運(yùn)行時(shí)函數(shù),所以需要導(dǎo)入頭文件:objc/runtime.h。

再次編譯運(yùn)行前面的測(cè)試代碼,輸出如下:

  >> Bar() in Foo.
  >> Instance resolving MissMethod
  >> dynamicMethodIMP called.
  >> Instance resolving _doZombieMe

dynamicMethodIMP 被調(diào)用了,crash 沒有了!萬事大吉!

注意:這里兩次調(diào)用了 resolveInstanceMethod,而且兩次決議的 selector 在不同的系統(tǒng)下是不同的,上面演示的是 10.7 系統(tǒng)下第一個(gè)決議 MissMethod,第二個(gè)決議 _doZombieMe;在 10.6 系統(tǒng)下兩次都是決議 MissMethod。

下面我把 resolveInstanceMethod 方法中為 selector 添加實(shí)現(xiàn)的那一行屏蔽了,消息轉(zhuǎn)發(fā)就應(yīng)該會(huì)進(jìn)行:

//class_addMethod([self class], name, (IMP)dynamicMethodIMP, "v@:");

再次編譯運(yùn)行,此時(shí)輸出:

 >> Bar() in Foo.
 >> Instance resolving MissMethod
 +[Foo resolveInstanceMethod:MissMethod] returned YES, but no new implementation of -[Foo MissMethod] was found
  >> Instance resolving _doZombieMe
 objc[1223]: +[Foo resolveInstanceMethod:MissMethod] returned YES, but no new implementation of -[Foo MissMethod] was found
 -[Foo MissMethod]: unrecognized selector sent to instance 0x10010c880
  *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Foo MissMethod]: unrecognized selector sent to instance 0x10010c880'
 *** Call stack at first throw:
 ......

在這里,resolveInstanceMethod 使詐了,它聲稱成功(返回 YES )決議了 selector,但是并沒有真正提供實(shí)現(xiàn),被編譯器發(fā)覺而提示相應(yīng)的錯(cuò)誤信息。那它的返回值到底有什么作用呢,在它沒有提供真正的實(shí)現(xiàn),并且提供了消息轉(zhuǎn)發(fā)機(jī)制的情況下,YES 表示不進(jìn)行后續(xù)的消息轉(zhuǎn)發(fā),返回  NO 則表示要進(jìn)行后續(xù)的消息轉(zhuǎn)發(fā)。

 

三,源碼剖析

讓我們來看看運(yùn)行時(shí)系統(tǒng)是如何進(jìn)行動(dòng)態(tài)方法決議的,下面的代碼來自蘋果官方公開的源碼 objc-class.mm,我在其中添加了中文注釋:

1,首先是判斷是不是要進(jìn)行類方法決議,如果不是或決議失敗,則進(jìn)行實(shí)例方法決議(請(qǐng)參考:《深入淺出Cocoa之類與對(duì)象》):

/***********************************************************************
* _class_resolveMethod
* Call +resolveClassMethod or +resolveInstanceMethod and return 
* the method added or NULL. 
* Assumes the method doesn't exist already.
*********************************************************************
*/
__private_extern__ Method _class_resolveMethod(Class cls, SEL sel)
{
    Method meth = NULL;

    if (_class_isMetaClass(cls)) {
        meth = _class_resolveClassMethod(cls, sel);
    }
    if (!meth) {
        meth = _class_resolveInstanceMethod(cls, sel);
    }

    if (PrintResolving  &&  meth) {
        _objc_inform("RESOLVE: method %c[%s %s] dynamically resolved to %p", 
                     class_isMetaClass(cls) ? '+' : '-', 
                     class_getName(cls), sel_getName(sel), 
                     method_getImplementation(meth));
    }
    
    return meth;
}

2,類方法決議與實(shí)例方法決議大體相似,在這里就只看實(shí)例方法決議部分了:

/***********************************************************************
 * _class_resolveInstanceMethod
 * Call +resolveInstanceMethod and return the method added or NULL.
 * cls should be a non-meta class.
 * Assumes the method doesn't exist already.
 *********************************************************************
*/
static Method _class_resolveInstanceMethod(Class cls, SEL sel)
{
    BOOL resolved;
    Method meth = NULL;
    
    // 是否實(shí)現(xiàn)了 resolveInstanceMethod,如果沒有返回 NULL
    if (!look_up_method(((id)cls)->isa, SEL_resolveInstanceMethod, 
                        YES /*cache*/, NO /*resolver*/))
    {
        return NULL;
    }
    
    // 調(diào)用 resolveInstanceMethod,并獲取返回值
    resolved = ((BOOL(*)(id, SEL, SEL))objc_msgSend)((id)cls, SEL_resolveInstanceMethod, sel);
    
    if (resolved) {
        // 返回值為 YES,表示 resolveInstanceMethod 聲稱它已經(jīng)成功添加實(shí)現(xiàn),則再次查找 method list 
        
// +resolveClassMethod adds to self
        meth = look_up_method(cls, sel, YES/*cache*/, NO/*resolver*/);
        
        if (!meth) {
            // resolveInstanceMethod 使詐了,它聲稱成功添加實(shí)現(xiàn)了,但實(shí)際沒有,給出警告信息,并返回 NULL
            
// Method resolver didn't add anything?
            _objc_inform("+[%s resolveInstanceMethod:%s] returned YES, but "
                         "no new implementation of %c[%s %s] was found", 
                         class_getName(cls),
                         sel_getName(sel), 
                         class_isMetaClass(cls) ? '+' : '-', 
                         class_getName(cls), 
                         sel_getName(sel));
            return NULL;
        }
    }
    
    // 其他情況下返回 NULL
    return meth;
}

這段代碼很容易理解:

1,首先判斷是否實(shí)現(xiàn)了 resolveInstanceMethod,如果沒有實(shí)現(xiàn),返回 NULL,進(jìn)入下一步處理;

2,如果實(shí)現(xiàn)了,調(diào)用 resolveInstanceMethod,獲取返回值;

3,如果返回值為 YES,表示 resolveInstanceMethod 聲稱它已經(jīng)提供了 selector 的實(shí)現(xiàn),因此再次查找 method list,如果依然找到對(duì)應(yīng)的 IMP,則返回該實(shí)現(xiàn),否則提示警告信息,返回 NULL,進(jìn)入下一步處理;

4,如果返回值為 NO,返回 NULL,進(jìn)入下一步處理;

 

四,加入消息轉(zhuǎn)發(fā)

在前文《深入淺出Cocoa之消息》一文中,我演示了一個(gè)消息轉(zhuǎn)發(fā)的示例,下面我把動(dòng)態(tài)方法決議部分去除,把消息轉(zhuǎn)發(fā)部分添加進(jìn)來:

// Proxy
@interface Proxy : NSObject

-(void)MissMethod;

@end

@implementation Proxy

-(void)MissMethod
{
    NSLog(@" >> MissMethod() called in Proxy.");
}

@end

// Foo
@interface Foo : NSObject

-(void)Bar;

@end

@implementation Foo

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
    SEL name = [anInvocation selector];
    NSLog(@" >> forwardInvocation for selector %@", NSStringFromSelector(name));
    
    Proxy * proxy = [[[Proxy alloc] init] autorelease];
    if ([proxy respondsToSelector:name]) {
        [anInvocation invokeWithTarget:proxy];
    }
    else {
        [super forwardInvocation:anInvocation];
    }
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    return [Proxy instanceMethodSignatureForSelector:aSelector];
}

-(void)Bar
{
    NSLog(@" >> Bar() in Foo.");
}

@end

運(yùn)行測(cè)試代碼,輸出如下:

  >> Bar() in Foo.
  >> forwardInvocation for selector MissMethod
  >> MissMethod() called in Proxy.

如果我把動(dòng)態(tài)方法決議部分代碼也加入進(jìn)來輸出又是怎樣呢?下面只列出了 Foo 的實(shí)現(xiàn)代碼,其他代碼不變動(dòng)。

@implementation Foo

+(BOOL)resolveInstanceMethod:(SEL)name
{
    NSLog(@" >> Instance resolving %@", NSStringFromSelector(name));
    
    if (name == @selector(MissMethod)) {
        class_addMethod([self class], name, (IMP)dynamicMethodIMP, "v@:");
        return YES;
    }
    
    return [super resolveInstanceMethod:name];
}

+(BOOL)resolveClassMethod:(SEL)name
{
    NSLog(@" >> Class resolving %@", NSStringFromSelector(name));
    return [super resolveClassMethod:name];
}

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
    SEL name = [anInvocation selector];
    NSLog(@" >> forwardInvocation for selector %@", NSStringFromSelector(name));
    
    Proxy * proxy = [[[Proxy alloc] init] autorelease];
    if ([proxy respondsToSelector:name]) {
        [anInvocation invokeWithTarget:proxy];
    }
    else {
        [super forwardInvocation:anInvocation];
    }
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    return [Proxy instanceMethodSignatureForSelector:aSelector];
}

-(void)Bar
{
    NSLog(@" >> Bar() in Foo.");
}

@end

此時(shí),輸出為:

  >> Bar() in Foo.
  >> Instance resolving MissMethod
  >> dynamicMethodIMP called.
  >> Instance resolving _doZombieMe

注意到了沒,消息轉(zhuǎn)發(fā)沒有進(jìn)行!在前文中說過,消息轉(zhuǎn)發(fā)只有在對(duì)象無法正常處理消息時(shí)才會(huì)調(diào)用,而在這里我在動(dòng)態(tài)方法決議中為 selector 提供了實(shí)現(xiàn),使得對(duì)象可以處理該消息,所以消息轉(zhuǎn)發(fā)不會(huì)繼續(xù)了。官方文檔中說:

If you implement resolveInstanceMethod: but want particular selectors to actually be forwarded via the forwarding mechanism, you return NO for those selectors.

文檔里的說法其實(shí)并不準(zhǔn)確,只有在 resolveInstanceMethod 的實(shí)現(xiàn)中沒有真正為 selector 提供實(shí)現(xiàn),并返回 NO 的情況下才會(huì)進(jìn)入消息轉(zhuǎn)發(fā)流程;否則絕不會(huì)進(jìn)入消息轉(zhuǎn)發(fā)流程,程序要么調(diào)用正確的動(dòng)態(tài)方法,要么 crash。這也與前面的源碼不太一致,我猜測(cè)在比上面源碼的更高層次的地方,再次查找了 method list,如果提供了實(shí)現(xiàn)就能夠找到該實(shí)現(xiàn)。

下面我把 resolveInstanceMethod 方法中為 selector 添加實(shí)現(xiàn)的那一行屏蔽了,消息轉(zhuǎn)發(fā)就應(yīng)該會(huì)進(jìn)行:

//class_addMethod([self class], name, (IMP)dynamicMethodIMP, "v@:");

再次編譯運(yùn)行,此時(shí)輸出正如前面所推斷的那樣:

  >> Bar() in Foo.
  >> Instance resolving MissMethod
  objc[1618]: +[Foo resolveInstanceMethod:MissMethod] returned YES, but no new implementation of -[Foo MissMethod] was found
  >> forwardInvocation for selector MissMethod
  >> MissMethod() called in Proxy.
  >> Instance resolving _doZombieMe

進(jìn)行了消息轉(zhuǎn)發(fā)!而且編譯器很善意地提示(見前面源碼剖析):哎呀,你不能欺騙我嘛,你說添加了實(shí)現(xiàn)(返回YES),其實(shí)還是沒有呀!然后編譯器就無奈地去看能不能消息轉(zhuǎn)發(fā)了。當(dāng)然如果把返回值修改為 NO 就不會(huì)有該警告出現(xiàn),其他的輸出不變。

 

五,總結(jié)

從上面的示例演示可以看出,動(dòng)態(tài)方法決議是先于消息轉(zhuǎn)發(fā)的。

如果向一個(gè) Objective C 對(duì)象對(duì)象發(fā)送它無法處理的消息(selector),那么編譯器會(huì)按照如下次序進(jìn)行處理:

1,首先看是否為該 selector 提供了動(dòng)態(tài)方法決議機(jī)制,如果提供了則轉(zhuǎn)到 2;如果沒有提供則轉(zhuǎn)到 3;

2,如果動(dòng)態(tài)方法決議真正為該 selector 提供了實(shí)現(xiàn),那么就調(diào)用該實(shí)現(xiàn),完成消息發(fā)送流程,消息轉(zhuǎn)發(fā)就不會(huì)進(jìn)行了;如果沒有提供,則轉(zhuǎn)到 3;

3,其次看是否為該 selector 提供了消息轉(zhuǎn)發(fā)機(jī)制,如果提供了消息了則進(jìn)行消息轉(zhuǎn)發(fā),此時(shí),無論消息轉(zhuǎn)發(fā)是怎樣實(shí)現(xiàn)的,程序均不會(huì) crash。(因?yàn)橄⒄{(diào)用的控制權(quán)完全交給消息轉(zhuǎn)發(fā)機(jī)制處理,即使消息轉(zhuǎn)發(fā)并沒有做任何事情,運(yùn)行也不會(huì)有錯(cuò)誤,編譯器更不會(huì)有錯(cuò)誤提示。);如果沒提供消息轉(zhuǎn)發(fā)機(jī)制,則轉(zhuǎn)到 4;

4,運(yùn)行報(bào)錯(cuò):無法識(shí)別的 selector,程序 crash;

 

六,引用

官方運(yùn)行時(shí)源代碼:http://www.opensource.apple.com/source/objc4/objc4-532/runtime/

Objective-C Runtime Programming Guide

深入淺出Cocoa之消息

深入淺出Cocoa之類與對(duì)象

posted on 2012-11-14 23:53 羅朝輝 閱讀(2374) 評(píng)論(0)  編輯 收藏 引用 所屬分類: Cocoa 開發(fā)
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产精品乱码| 亚洲欧美激情诱惑| 亚洲永久精品大片| 亚洲欧洲日产国产综合网| 一区二区日韩伦理片| 亚洲高清av| 欧美日韩精品在线观看| 亚洲欧美日韩国产一区| 午夜精品国产| 亚洲精品一二区| 亚洲专区一二三| 亚洲国产成人av在线| 99精品欧美| 精品动漫3d一区二区三区免费版| 亚洲国产精品精华液2区45| 欧美三级欧美一级| 蜜乳av另类精品一区二区| 欧美美女视频| 蜜臀av在线播放一区二区三区| 欧美第十八页| 欧美国产日韩a欧美在线观看| 国产精品国产精品| 91久久线看在观草草青青| 国产一区二区三区在线观看免费视频| 最新成人av在线| 亚洲精品偷拍| 欧美大香线蕉线伊人久久国产精品| 久久精品国产亚洲aⅴ| 国产精品theporn88| 亚洲乱码精品一二三四区日韩在线| 亚洲大胆女人| 欧美国产专区| 亚洲免费成人av电影| 99国产精品久久久久久久成人热| 久久裸体艺术| 欧美国产日韩精品| 亚洲国产一二三| 久久手机精品视频| 欧美成人a∨高清免费观看| 国产最新精品精品你懂的| 久久男女视频| 亚洲精品视频免费| 先锋a资源在线看亚洲| 国产视频精品va久久久久久| 在线电影一区| 久久精品伊人| 牛牛精品成人免费视频| 一本色道久久综合亚洲精品不 | 老色鬼精品视频在线观看播放| 在线看国产日韩| 亚洲精品日本| 国产在线日韩| 亚洲精品女人| 欧美性猛交99久久久久99按摩| 久久精品一区二区三区四区| 老司机精品导航| 午夜精品视频在线| 美女国产精品| 香蕉成人伊视频在线观看| 久久全国免费视频| 亚洲毛片在线看| 久久国产视频网站| 日韩亚洲精品在线| 欧美在线观看一二区| 亚洲深夜福利在线| 久久一区激情| 久久久久成人精品免费播放动漫| 欧美精品三级| 欧美不卡视频| 国产亚洲网站| 亚洲网站在线看| 99视频精品| 欧美激情国产日韩| 免费一级欧美片在线播放| 国产日韩成人精品| 这里只有精品丝袜| 亚洲四色影视在线观看| 欧美精品www| 亚洲二区在线观看| 雨宫琴音一区二区在线| 欧美一级午夜免费电影| 欧美一区二区三区四区在线观看 | 亚洲欧美中文另类| 欧美精品亚洲一区二区在线播放| 久久综合999| 国外成人在线视频网站| 午夜在线视频一区二区区别| 亚洲欧美日韩在线综合| 欧美天天综合网| 一区二区三区精密机械公司| 亚洲香蕉伊综合在人在线视看| 欧美日韩国产小视频在线观看| 亚洲精品国精品久久99热一| 宅男噜噜噜66一区二区| 欧美日韩高清不卡| 日韩视频在线观看国产| 在线视频中文亚洲| 欧美日韩亚洲精品内裤| 亚洲一区二区在| 性欧美8khd高清极品| 9国产精品视频| 一区二区三区鲁丝不卡| 亚洲大胆女人| 欧美中文在线观看| 久久精品中文字幕一区| 欧美一区二区在线| 久久本道综合色狠狠五月| 国产精品综合av一区二区国产馆| 一区二区三区偷拍| 亚洲女爱视频在线| 亚洲欧美日韩区| 欧美在线免费视频| 欧美日韩美女在线| 一区二区成人精品| 羞羞色国产精品| 国产一区二区视频在线观看| 久久国产主播| 美女爽到呻吟久久久久| 日韩亚洲欧美精品| 国产精品av免费在线观看| 亚洲欧美在线免费观看| 久久综合给合| 一区二区欧美在线| 国产日韩精品一区二区浪潮av| 久久精品欧美| 亚洲黄色成人久久久| 香蕉av福利精品导航| 伊人久久久大香线蕉综合直播 | 欧美一级播放| 欧美r片在线| 亚洲一区二区三区成人在线视频精品| 国产伦精品一区二区三区免费迷 | 国产日韩精品视频一区| 久久综合免费视频影院| 中文有码久久| 欧美电影免费观看| 亚洲一区二区在线视频 | 欧美另类一区二区三区| 亚洲无亚洲人成网站77777| 狼人天天伊人久久| 一区二区三区四区国产| 影音先锋欧美精品| 国产精品视频yy9299一区| 麻豆精品在线视频| 午夜精品美女自拍福到在线| 亚洲激情综合| 久久视频精品在线| 亚洲视频www| 亚洲精品久久久久中文字幕欢迎你| 国产精品一区毛片| 欧美精品在线免费| 久久久久久精| 亚洲欧美日韩综合aⅴ视频| 亚洲精品乱码| 亚洲第一色中文字幕| 美女久久一区| 久久久久久欧美| 亚洲欧美一区在线| 一区二区欧美在线| 亚洲欧美国产77777| 亚洲精品免费在线| 国产精品卡一卡二| 久久成人精品一区二区三区| 欧美伊人久久大香线蕉综合69| 国产午夜精品理论片a级大结局| 蜜桃视频一区| 国产精品高潮久久| 另类图片国产| 久久本道综合色狠狠五月| 亚洲高清一区二| 国内揄拍国内精品少妇国语| 国产精品久久一区主播| 欧美日韩视频免费播放| 欧美大片国产精品| 欧美电影电视剧在线观看| 免费亚洲一区二区| 美日韩精品视频免费看| 媚黑女一区二区| 免费不卡在线观看| 欧美肥婆在线| 欧美精品在线极品| 欧美午夜大胆人体| 国产精品亚洲а∨天堂免在线| 国产精品亚洲综合久久| 国产精品一区二区三区四区 | 麻豆精品视频在线| 久久在线观看视频| 欧美freesex交免费视频| 免费成人在线视频网站| 模特精品裸拍一区| 欧美精品久久久久久久免费观看| 欧美日韩午夜视频在线观看| 国产精品高潮呻吟久久| 国产麻豆精品视频| 韩国av一区二区三区| 亚洲国产美国国产综合一区二区| 99成人免费视频| 亚洲欧美一区二区视频| 久久久久免费视频| 欧美国产日韩在线|