iOS進階之masonry細致入微_MASUtilities.h

這個文件區(qū)別于Masonry.h文件蚀瘸。打個比方:Masonry主外,是個爺們绢掰。MASUtilities主內(nèi)痒蓬,是個姑娘童擎。

接下來,讓我們來了解一下這個渾身上下都是“干貨”的姑娘攻晒。
#import <Foundation/Foundation.h>

#if TARGET_OS_IPHONE || TARGET_OS_TV

    #import <UIKit/UIKit.h>
    #define MAS_VIEW UIView
    #define MAS_VIEW_CONTROLLER UIViewController
    #define MASEdgeInsets UIEdgeInsets

    typedef UILayoutPriority MASLayoutPriority;
    static const MASLayoutPriority MASLayoutPriorityRequired = UILayoutPriorityRequired;
    static const MASLayoutPriority MASLayoutPriorityDefaultHigh = UILayoutPriorityDefaultHigh;
    static const MASLayoutPriority MASLayoutPriorityDefaultMedium = 500;
    static const MASLayoutPriority MASLayoutPriorityDefaultLow = UILayoutPriorityDefaultLow;
    static const MASLayoutPriority MASLayoutPriorityFittingSizeLevel = UILayoutPriorityFittingSizeLevel;

#elif TARGET_OS_MAC

    #import <AppKit/AppKit.h>
    #define MAS_VIEW NSView
    #define MASEdgeInsets NSEdgeInsets

    typedef NSLayoutPriority MASLayoutPriority;
    static const MASLayoutPriority MASLayoutPriorityRequired = NSLayoutPriorityRequired;
    static const MASLayoutPriority MASLayoutPriorityDefaultHigh = NSLayoutPriorityDefaultHigh;
    static const MASLayoutPriority MASLayoutPriorityDragThatCanResizeWindow = NSLayoutPriorityDragThatCanResizeWindow;
    static const MASLayoutPriority MASLayoutPriorityDefaultMedium = 501;
    static const MASLayoutPriority MASLayoutPriorityWindowSizeStayPut = NSLayoutPriorityWindowSizeStayPut;
    static const MASLayoutPriority MASLayoutPriorityDragThatCannotResizeWindow = NSLayoutPriorityDragThatCannotResizeWindow;
    static const MASLayoutPriority MASLayoutPriorityDefaultLow = NSLayoutPriorityDefaultLow;
    static const MASLayoutPriority MASLayoutPriorityFittingSizeCompression = NSLayoutPriorityFittingSizeCompression;

#endif

/**
 *  Allows you to attach keys to objects matching the variable names passed.
 *
 *  view1.mas_key = @"view1", view2.mas_key = @"view2";
 *
 *  is equivalent to:
 *
 *  MASAttachKeys(view1, view2);
 */
#define MASAttachKeys(...)                                                        \
    {                                                                             \
        NSDictionary *keyPairs = NSDictionaryOfVariableBindings(__VA_ARGS__);     \
        for (id key in keyPairs.allKeys) {                                        \
            id obj = keyPairs[key];                                               \
            NSAssert([obj respondsToSelector:@selector(setMas_key:)],             \
                 @"Cannot attach mas_key to %@", obj);                        \
            [obj setMas_key:key];                                                 \
        }                                                                         \
    }

/**
 *  Used to create object hashes
 *  Based on http://www.mikeash.com/pyblog/friday-qa-2010-06-18-implementing-equality-and-    hashing.html
*/
#define MAS_NSUINT_BIT (CHAR_BIT * sizeof(NSUInteger))
#define MAS_NSUINTROTATE(val, howmuch) ((((NSUInteger)val) << howmuch) | (((NSUInteger)val) >> (MAS_NSUINT_BIT - howmuch)))

/**
 *  Given a scalar or struct value, wraps it in NSValue
 *  Based on EXPObjectify: https://github.com/specta/expecta
 */
/**
 *  inline關鍵字用來定義一個類的內(nèi)聯(lián)函數(shù)顾复,引入它的主要原因是用它替代C中表達式形式的宏定義。
 */
static inline id _MASBoxValue(const char *type, ...) {
    va_list v;
    va_start(v, type);
    id obj = nil;
    if (strcmp(type, @encode(id)) == 0) {
        id actual = va_arg(v, id);
        obj = actual;
    } else if (strcmp(type, @encode(CGPoint)) == 0) {
        CGPoint actual = (CGPoint)va_arg(v, CGPoint);
        obj = [NSValue value:&actual withObjCType:type];
    } else if (strcmp(type, @encode(CGSize)) == 0) {
        CGSize actual = (CGSize)va_arg(v, CGSize);
        obj = [NSValue value:&actual withObjCType:type];
    } else if (strcmp(type, @encode(MASEdgeInsets)) == 0) {
        MASEdgeInsets actual = (MASEdgeInsets)va_arg(v, MASEdgeInsets);
        obj = [NSValue value:&actual withObjCType:type];
    } else if (strcmp(type, @encode(double)) == 0) {
        double actual = (double)va_arg(v, double);
        obj = [NSNumber numberWithDouble:actual];
    } else if (strcmp(type, @encode(float)) == 0) {
        float actual = (float)va_arg(v, double);
        obj = [NSNumber numberWithFloat:actual];
    } else if (strcmp(type, @encode(int)) == 0) {
        int actual = (int)va_arg(v, int);
        obj = [NSNumber numberWithInt:actual];
    } else if (strcmp(type, @encode(long)) == 0) {
        long actual = (long)va_arg(v, long);
        obj = [NSNumber numberWithLong:actual];
    } else if (strcmp(type, @encode(long long)) == 0) {
        long long actual = (long long)va_arg(v, long long);
        obj = [NSNumber numberWithLongLong:actual];
    } else if (strcmp(type, @encode(short)) == 0) {
        short actual = (short)va_arg(v, int);
        obj = [NSNumber numberWithShort:actual];
    } else if (strcmp(type, @encode(char)) == 0) {
        char actual = (char)va_arg(v, int);
        obj = [NSNumber numberWithChar:actual];
    } else if (strcmp(type, @encode(bool)) == 0) {
        bool actual = (bool)va_arg(v, int);
        obj = [NSNumber numberWithBool:actual];
    } else if (strcmp(type, @encode(unsigned char)) == 0) {
        unsigned char actual = (unsigned char)va_arg(v, unsigned int);
        obj = [NSNumber numberWithUnsignedChar:actual];
    } else if (strcmp(type, @encode(unsigned int)) == 0) {
        unsigned int actual = (unsigned int)va_arg(v, unsigned int);
        obj = [NSNumber numberWithUnsignedInt:actual];
    } else if (strcmp(type, @encode(unsigned long)) == 0) {
        unsigned long actual = (unsigned long)va_arg(v, unsigned long);
        obj = [NSNumber numberWithUnsignedLong:actual];
    } else if (strcmp(type, @encode(unsigned long long)) == 0) {
        unsigned long long actual = (unsigned long long)va_arg(v, unsigned long long);
        obj = [NSNumber numberWithUnsignedLongLong:actual];
    } else if (strcmp(type, @encode(unsigned short)) == 0) {
        unsigned short actual = (unsigned short)va_arg(v, unsigned int);
        obj = [NSNumber numberWithUnsignedShort:actual];
    }
    va_end(v);
    return obj;
}

#define MASBoxValue(value) _MASBoxValue(@encode(__typeof__((value))), (value))
1炎辨, 先看臉捕透。這位姑娘不僅有一張白皙的臉蛋,還情商極高碴萧。
 ///見人說人話乙嘀,見鬼說鬼話
 ///這里你要了解蘋果公司的生態(tài),不僅僅有iphone還有TV和mac破喻。這也表明了虎谢,這個庫是可以伺候這三大平臺的。
 #if TARGET_OS_IPHONE || TARGET_OS_TV
 #elif TARGET_OS_MAC
 #endif
///但愿你不是一個死讀書的孩子曹质。我上一篇文章列舉了#define很多缺點婴噩。你不會看到這幾行代碼就吐槽我或者吐槽這個庫的作者吧。你要理解羽德,這兩個地方是完全不同的兩種考慮几莽。
#define MAS_VIEW UIView
#define MAS_VIEW_CONTROLLER UIViewController
#define MASEdgeInsets UIEdgeInsets
///別名,給系統(tǒng)的類取個別名宅静。一度覺得別名這個功能沒啥用≌买迹現(xiàn)在想想,無知比博學更容易使人自信姨夹∠舜梗看看這里,作者怎么使用別名這個功能的磷账。
typedef UILayoutPriority MASLayoutPriority;
///這里也是常量峭沦,可以算是第三種定義常量的方式。不要再問哪個會好一點了逃糟。沉下心來看看代碼吼鱼,好好思考一下。沒有什么是絕對好的绰咽,我們要追求的是合適蛉抓,而不是偏執(zhí)的知識理論。
static const MASLayoutPriority MASLayoutPriorityRequired = UILayoutPriorityRequired;
static const MASLayoutPriority MASLayoutPriorityDefaultHigh = UILayoutPriorityDefaultHigh;
static const MASLayoutPriority MASLayoutPriorityDefaultMedium = 500;
static const MASLayoutPriority MASLayoutPriorityDefaultLow = UILayoutPriorityDefaultLow;
static const MASLayoutPriority MASLayoutPriorityFittingSizeLevel = UILayoutPriorityFittingSizeLevel;
比較一下if里的代碼和else if里面的代碼剃诅。是不是很容易發(fā)現(xiàn)一個問題,if里面定義了MAS_VIEW_CONTROLLER而else if里面卻沒有驶忌。對矛辕,這個姑娘還很聰明笑跛。這里的用處,我留給聰明的你聊品。你最好自己思考一下飞蹂,我在后面的文章會回顧這里,到時候翻屈,看看我們是否心有靈犀陈哑。(鄭重聲明:我不是大神,也沒有故意擺架子伸眶,更沒有逗你玩惊窖。我是希望能夠讓你有提升,好對得起你與我的這份緣分)厘贼。
2界酒, 再看胸。這里拒絕評論嘴秸。
/**
 *  Allows you to attach keys to objects matching the variable names passed.
 *  view1.mas_key = @"view1", view2.mas_key = @"view2";
 *  is equivalent to:
 *  MASAttachKeys(view1, view2);
 */
#define MASAttachKeys(...)                                                        \
{                                                                             \
    NSDictionary *keyPairs = NSDictionaryOfVariableBindings(__VA_ARGS__);     \
    for (id key in keyPairs.allKeys) {                                        \
        id obj = keyPairs[key];                                               \
        NSAssert([obj respondsToSelector:@selector(setMas_key:)],             \
             @"Cannot attach mas_key to %@", obj);                        \
        [obj setMas_key:key];                                                 \
    }                                                                         \
}
這個宏簡直就是一件作品毁欣。
先說作用:這個宏是為了給每一個view一個名字。干什么用岳掐?當你約束添加有誤時凭疮,會有錯誤提示,但卻無法告訴你哪一個view的約束出現(xiàn)了問題串述。然后你開始一個一個的排查执解。大部分情況下你的運氣比較好,很快就找到問題剖煌。但每個月總有那么幾天材鹦,你感覺渾身無力,頭腦發(fā)熱耕姊,怎么也找不到哪里約束出了問題桶唐。怎么辦?如何找到這個有問題的約束茉兰,然后你應該看代碼尤泽。對,源碼面前了無秘密规脸。然后你就發(fā)現(xiàn)了這個宏坯约。然后你就知道了這個宏是干啥用的。那么莫鸭,現(xiàn)在你是不是已經(jīng)猜到了這個宏是干什么的了闹丐。這個宏會將當前view對象的名字轉(zhuǎn)化為字符串,并賦值給view的一個屬性被因。當這個view的約束報錯時卿拴,會打印出這個字符串衫仑,讓開發(fā)者快速定位到出問題的view。
這里定義的是一個方法堕花,用宏的方式定義方法文狱。
NSDictionaryOfVariableBindings看明白這個的作用了嗎?
 NSDictionaryOfVariableBindings(v1缘挽,v2瞄崇,v3)相當于[NSDictionary dictionaryWithObjectsAndKeys:v1,@“v1”壕曼,v2苏研,@“v2”,v3窝稿,@“v3”楣富,nil];
斷言

NSAssert([obj respondsToSelector:@selector(setMas_key:)], @"Cannot attach mas_key to %@", obj);

如果發(fā)現(xiàn)obj這個對象沒有實現(xiàn)對應的setMas_key方法,這里會拋異常出來伴榔!看一眼異常信息纹蝴,慢慢體會斷言的作用。
LGMasonryDome[6607:1939185] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Cannot attach mas_key to <ViewController: 0x104e08770>'
重點了W偕佟L涟病!T荨<娣浮!
obj是如何擁有mas_key這個屬性的集漾。是系統(tǒng)的嗎切黔?看一眼前綴mas,難道是巧合具篇,別鬧了纬霞,這個明顯是這個庫的前綴嘛。既然不是系統(tǒng)的,那作者是通過何種手段為其添加的mas_key屬性呢?

答案是分類+runtime

分類請親自行百度的业栅,這是個比較重要的概念。分類的理解不難也切,但結(jié)合代碼構(gòu)建過程,慢慢的就會體會出其巨大的威力。我曾見過有人用這個特性做組建開發(fā)。
我們來看下作者的源碼翠桦。源碼面前了無秘密。
- (id)mas_key {
    return objc_getAssociatedObject(self, @selector(mas_key));
}
- (void)setMas_key:(id)key {
    objc_setAssociatedObject(self, @selector(mas_key), key, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
runtime也是一個很大的概念胳蛮,關于它的爭論也很多秤掌〕钇蹋總的來說,理解方面你應該比較清晰的知曉其內(nèi)部構(gòu)造闻鉴。這個是你理解OC這門語言的基礎和難點。但使用方面茂洒,我的觀點是盡量克制孟岛。
如果要論證,mas_key作為成員變量被添加到obj督勺,那這也是個比較大的概念渠羞。要清楚一個對象的runtime組成,了解runtime的API智哀,理解obj和mas_key的內(nèi)存分布關系次询,我盡量在后期寫一下這方 面的自己的理解。如果在這里扯瓷叫,就偏離的我們的主題了屯吊。
3,我們先看腿摹菠,屁股就留在最后盒卸。我自己都覺得這么寫是不是不合適啊。
/**
 *  inline關鍵字用來定義一個類的內(nèi)聯(lián)函數(shù)次氨,引入它的主要原因是用它替代C中表達式形式的宏定義蔽介。
 */
static inline id _MASBoxValue(const char *type, ...) {
    va_list v;
    va_start(v, type);
    id obj = nil;
    if (strcmp(type, @encode(id)) == 0) {
        id actual = va_arg(v, id);
        obj = actual;
    } else if (strcmp(type, @encode(CGPoint)) == 0) {
        CGPoint actual = (CGPoint)va_arg(v, CGPoint);
        obj = [NSValue value:&actual withObjCType:type];
    } else if (strcmp(type, @encode(CGSize)) == 0) {
        CGSize actual = (CGSize)va_arg(v, CGSize);
        obj = [NSValue value:&actual withObjCType:type];
    } else if (strcmp(type, @encode(MASEdgeInsets)) == 0) {
        MASEdgeInsets actual = (MASEdgeInsets)va_arg(v, MASEdgeInsets);
        obj = [NSValue value:&actual withObjCType:type];
    } else if (strcmp(type, @encode(double)) == 0) {
        double actual = (double)va_arg(v, double);
        obj = [NSNumber numberWithDouble:actual];
    } else if (strcmp(type, @encode(float)) == 0) {
        float actual = (float)va_arg(v, double);
        obj = [NSNumber numberWithFloat:actual];
    } else if (strcmp(type, @encode(int)) == 0) {
        int actual = (int)va_arg(v, int);
        obj = [NSNumber numberWithInt:actual];
    } else if (strcmp(type, @encode(long)) == 0) {
        long actual = (long)va_arg(v, long);
        obj = [NSNumber numberWithLong:actual];
    } else if (strcmp(type, @encode(long long)) == 0) {
        long long actual = (long long)va_arg(v, long long);
        obj = [NSNumber numberWithLongLong:actual];
    } else if (strcmp(type, @encode(short)) == 0) {
        short actual = (short)va_arg(v, int);
        obj = [NSNumber numberWithShort:actual];
    } else if (strcmp(type, @encode(char)) == 0) {
        char actual = (char)va_arg(v, int);
        obj = [NSNumber numberWithChar:actual];
    } else if (strcmp(type, @encode(bool)) == 0) {
        bool actual = (bool)va_arg(v, int);
        obj = [NSNumber numberWithBool:actual];
    } else if (strcmp(type, @encode(unsigned char)) == 0) {
        unsigned char actual = (unsigned char)va_arg(v, unsigned int);
        obj = [NSNumber numberWithUnsignedChar:actual];
    } else if (strcmp(type, @encode(unsigned int)) == 0) {
        unsigned int actual = (unsigned int)va_arg(v, unsigned int);
        obj = [NSNumber numberWithUnsignedInt:actual];
    } else if (strcmp(type, @encode(unsigned long)) == 0) {
        unsigned long actual = (unsigned long)va_arg(v, unsigned long);
        obj = [NSNumber numberWithUnsignedLong:actual];
    } else if (strcmp(type, @encode(unsigned long long)) == 0) {
        unsigned long long actual = (unsigned long long)va_arg(v, unsigned long long);
        obj = [NSNumber numberWithUnsignedLongLong:actual];
    } else if (strcmp(type, @encode(unsigned short)) == 0) {
        unsigned short actual = (unsigned short)va_arg(v, unsigned int);
        obj = [NSNumber numberWithUnsignedShort:actual];
    }
    va_end(v);
    return obj;
}
#define MASBoxValue(value) _MASBoxValue(@encode(__typeof__((value))), (value))
C++的代碼,大家有時間可以了解一下煮寡。
這里的內(nèi)聯(lián)函數(shù)虹蓄,相當于上面對于MASAttachKeys方法宏定義一樣。這里你可以理解為C++中對方法的宏定義使用inline幸撕。
static inline id _MASBoxValue(const char *type, ...) 最后這三個點薇组,是怎么回事?在C中杈帐,當我們無法列出傳遞函數(shù)的所有實參的類型和數(shù)目時,可以用省略號指定參數(shù)表体箕。
函數(shù)參數(shù)是以數(shù)據(jù)結(jié)構(gòu):棧的形式存取,從右至左入棧。
首先是參數(shù)的內(nèi)存存放格式:參數(shù)存放在內(nèi)存的堆棧段中挑童,在執(zhí)行函數(shù)的時候累铅,從最后一個開始入棧。因此棧底高地址站叼,棧頂?shù)偷刂贰?舉個例子如下:void func(int x, float y, char z);   
那么娃兽,調(diào)用函數(shù)的時候,實參 char z 先進棧尽楔,然后是 float y投储,最后是 int x第练,因此在內(nèi)存中變量的存放次序是 x->y->z,因此玛荞,從理論上說娇掏,我們只要探測到任意一個變量的地址,并且知道其他變量的類型勋眯,通過指針移位運算婴梧,則總可以順藤摸瓜找到其他的輸入變量。
這里給了第一個參數(shù)type客蹋。我們可以順藤摸瓜了塞蹭。
看看作者怎么摸腿的。哦讶坯,不番电,摸瓜。
下面是 <stdarg.h> 里面重要的幾個宏定義如下:
typedef char* va_list;
void va_start ( va_list ap, prev_param ); /* ANSI version */
type va_arg ( va_list ap, type );
void va_end ( va_list ap );
va_list 是一個字符指針辆琅,可以理解為指向當前參數(shù)的一個指針漱办,取參必須通過這個指針進行。
<Step 1> 在調(diào)用參數(shù)表之前涎跨,定義一個 va_list 類型的變量洼冻,(假設va_list 類型變量被定義為ap);
<Step 2> 然后應該對ap 進行初始化隅很,讓它指向可變參數(shù)表里面的第一個參數(shù)撞牢,這是通過 va_start 來實現(xiàn)的,第一個參數(shù)是 ap 本身叔营,第二個參數(shù)是在變參表前面緊挨著的一個變量,即“...”之前的那個參數(shù)屋彪;
<Step 3> 然后是獲取參數(shù),調(diào)用va_arg绒尊,它的第一個參數(shù)是ap畜挥,第二個參數(shù)是要獲取的參數(shù)的指定類型,然后返回這個指定類型的值婴谱,并且把 ap 的位置指向變參表的下一個變量位置蟹但;
 <Step 4> 獲取所有的參數(shù)之后,我們有必要將這個 ap 指針關掉谭羔,以免發(fā)生危險华糖,方法是調(diào)用 va_end,他是輸入的參數(shù) ap 置為 NULL瘟裸,應該養(yǎng)成獲取完參數(shù)表之后關閉指針的習慣客叉。說白了,就是讓我們的程序具有健壯性。通常va_start和va_end是成對出現(xiàn)兼搏。
回過頭再看看作者代碼卵慰,是不是“又細又長”。
4佛呻,最后一步了裳朋。各位看客,辦理VIP才可以一探究竟哦吓著。這個作者好污再扭。讀這種技術文章,很頭痛的夜矗。所以作者也算是煞費苦心了。
看看哪里使用了让虐?
- (NSUInteger)hash {
    return MAS_NSUINTROTATE([self.view hash], MAS_NSUINT_BIT / 2) ^ self.layoutAttribute;
}
這是我最頭痛的地方了紊撕。作者已經(jīng)哭暈在廁所。請大家自行百度吧赡突。
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末对扶,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子惭缰,更是在濱河造成了極大的恐慌浪南,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,294評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件漱受,死亡現(xiàn)場離奇詭異络凿,居然都是意外死亡,警方通過查閱死者的電腦和手機昂羡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,493評論 3 385
  • 文/潘曉璐 我一進店門絮记,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人虐先,你說我怎么就攤上這事怨愤。” “怎么了蛹批?”我有些...
    開封第一講書人閱讀 157,790評論 0 348
  • 文/不壞的土叔 我叫張陵撰洗,是天一觀的道長。 經(jīng)常有香客問我腐芍,道長差导,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,595評論 1 284
  • 正文 為了忘掉前任甸赃,我火速辦了婚禮柿汛,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己络断,他們只是感情好裁替,可當我...
    茶點故事閱讀 65,718評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著貌笨,像睡著了一般弱判。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上锥惋,一...
    開封第一講書人閱讀 49,906評論 1 290
  • 那天昌腰,我揣著相機與錄音,去河邊找鬼膀跌。 笑死遭商,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的捅伤。 我是一名探鬼主播劫流,決...
    沈念sama閱讀 39,053評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼丛忆!你這毒婦竟也來了祠汇?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,797評論 0 268
  • 序言:老撾萬榮一對情侶失蹤熄诡,失蹤者是張志新(化名)和其女友劉穎可很,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體凰浮,經(jīng)...
    沈念sama閱讀 44,250評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡我抠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,570評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了导坟。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片屿良。...
    茶點故事閱讀 38,711評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖惫周,靈堂內(nèi)的尸體忽然破棺而出尘惧,到底是詐尸還是另有隱情,我是刑警寧澤递递,帶...
    沈念sama閱讀 34,388評論 4 332
  • 正文 年R本政府宣布喷橙,位于F島的核電站,受9級特大地震影響登舞,放射性物質(zhì)發(fā)生泄漏贰逾。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,018評論 3 316
  • 文/蒙蒙 一菠秒、第九天 我趴在偏房一處隱蔽的房頂上張望疙剑。 院中可真熱鬧氯迂,春花似錦、人聲如沸言缤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,796評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽管挟。三九已至轿曙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間僻孝,已是汗流浹背导帝。 一陣腳步聲響...
    開封第一講書人閱讀 32,023評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留穿铆,地道東北人您单。 一個月前我還...
    沈念sama閱讀 46,461評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像荞雏,于是被迫代替她去往敵國和親睹限。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,595評論 2 350

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

  • 這個文件是整個庫的頭文件讯檐。顧名思義,使用時引入這個頭文件染服,就可以使用這個文件中引入的所有文件别洪。 先看源碼 這個文件...
    天蓬大元閱讀 1,813評論 1 0
  • 一,理清思路 二柳刮,深入實踐 1挖垛,使用masonry,最常用的三個API 2秉颗,了解mas_makeConstrain...
    天蓬大元閱讀 1,020評論 0 0
  • 本來沒打算寫總結(jié)的痢毒,無意間在簡書看到了一位同行的總結(jié),挺有意思的蚕甥,想想寫寫總結(jié)其實挺不錯的哪替,這樣可以理清楚一周都干...
    Timefiles閱讀 254評論 0 0
  • 在路上 車輪飛旋 車輪上綁著希望 在路上 思緒飛揚 思緒里飄著夢想 車輪追趕著夢里的憧憬 歲月的轍印在身后拉長 在...
    忙里偷閑_9c1d閱讀 207評論 0 1
  • 稽核不是管理人心,也不是改變?nèi)诵墓交常诵氖翘摶玫目床坏降钠静埃灾荒芨惺懿荒芨淖儭? 當我們改變不了人心的...
    姜楊Ada閱讀 89評論 0 0