iOS之runtime詳解api(一)

什么是runtime苞冯?

runtime在iOS中是“運行時”的含義羡宙,是一套用c語言寫的api,很多人會用但是也僅僅用過最最常用的幾個函數(shù)孵坚,這次徐矩,我將詳細的帶著大家探索下runtime的API滞时,這一章就說下<objc/runtime.h>這個文件里的API,并且我會把不適用于ARC和不支持64位的API剔除掉。

1.Class相關(guān)

首先滤灯,我們先看一個簡單的函數(shù):

const char * _Nonnull
class_getName(Class _Nullable cls)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);

這個函數(shù)是通過傳入Class類型的cls來得到Class的名字坪稽。那我們測試下這個函數(shù):

-(void)getName {
    const char* name = class_getName([Person class]);
    NSLog(@"name = %s",name);
}

其中[Person class]OC中獲得Class的方法,當然鳞骤,你也可以用runtime里面的objc_getClass等函數(shù)窒百,后面我也會講到。
運行結(jié)果:

name = Person

我們可以看到打印出來的結(jié)果就是類的名字豫尽。
上面既然用到了[Person class]篙梢,那我們就看下在runtime[Person class]的替代函數(shù),都是通過名字來獲得Class

Class _Nullable
objc_getClass(const char * _Nonnull name)
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);

Class _Nullable
objc_lookUpClass(const char * _Nonnull name)
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);

Class _Nonnull
objc_getRequiredClass(const char * _Nonnull name)
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);

那這三個有什么區(qū)別美旧,從結(jié)論上講渤滞,objc_getClassobjc_lookUpClass的效果是一致的,在最新的源碼里面榴嗅,這兩個方法調(diào)用的底層也是一致的妄呕,當你要找的類不存在的話,就返回nil嗽测,而objc_getRequiredClass里你要找的類不存在的話绪励,就會崩潰。下面我們來測試下唠粥,我們創(chuàng)建一個Person類疏魏。

-(void)getClass {
    const char* name = "Person1";
    const char* name_exist = "Person";
    Class class1_exist = objc_getClass(name_exist );
    NSLog(@"class1_exist = %@",class1_exist);

    Class class1 = objc_getClass(name);
    NSLog(@"class1 = %@",class1);
    Class class2_exist = objc_lookUpClass(name_exist );
    NSLog(@"class2_exist = %@",class2_exist);
    Class class2 = objc_lookUpClass(name );
    NSLog(@"class2 = %@",class2);

    Class class3_exist = objc_getRequiredClass(name_exist );
    NSLog(@"class3_exist = %@",class3_exist);
    Class class3 = objc_getRequiredClass(name );
    NSLog(@"class3 = %@",class3);
}

運行結(jié)果:

2019-02-21 16:58:39.173892+0800 Runtime-Demo[91840:2890084] class1_exist = Person
2019-02-21 16:58:39.173939+0800 Runtime-Demo[91840:2890084] class1 = (null)
2019-02-21 16:58:39.173951+0800 Runtime-Demo[91840:2890084] class2_exist = Person
2019-02-21 16:58:39.173960+0800 Runtime-Demo[91840:2890084] class2 = (null)
2019-02-21 16:58:39.173969+0800 Runtime-Demo[91840:2890084] class3_exist = Person
objc[91840]: link error: class 'Person1' not found.

最后也確實崩潰了,所以大家使用objc_getRequiredClass這個函數(shù)時候要慎重小心晤愧。
除了用名字獲得類對象以外大莫,還可以用實例對象來獲取:

Class _Nullable
object_getClass(id _Nullable obj)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);

我們測試下:

-(void)getClassWithObjc {
    Person* person = [Person new];
    Class class = object_getClass(person);
    NSLog(@"class = %@",class);
}

運行結(jié)果:

class = Person

完全沒問題养涮。
Class不僅可以代表類對象葵硕,也可以代表元類對象眉抬,下面這個函數(shù)就是通過名字獲取元類對象贯吓。

Class _Nullable
objc_getMetaClass(const char * _Nonnull name)
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);

如果你讀過源碼的話懈凹,你就會清楚元類對象儲存的是類方法,類對象儲存的是實例方法悄谐,在后面講到Method相關(guān)的API的時候介评,我們在具體講他們之間的區(qū)別。

講到元類對象爬舰,我們還要關(guān)注下這個函數(shù)们陆,

BOOL
class_isMetaClass(Class _Nullable cls)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);

這個函數(shù)是用來判斷是否是元類對象。

-(void)isMetaClass {
    const char* name = "Person";
    BOOL isMetaClass1 = class_isMetaClass(objc_getMetaClass(name ));
    BOOL isMetaClass2 = class_isMetaClass(objc_getClass(name));
    NSLog(@"objc_getMetaClass = %d,objc_getClass = %d",isMetaClass1,isMetaClass2);
}

運行結(jié)果:

objc_getMetaClass = 1,objc_getClass = 0

我們可以看到objc_getMetaClass生成才是元類對象情屹,objc_getClass生成的只是類對象坪仇。
那么有沒有函數(shù)區(qū)分類(元類)對象和實例對象呢?當然有:

BOOL
object_isClass(id _Nullable obj)
OBJC_AVAILABLE(10.10, 8.0, 9.0, 1.0, 2.0);

這個方法只要是類對象或者元類對象都會返回YES:

-(void)isClass {
    Person* person = [Person new];
    BOOL isClass_objc = object_isClass(person);
    BOOL isClass_class = object_isClass(objc_getClass("Person"));
    BOOL isClass_metaClass = object_isClass(objc_getMetaClass("Person"));

    NSLog(@"isClass_objc = %d  isClass_class = %d  isClass_metaClass = %d",isClass_objc,isClass_class,isClass_metaClass);
}

運行結(jié)果:

isClass_objc = 0  isClass_class = 1  isClass_metaClass = 1

當然也可以獲得父類對象垃你。

Class _Nullable
class_getSuperclass(Class _Nullable cls)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);

我們新建一個繼承Person的類Student椅文,然后我們通過Student類來獲得Person類。

-(void)getSuperclass {
    Class class = class_getSuperclass(objc_getClass("Student"));
    NSLog(@"class = %@",class);
}

運行結(jié)果:

class = Person

Student的父類確實是Person惜颇。

我們知道OC里面可以強轉(zhuǎn)類型皆刺,當然,runtime里面也有相關(guān)方法

Class _Nullable
object_setClass(id _Nullable obj, Class _Nonnull cls)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);

這個方法的意思是給一個實例對象設(shè)置新的類凌摄,返回舊的類

-(void)setClass {
    Student* student = [Student new];
    Class class = object_setClass(student, objc_getClass("Person"));
    NSLog(@"oldClass = %@",class);
    NSLog(@"newStudent = %@",student);
}

運行結(jié)果:

2019-02-21 17:38:17.388341+0800 Runtime-Demo[92493:2904857] oldClass = Student
2019-02-21 17:38:17.388413+0800 Runtime-Demo[92493:2904857] newStudent = <Person: 0x282dd8b50>

我們可以看出開始的時候student的類是Student羡蛾,用了object_setClass后就是Person類了。
runtime的動態(tài)性還可以動態(tài)新增類锨亏,下面四個函數(shù)分別表示為一個類分配內(nèi)存痴怨,注冊一個類,復制一個類器予,銷毀一個類

Class _Nullable
objc_allocateClassPair(Class _Nullable superclass, const char * _Nonnull name,
                       size_t extraBytes)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);

創(chuàng)建一個新類浪藻,superclass是新類所繼承的類,如果為nil劣摇,superclass就默認為根類珠移,也就是NSObjectextraBytes是在類和元類對象的末尾為索引ivars分配的字節(jié)數(shù)末融。這一般是0钧惧,name是新類的名字。

void
objc_registerClassPair(Class _Nonnull cls)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);

注冊類勾习,如果這個類objc_allocateClassPair好了浓瞪,就必須objc_registerClassPair才能使用。

Class _Nonnull
objc_duplicateClass(Class _Nonnull original, const char * _Nonnull name,
                    size_t extraBytes)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);

這個方法在系統(tǒng)KVO的底層用過巧婶,系統(tǒng)不推薦我們自己用乾颁。

 void
objc_disposeClassPair(Class _Nonnull cls)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);

objc_disposeClassPair只能銷毀通過objc_allocateClassPair創(chuàng)建的類涂乌。
我們寫個demo來測試這些方法,objc_duplicateClass官方不建議使用英岭,那么我們就不測試這函數(shù)湾盒。

-(void)classLifeCycle {
    Class class = objc_allocateClassPair(objc_getClass("Person"), "Teacher" , 0);
    const char* name = class_getName(class);
    Class allocateClass = objc_getClass(name);
    NSLog(@"allocateClass = %@",allocateClass);
    
    objc_registerClassPair(class);
    Class registerClass = objc_getClass(name);
    NSLog(@"registerClass = %@",registerClass);
    
    objc_disposeClassPair(class);
    Class disposeClass = objc_getClass(name);
    NSLog(@"disposeClass = %@",disposeClass);
}

運行結(jié)果:

2019-02-22 09:37:52.705001+0800 Runtime-Demo[99587:3143177] allocateClass = (null)
2019-02-22 09:37:52.705049+0800 Runtime-Demo[99587:3143177] registerClass = Teacher
2019-02-22 09:37:52.705071+0800 Runtime-Demo[99587:3143177] disposeClass = (null)

我們可以知道如果僅僅只是objc_allocateClassPair的話,你是找不到這個類的诅妹,必須再objc_registerClassPair才可以找到罚勾,objc_disposeClassPair則是把類銷毀掉,所以再實際開發(fā)中吭狡,如果我們不再使用自建類的時候尖殃,就要及時銷毀,節(jié)省內(nèi)存划煮。

下面兩個函數(shù)是關(guān)于整個工程的類列表的函數(shù):

Class _Nonnull * _Nullable
objc_copyClassList(unsigned int * _Nullable outCount)
OBJC_AVAILABLE(10.7, 3.1, 9.0, 1.0, 2.0);

這個函數(shù)是獲得所有注冊類的列表送丰,我們試用下:

-(void)copyClassList {
    unsigned int outCount;
    Class *classes = objc_copyClassList(&outCount);
    NSLog(@"outCount = %d",outCount);
    for (int i = 0; i < outCount; i++) {
        NSLog(@"%s", class_getName(classes[i]));
    }
    free(classes);
}

運行結(jié)果:

2019-02-22 09:52:12.218871+0800 Runtime-Demo[99840:3149922] outCount = 15765
2019-02-22 09:52:12.218939+0800 Runtime-Demo[99840:3149922] _CNZombie_
2019-02-22 09:52:12.218953+0800 Runtime-Demo[99840:3149922] JSExport
2019-02-22 09:52:12.218963+0800 Runtime-Demo[99840:3149922] NSLeafProxy
......
......

我們看到注冊的類有15765個。
objc_getClassList也是獲取注冊類的方法.

int
objc_getClassList(Class _Nonnull * _Nullable buffer, int bufferCount)
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);

第一個參數(shù)buffer已分配好內(nèi)存空間的數(shù)組指針弛秋,bufferCount是數(shù)組的個數(shù)器躏,如果bufferCount的數(shù)量小于實際的數(shù)組數(shù)量,那么buffer返回的是所有數(shù)組集合的任意一個子類铐懊。如果buffer為NULL邀桑,那么bufferCount為0。無論那種情況科乎,返回結(jié)果都是當前注冊類的總數(shù)壁畸。

-(void)getClassList {
    int bufferCount = 4;
    Class* buffer = (Class*)malloc(sizeof(Class)* bufferCount);
    int count1 = objc_getClassList(buffer, bufferCount);
    for (unsigned int i =0; i <bufferCount; i++) {
        NSLog(@"name = %s",class_getName(buffer[i]));
    }
    NSLog(@"count1 = %d",count1);

    int count2 = objc_getClassList(NULL, 0);
    NSLog(@"count2 = %d",count2);
}

運行結(jié)果:

2019-02-22 10:14:34.487051+0800 Runtime-Demo[354:3159864] name = _CNZombie_
2019-02-22 10:14:34.487145+0800 Runtime-Demo[354:3159864] name = JSExport
2019-02-22 10:14:34.487158+0800 Runtime-Demo[354:3159864] name = NSLeafProxy
2019-02-22 10:14:34.487173+0800 Runtime-Demo[354:3159864] name = NSProxy
2019-02-22 10:14:34.487186+0800 Runtime-Demo[354:3159864] count1 = 15765
2019-02-22 10:14:34.493662+0800 Runtime-Demo[354:3159864] count2 = 15765
size_t
class_getInstanceSize(Class _Nullable cls)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);

返回類實例的大小。

-(void)getInstanceSize {
    size_t size = class_getInstanceSize(objc_getClass("Person"));
    NSLog(@"size = %zu",size);
}

運行結(jié)果

size = 8

一個沒有變量或?qū)傩缘睦^承于NSObject的類占有8個字節(jié)茅茂。
還有個方法是:

id _Nullable
class_createInstance(Class _Nullable cls, size_t extraBytes)
OBJC_RETURNS_RETAINED
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);

這是一個創(chuàng)建實例的方法捏萍,cls是要創(chuàng)建的類,extraBytes是額外的字節(jié)內(nèi)存空闲,用來存儲類定義中的實例變量之外的其他實例變量令杈。在源碼中alloc方法底層就是用的這個函數(shù)。那么碴倾,我們用這個函數(shù)來初始化Person類:

-(void)createInstance {
    Person* person = class_createInstance(objc_getClass("Person"), 0);
    NSLog(@"%@",person);
}

運行結(jié)果:

<Person: 0x60000343d2f0>

確實能夠成功創(chuàng)建出來逗噩。
最后剩下兩個方法:

int
class_getVersion(Class _Nullable cls)
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);

void
class_setVersion(Class _Nullable cls, int version)
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);

這兩個方法都和version有關(guān),這個version在實際中我也沒發(fā)現(xiàn)用處跌榔,可能是在改變類的變量或者方法時給定一個標識.

-(void)version {
    int verson = class_getVersion(objc_getClass("Person"));
    NSLog(@"version = %d",verson);
    class_setVersion(objc_getClass("Person"), 10);
    int newVersion = class_getVersion(objc_getClass("Person"));
    NSLog(@"newVersion = %d",newVersion);
}

運行結(jié)果

2019-02-22 11:29:57.325309+0800 Runtime-Demo[526:167322] version = 0
2019-02-22 11:29:57.325349+0800 Runtime-Demo[526:167322] newVersion = 10

2.objc_category or Category

下面我們將使用runtime里面最最常用的api异雁,也就是給分類綁定對象,這里僧须,我們先了解下纲刀,一個枚舉:

typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {
    OBJC_ASSOCIATION_ASSIGN = 0,           /**< Specifies a weak reference to the associated object. */
    OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, /**< Specifies a strong reference to the associated object.
                                            *   The association is not made atomically. */
    OBJC_ASSOCIATION_COPY_NONATOMIC = 3,   /**< Specifies that the associated object is copied.
                                            *   The association is not made atomically. */
    OBJC_ASSOCIATION_RETAIN = 01401,       /**< Specifies a strong reference to the associated object.
                                            *   The association is made atomically. */
    OBJC_ASSOCIATION_COPY = 01403          /**< Specifies that the associated object is copied.
                                            *   The association is made atomically. */
};

objc_AssociationPolicy是一個枚舉,里面的枚舉值分別代表要添加的屬性的修飾類型担平。
OBJC_ASSOCIATION_ASSIGN相當于weak
OBJC_ASSOCIATION_RETAIN_NONATOMIC相當于strongnonatomic
OBJC_ASSOCIATION_COPY_NONATOMIC相當于copynonatomic
OBJC_ASSOCIATION_RETAIN相當于strongatomic
OBJC_ASSOCIATION_COPY相當于copyatomic
關(guān)于分類的runtime函數(shù)示绊,主要有下面3個:

void
objc_setAssociatedObject(id _Nonnull object, const void * _Nonnull key,
                         id _Nullable value, objc_AssociationPolicy policy)
OBJC_AVAILABLE(10.6, 3.1, 9.0, 1.0, 2.0);

id _Nullable
objc_getAssociatedObject(id _Nonnull object, const void * _Nonnull key)
OBJC_AVAILABLE(10.6, 3.1, 9.0, 1.0, 2.0);

void
objc_removeAssociatedObjects(id _Nonnull object)
OBJC_AVAILABLE(10.6, 3.1, 9.0, 1.0, 2.0);

含義分別為設(shè)置關(guān)聯(lián)對象锭部,獲得關(guān)聯(lián)對象,刪除關(guān)聯(lián)對象面褐。
我們知道如果在分類的.h文件設(shè)置屬性并沒有用拌禾,調(diào)用的時候會發(fā)生閃退,這是因為系統(tǒng)并沒有自動為屬性生成SetGet方法盆耽,所以蹋砚,我們用上面三個方法來手動關(guān)聯(lián)對象扼菠。
我們創(chuàng)建一個 Person的分類Person+Actor.h摄杂,在.h文件里新建一個新屬性@property(nonatomic, assign)float actingSkill而不做其他任何處理,這時候循榆,.m文件就會有警告析恢。

屏幕快照 2019-02-23 下午12.41.52.png

這就告訴我們需要手動實現(xiàn)setActingSkill:actingSkill方法:
.m文件

#import "Person+Actor.h"
#import <objc/runtime.h>
static const char* key = "actingSkill";
@implementation Person (Actor)

-(void)setActingSkill:(float)actingSkill {
    NSNumber *actingSkillObjc = [NSNumber numberWithFloat:actingSkill];
    objc_setAssociatedObject(self, key, actingSkillObjc, OBJC_ASSOCIATION_RETAIN);
}

-(float)actingSkill {
    NSNumber *actingSkillObjc = objc_getAssociatedObject(self, key);
    return [actingSkillObjc floatValue];
}

@end

這時候就綁定好了。
ViewController里面去使用下這個屬性

-(void)testCategory {
    _person = [Person new];
    _person.actingSkill = 0.1;
    NSLog(@"actingSkill = %f",_person.actingSkill);
}

運行結(jié)果:

actingSkill = 0.100000

說明set和get方法都成功了秧饮。
那么還有一個objc_removeAssociatedObjects方法還沒用映挂,這個方法是解除綁定,為了測試這個效果盗尸,我們在ViewController里面touchesBegan里面去調(diào)用這個方法柑船。

-(void)testCategory {
    _person = [Person new];
    _person.actingSkill = 0.1;
    NSLog(@"actingSkill = %f",_person.actingSkill);
}


- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [super touchesBegan:touches withEvent:event];
    if (_person) {
        objc_removeAssociatedObjects(_person);
        NSLog(@"actingSkill2 = %f",_person.actingSkill);
    }
}

運行結(jié)果:

2019-02-23 13:21:13.090961+0800 Runtime-Demo[2964:201009] actingSkill = 0.100000
2019-02-23 13:24:24.585347+0800 Runtime-Demo[2964:201009] actingSkill2 = 0.000000

之前綁定的結(jié)果被移除了。
今天我們這一篇就講到這泼各,runtime還有很多其他的用法我們下一篇見鞍时。
對了,這個是demo扣蜻,喜歡的可以點個星逆巍。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市莽使,隨后出現(xiàn)的幾起案子锐极,更是在濱河造成了極大的恐慌,老刑警劉巖芳肌,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件灵再,死亡現(xiàn)場離奇詭異,居然都是意外死亡亿笤,警方通過查閱死者的電腦和手機翎迁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來责嚷,“玉大人鸳兽,你說我怎么就攤上這事『狈鳎” “怎么了揍异?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵全陨,是天一觀的道長。 經(jīng)常有香客問我衷掷,道長辱姨,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任戚嗅,我火速辦了婚禮雨涛,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘懦胞。我一直安慰自己替久,他們只是感情好,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布躏尉。 她就那樣靜靜地躺著蚯根,像睡著了一般。 火紅的嫁衣襯著肌膚如雪胀糜。 梳的紋絲不亂的頭發(fā)上颅拦,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機與錄音教藻,去河邊找鬼距帅。 笑死,一個胖子當著我的面吹牛括堤,可吹牛的內(nèi)容都是我干的碌秸。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼痊臭,長吁一口氣:“原來是場噩夢啊……” “哼哮肚!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起广匙,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤允趟,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后鸦致,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體潮剪,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年分唾,在試婚紗的時候發(fā)現(xiàn)自己被綠了抗碰。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡绽乔,死狀恐怖弧蝇,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤看疗,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布沙峻,位于F島的核電站,受9級特大地震影響两芳,放射性物質(zhì)發(fā)生泄漏摔寨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一怖辆、第九天 我趴在偏房一處隱蔽的房頂上張望是复。 院中可真熱鬧,春花似錦竖螃、人聲如沸淑廊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蒋纬。三九已至,卻和暖如春坚弱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背关摇。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工荒叶, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人输虱。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓些楣,卻偏偏與公主長得像,于是被迫代替她去往敵國和親宪睹。 傳聞我的和親對象是個殘疾皇子愁茁,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353

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

  • 參考鏈接: http://www.cnblogs.com/ioshe/p/5489086.html 簡介 Runt...
    樂樂的簡書閱讀 2,135評論 0 9
  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,709評論 0 9
  • 簡介 Runtime 又叫運行時亭病,是一套底層的 C 語言 API鹅很,其為 iOS 內(nèi)部的核心之一,我們平時編寫的 O...
    專業(yè)男神經(jīng)閱讀 906評論 0 2
  • 其實4.1號就該寫這篇的,因為這個題目就是為了一個人:“哥哥 張國榮” 我從小就是一個孤陋寡聞的人整袁,第一次對哥哥有...
    佛右扯閱讀 433評論 0 0
  • 再次感覺到無比的疲憊菠齿!這就是我現(xiàn)在的狀態(tài)! 都說坐昙,你不堅強绳匀,沒有人替你堅強。而我想說,我真的沒那么...
    聽風舞者閱讀 190評論 0 0