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

羅朝輝(飄飄白云)

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

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

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

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

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

序言

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

本文代碼下載:點此下載

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

如下代碼:

@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;
}

在編譯時,XCode 會提示警告:

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

如果,我們忽視該警告運行之,一定會 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 的原因:對象無法處理 MissMethod 對應的 selector,也就是沒有相應的實現(xiàn)。

 

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

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

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

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

下面我們用動態(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ù)(self 和 _cmd)的普通 C 函數(shù),因此在上面的代碼中提供這樣一個 C 函數(shù) dynamicMethodIMP,讓它來充當對象方法 MissMethod 這個 selector 的動態(tài)實現(xiàn)。因為 MissMethod 是被對象所調(diào)用,所以它被認為是一個對象方法,因而應該在 resolveInstanceMethod 方法中為其提供實現(xiàn)。通過調(diào)用

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

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

再次編譯運行前面的測試代碼,輸出如下:

  >> 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)下第一個決議 MissMethod,第二個決議 _doZombieMe;在 10.6 系統(tǒng)下兩次都是決議 MissMethod。

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

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

再次編譯運行,此時輸出:

 >> 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,但是并沒有真正提供實現(xiàn),被編譯器發(fā)覺而提示相應的錯誤信息。那它的返回值到底有什么作用呢,在它沒有提供真正的實現(xiàn),并且提供了消息轉(zhuǎn)發(fā)機制的情況下,YES 表示不進行后續(xù)的消息轉(zhuǎn)發(fā),返回  NO 則表示要進行后續(xù)的消息轉(zhuǎn)發(fā)。

 

三,源碼剖析

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

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

/***********************************************************************
* _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,類方法決議與實例方法決議大體相似,在這里就只看實例方法決議部分了:

/***********************************************************************
 * _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;
    
    // 是否實現(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)成功添加實現(xiàn),則再次查找 method list 
        
// +resolveClassMethod adds to self
        meth = look_up_method(cls, sel, YES/*cache*/, NO/*resolver*/);
        
        if (!meth) {
            // resolveInstanceMethod 使詐了,它聲稱成功添加實現(xiàn)了,但實際沒有,給出警告信息,并返回 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,首先判斷是否實現(xiàn)了 resolveInstanceMethod,如果沒有實現(xiàn),返回 NULL,進入下一步處理;

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

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

4,如果返回值為 NO,返回 NULL,進入下一步處理;

 

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

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

// 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

運行測試代碼,輸出如下:

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

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

@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

此時,輸出為:

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

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

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

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

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

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

再次編譯運行,此時輸出正如前面所推斷的那樣:

  >> 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

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

 

五,總結

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

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

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

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

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

4,運行報錯:無法識別的 selector,程序 crash;

 

六,引用

官方運行時源代碼:http://www.opensource.apple.com/source/objc4/objc4-532/runtime/

Objective-C Runtime Programming Guide

深入淺出Cocoa之消息

深入淺出Cocoa之類與對象

posted on 2012-11-14 23:53 羅朝輝 閱讀(2374) 評論(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>
            亚洲天堂成人在线观看| 欧美综合第一页| 欧美视频久久| 免费观看亚洲视频大全| 久久人人爽人人爽爽久久| 久久久久国产一区二区三区四区| 欧美资源在线| 久久综合色婷婷| 欧美日本在线播放| 国产精品一区二区男女羞羞无遮挡| 国产精品任我爽爆在线播放| 国产欧美韩国高清| 亚洲国产成人久久综合| 亚洲视频观看| 亚洲精品日本| 久久久欧美精品sm网站| 欧美xart系列高清| 日韩亚洲欧美中文三级| 午夜久久黄色| 麻豆精品网站| 国产伦精品一区二区三区照片91| 精品成人一区二区三区| 日韩一区二区电影网| 欧美在线亚洲在线| 亚洲国产一区二区三区高清| 亚洲欧洲一区| 久久电影一区| 欧美色大人视频| 尤物在线精品| 午夜久久电影网| 亚洲国产黄色片| 午夜免费在线观看精品视频| 欧美激情综合网| 在线成人www免费观看视频| 亚洲一区三区视频在线观看| 欧美电影免费观看高清完整版| 亚洲午夜久久久久久久久电影院 | 久久久久久久成人| 一本久久综合| 欧美精品 国产精品| 精品1区2区3区4区| 欧美一区二区三区免费观看 | 亚洲毛片在线观看.| 久久久久久成人| 国产日韩精品视频一区二区三区| 一区二区久久久久久| 亚洲第一成人在线| 久久9热精品视频| 国产麻豆精品theporn| 在线视频中文亚洲| 亚洲欧洲精品天堂一级| 免费在线看成人av| 亚洲国产欧美久久| 欧美成人精品| 久久蜜桃香蕉精品一区二区三区| 国产日韩欧美高清| 久久久精品网| 久久久夜夜夜| 亚洲人体偷拍| 亚洲国产精品一区制服丝袜| 欧美1级日本1级| 亚洲精品一区二区三区在线观看| 裸体素人女欧美日韩| 久久久久久香蕉网| 亚洲国产精品女人久久久| 欧美阿v一级看视频| 老色鬼久久亚洲一区二区| 在线观看亚洲视频| 欧美电影在线观看| 欧美精品在线视频观看| 久久精品亚洲一区二区| 久久精品亚洲乱码伦伦中文 | 在线激情影院一区| 欧美韩国在线| 欧美日韩一区二区三区在线| 亚洲欧美成人精品| 性色av一区二区三区在线观看 | 久热re这里精品视频在线6| 亚洲韩国精品一区| 日韩视频精品| 国产色综合久久| 欧美大片在线观看一区| 欧美日韩第一区| 久久福利毛片| 欧美成人一区二区在线| 亚洲一区二区在线| 久久九九热免费视频| 亚洲剧情一区二区| 亚洲综合社区| 亚洲精品无人区| 亚洲一级在线观看| 亚洲国产精品一区二区www| 亚洲靠逼com| 国产亚洲精品v| 91久久国产综合久久| 国产欧美日韩视频在线观看| 欧美电影资源| 欧美午夜大胆人体| 久久综合激情| 欧美日韩国产美| 久久蜜桃香蕉精品一区二区三区| 欧美精品麻豆| 欧美99在线视频观看| 国产伦精品一区二区三区| 麻豆久久精品| 国产农村妇女精品一二区| 亚洲国产日日夜夜| 韩日欧美一区二区| 一区二区不卡在线视频 午夜欧美不卡在| 国模精品一区二区三区| 亚洲天堂成人在线观看| 亚洲精品久久久久久下一站| 欧美一区二区三区在| 亚洲综合精品| 欧美精品成人91久久久久久久| 久久人人爽人人| 国产人成一区二区三区影院| 一二三区精品福利视频| 在线日韩中文字幕| 久久国产视频网站| 久久久91精品国产| 国产免费成人| 亚洲一区二区三区高清不卡| 亚洲最新视频在线| 免费欧美日韩| 久久免费少妇高潮久久精品99| 国产精品久久久久久久久果冻传媒| 亚洲国产黄色| 亚洲精品视频在线观看免费| 在线综合+亚洲+欧美中文字幕| 亚洲性人人天天夜夜摸| 亚洲视频在线一区| 欧美国产三级| 亚洲精品视频在线播放| 日韩系列欧美系列| 欧美极品欧美精品欧美视频| 亚洲黄色av一区| 日韩一级欧洲| 欧美三级日本三级少妇99| 日韩一级免费| 午夜电影亚洲| 国产伦精品一区| 欧美在线免费观看视频| 久久女同互慰一区二区三区| 国产综合色在线视频区| 久久久久99| 亚洲黑丝在线| 亚洲一区免费视频| 国产日韩一区二区| 久久久久久久波多野高潮日日| 麻豆亚洲精品| 最新国产成人av网站网址麻豆 | 日韩视频一区二区三区| 亚洲视频一二区| 国产精一区二区三区| 久久成人人人人精品欧| 你懂的视频一区二区| 日韩一级黄色片| 国产精品夜夜嗨| 久久综合一区| 一区二区黄色| 久久婷婷久久| 一区二区成人精品| 国产一区二区三区在线观看免费 | 免费观看成人| 亚洲精品看片| 国产精品一区在线观看你懂的| 久久久久**毛片大全| 夜夜嗨av一区二区三区免费区| 久久国产主播| 一区二区欧美日韩| 国产一区三区三区| 欧美日本亚洲韩国国产| 午夜精品美女自拍福到在线| 亚洲国产专区| 麻豆视频一区二区| 亚洲欧美成人精品| 亚洲日本国产| 国模精品一区二区三区| 国产精品v片在线观看不卡| 久久精品国产久精国产爱| 亚洲美女精品成人在线视频| 久久米奇亚洲| 亚洲欧美日韩直播| 亚洲精品视频免费观看| 国产日本欧美一区二区| 欧美日韩一区二区精品| 嫩模写真一区二区三区三州| 欧美一区二区成人| 一个人看的www久久| 亚洲激情电影在线| 欧美电影免费观看大全| 久久久久国产精品人| 亚洲一区区二区| 一本到12不卡视频在线dvd| 黄色国产精品一区二区三区| 国产精品日韩欧美一区二区三区| 欧美日韩精品免费观看视频| 亚洲欧美www| 一区二区欧美日韩|