iOS套路面試題之Category

面試中筆試題和面試題好多都問Category代虾,剛?cè)胄斜容^納悶,心里就犯嘀咕:這么簡單還問激蹲。之前一般都是背一背結(jié)合簡單用法直接脫口而出棉磨,結(jié)果就是:回去等通知吧!Q琛乘瓤!

Category:不用繼承對象,就可以增加新的方法策泣,或原本的方法衙傀。

Objective-C語言中,每一個類有哪些方法萨咕,都是在runtime時加入的统抬,我們可以通過runtime提供的一個叫做class_addMethod的function,加入對應(yīng)的某個selector的實現(xiàn)。而在runtime加入新的方法聪建,使用category會更容易理解與實現(xiàn)的方法钙畔,因為可以使用
與聲明類時差不多的語法,同時也以一般實現(xiàn)的方法金麸,實現(xiàn)我們加入的方法擎析。
至于Swift語言中,Swift的Extension 特性挥下,也與Objective-C的Category差不多叔锐。

什么時候應(yīng)該要使用Category呢?

如果想要擴展某個類的功能见秽,增加新的成員變量與方法愉烙,我們又沒有這些類的源代碼,正規(guī)的做法就是繼承解取、建立新的子類步责。那我們需要子啊不用繼承,就直接添加method這種做法的重要理由禀苦,就是我們要擴展的類很難繼承蔓肯。
可能有以下幾種狀況:
1.Foundation 對象
2.用工廠模式實現(xiàn)的對zai象
3.單利對象
4.在工程中出現(xiàn)多次已經(jīng)不計其數(shù)的對象

Foundation對象

Foundation里面的基本對象,像是NSString振乏、NSArray蔗包、NSDictionary等類的底層實現(xiàn),除了可以通過Objective-C的層面調(diào)用之外慧邮,也可以通過另外一個C的層面调限,叫做Core Foundation,像是NSString其實會對應(yīng)到Core Foundation里面的CFStringRef误澳,NSArray對應(yīng)到CFArrayRef耻矮,而甚至可以直接把Foundation對象轉(zhuǎn)換(cast)成Core Foundation的類型,當(dāng)你遇到一個需要傳入CFStringRef的function的時候忆谓,只要建立NSString然后轉(zhuǎn)換(cast)成CFStringRef 傳入就可以了裆装。
所以,當(dāng)你使用alloc倡缠、init產(chǎn)生一個Foundation對象的時候哨免,其實會得到一個有Foundation與Core Foundation 實現(xiàn)的子類,而實際生成的對象昙沦,往往和我們所認知的有很大差距琢唾,例如,我們認為一個NSMutableString繼承自NSString桅滋,但是建立 NSString 慧耍,調(diào)用alloc、init的時候丐谋,我們真正拿到的是__NSCFConstantString芍碧,而建立NSMutableString ,拿到的__NSCFString号俐,而__NSCFConstantString其實繼承__NSCFString泌豆!
以下代碼說明Foundation 的對象其實是屬于哪些類:

這些對象屬于哪些類

因此,當(dāng)我們嘗試建立Foundation 對象的子類之后吏饿,像是繼承 NSString踪危,建立我們自己的MyString,假如我們并沒有重載原本關(guān)于新建實例的方法猪落,我們也不能保證贞远,建立出來的就是MyString的實例。

用工廠模式實現(xiàn)的對象

工廠模式是一套用來解決不用指定特定是哪一個類笨忌,就可以新建對象的方法。比如說,某個類下胜宇,其實有一堆的子類迂卢,但對外部來說并不需要確切知道這些子類而只要對最上層的類,輸入致電該的條件途凫,就會挑選出一個符合指定條件的子類垢夹,新建實例回調(diào)。
在UIKit中维费,UIButton 就是很好的例子果元,我們建立 UIButton對象的時候,并不是調(diào)用init或者是initWithFrame:,而是調(diào)用UIButton 的類方法:buttonWithType:,通過傳遞按鈕的type新建按鈕對象犀盟。在大多數(shù)狀況下噪漾,會返回UIButton 的對象,但假如我們傳入的type是UIButtonTypeRoundedRect,卻會返回繼承自UIButton的UIRoundedRectButton且蓬。
驗證下:

UIButton

我們要擴展的是UIButton欣硼,但是拿到的卻是UIRoundedRectButton,而UIRoundedRectButton卻無法繼承,因為這些對象不在公開的頭文件里恶阴,我們也不能保證以后傳入UIButtonTypeRoundedRect就一定會拿到UIRoundedRectButton诈胜。如此一來,就造成我們難以繼承UIButton冯事。
或這么說:假使我們的需求就是想要改動某個上層的類焦匈,讓底下所有的子類也都增加了一個新的方法,我們又無法改變這個上層的類程序昵仅,就會采用category缓熟。比方說累魔,我們要做所有的UIViewController都有一個新的方法,如此我們整個應(yīng)用程序中每個UIViewController的子類都可以調(diào)用這個方法够滑,但是我們就是無法改動UIViewController垦写。

單例模式

單例對象是指:某個類只要、也只該有一個實例彰触,每次都只對這個實例操作梯投,而不是建立新的實例。
像UIApplication况毅、 NSUserDefault分蓖、NSNotificationCenter都是采用單例設(shè)計。
之所以說單例對象很難繼承尔许,我們先來看怎么實現(xiàn)單例:我們會有一個static對象么鹤,然后沒戲都返回這個對象。聲明部分如下:

@interface MyClass : NSObject
+ (MyClass *)sharedInstance;
@end

實現(xiàn)部分:

static MyClass *sharedInstance = nil;

@implementation MyClass
+ (MyClass *)sharedInstance
{
    return sharedInstance ?
           sharedInstance :
           (sharedInstance = [[MyClass alloc] init]);
}
@end 

其實目前單例大多使用GCD的dispatch_once實現(xiàn)味廊,之后再寫吧午磁。
如果我們子類化MyClass,卻沒有重寫(override)掉sharedInstance,那么sharedInstance返回的還是MyClass 的單例實例毡们。而想要重寫(override)掉sharedInstance又不見得那么簡單迅皇,因為這個方法里面很可能又做了許多其他的事情,很可能會把這些initiailize時該做的事情衙熔,按照以下的寫法登颓。例如MyClass 可能這樣寫:

+ (MyClass *)sharedInstance
{
    if (!sharedInstance) {
        sharedInstance = [[MyClass alloc] init];
        [sharedInstance doSomething];
        [sharedInstance doAnotherThine];
    }
    return sharedInstance;
}

如果我們并沒有MyClass的源代碼,這個類是在其他的library或是framework 中红氯,我們直接重寫(override)了sharedInstance框咙,就很有可能有事沒做,而產(chǎn)生不符合預(yù)期的結(jié)果痢甘。

在工程中出現(xiàn)次數(shù)不計其數(shù)的對象

隨著對工程項目的不斷開發(fā)喇嘱,某些類已經(jīng)頻繁使用到了到處都是,而我們現(xiàn)在需求改變塞栅,我們要增加新的方法者铜,但是把所有的用到的地方統(tǒng)統(tǒng)換成新的子類。Category 就是解決這種狀況的救星放椰。

實現(xiàn)Category

Category的語法很簡單作烟,一樣使用@interface關(guān)鍵字聲明頭文件,在@implementation與@end關(guān)鍵字當(dāng)中的范圍是實現(xiàn)砾医,然后在原本的類名后面拿撩,用中括號表示Category名稱。
舉例說明:

@interface NSObject (Test)
- (void)printTest;
@end

@implementation NSObject (Test)
- (void)printTest
{
    NSLog(@"%@", self);
}
@end

這樣每個對象都增加了printTest這個方法如蚜,可以調(diào)用[myObject printTest];
排列字符串的時候压恒,可以調(diào)用localizedCompare:,但是假如我們希望所有的字符串都按照中文筆畫 順序排列影暴,我們可以寫一個自己的方法,例如:strokeCompare:探赫。

@interface NSString (CustomCompare)
- (NSComparisonResult)strokeCompare:(NSString *)anotherString;
@end

@implementation NSString (CustomCompare)
- (NSComparisonResult)strokeCompare:(NSString *)anotherString
{
    
   NSLocale *strokeSortingLocale = [[[NSLocale alloc]
              initWithLocaleIdentifier:@"zh@collation=stroke"]
              autorelease];
    return [self compare:anotherString
                 options:0
                 range:NSMakeRange(0, [self length])
                 locale:strokeSortingLocale];
}
@end

在保存的時候型宙,文件名的命名規(guī)則是原本的類名加上category的名稱,中間用“+”連接期吓,以我們新建CustomCompare為例子,保存的時候就要保存為NSString+CustomCompare.h以及NSString+CustomCompare.m倾芝。

Category還有啥用處呢讨勤?

除了幫原有的類增加新的方法,我們也會在多種狀況下使用Category晨另。

將一個很大的類切割成多個部分

由于我們可以在新建類之后潭千,繼續(xù)通過Category增加方法,所以借尿,加入一個類很大刨晴,里面又十幾個方法 ,實現(xiàn)有千百行之多路翻,我們就可以考慮將這些類的方法拆分成若干個category狈癞,讓整個類的實現(xiàn)分開在不同的文件里,以便知道某一群方法屬于什么用途茂契。
切割一個很大的類的好處包括以下:

跨工程

如果你手上有好多工程蝶桶,我們在開發(fā)的時候,由于之前寫的一些代碼可以重復(fù)使用掉冶,造成了好多工程可以共用一個類真竖,但是每個工程又不見都會用到這個類的所有的實現(xiàn),我們就可以考慮將屬于某個項目的實現(xiàn)厌小,拆分到某一個category恢共。

跨平臺

如果我們的某段代碼用到在Mac OS X 和iOS 都有的library 與 framework ,那么這就可以在Mac OS X 和iOS 使用璧亚。

替換原來的實現(xiàn)

由于一個類有哪些方法讨韭,是在runtime 時加入,所以除了可以加入新的方法之外癣蟋,假如我們嘗試再加入一個selector與已經(jīng)存在的方法名稱相同的實現(xiàn)拐袜,我們可以把已經(jīng)存在的方法實現(xiàn),換成我們要加入的實現(xiàn)梢薪。這么做在Objective-C語言中是完全可以的蹬铺,如果category 里面出現(xiàn)了名稱相同的方法,編譯器會允許編譯成功秉撇,只會跳出簡單的警告??甜攀。
實際操作上秋泄,這樣的做法很危險,假如我們自己寫了一個類规阀,我們又另外自己寫了一個category 替換掉方法恒序,當(dāng)我們?nèi)蘸笙胄薷倪@個方法的內(nèi)容,很容易忽略掉category 中同名的方法谁撼,結(jié)果就是不管我們?nèi)绾涡薷脑痉椒ㄖ械某绦蚱缧玻Y(jié)果都是什么也沒改。
除了在某一個category 中可以出現(xiàn)與原本類中名稱相同的方法厉碟,我們甚至可以在好幾個category 中喊巍,都出現(xiàn)名稱一樣的方法,哪一個category 在執(zhí)行的時候都會被最后載入箍鼓,這就會造成是這個category 中的實現(xiàn)崭参。那么,如果有多個category 款咖,我們?nèi)绾沃滥囊粋€category 才會是最后被載入的哪一個何暮?Objective-C runtime并不保證category 的載入順序,所以必須避免寫出這樣的程序铐殃。

Extensions

Objective-C語言中有一項叫做extensions 的設(shè)計海洼,也可以拆分一個很大的類,語法與category非常相似富腊,但是不是太一樣贰军。在語法上,extensions 像是一個沒有名字的category蟹肘,在class名稱之后直接加上一個空的括號词疼,而extensions 定義的方法,需要放到原本的類實現(xiàn)中帘腹。
例如:

@interface MyClass : NSObject
@end

@interface MyClass()
- (void)doSomthing;
@end

@implementation MyClass
- (void)doSomthing
{
}
@end

@interface MyClass ()這段聲明中贰盗,我們并沒有在括號中定義任何名稱,接著doSomthing有是MyClass中實現(xiàn)阳欲。extensions 可以有多個用途舵盈。

拆分 Header

如果我們就是打算實現(xiàn)一個很大的類,但是覺得 header里面已經(jīng)列出的太多的方法球化,我們可以將一部分方法搬到extensions的定義里面秽晚。
另外,extension除了可以放方法之外筒愚,還可以放成員變量赴蝇,而一個類可以擁有不止一個extension,所以一個類有很多的方法可成員變量巢掺,就可以把這些方法與成員變量句伶,放在多個extension中劲蜻。

管理私有方法( Private Methods)

最常見的,我們在寫一個類的時候考余,內(nèi)部有一些方法不需要先嬉、我們也不想放在public header 中,但是如果不將這些方法放到header里楚堤,又會出現(xiàn)一個問題:Xcode 4.3 之前疫蔓,如果這些私有方法在程序代碼中不放在其他的方法前面,其他的方法在調(diào)用這些方法的時候身冬,編譯器會不斷跳出警告衅胀,而這種無關(guān)緊要的警告一多,會覆蓋掉重要的警告吏恭。
要想避免這種警告拗小,要不就是把私有方法都最在最前面重罪,但這樣也不能完全解決問題樱哼,因為私有方法之間可以互相調(diào)用,湖事件確認每個方法之間相互調(diào)用剿配,花時間確認每個方法的調(diào)用順序并不是很有效率的事情;要不就是都用performSelector:調(diào)用搅幅,這樣問題更大,就像呼胚,在方法改名茄唐、調(diào)用重構(gòu)工具的時候,這樣的做法很危險蝇更。
蘋果提供的建議沪编,就是.m或者.mm文件開頭的地方聲明一個extensions,將私有方法都放在這個地方,如此一來年扩,其他的方法就可以找到私有方法的聲明蚁廓。在Xcode提供的file template 中,如果建立一個UIViewController 的子類厨幻,就可以看到在.m文件的最前面相嵌,幫你預(yù)留一塊extensions``的聲明。 在這里順便也寫一下Swift的extensions况脆。在Swift語言中饭宾,我們可以直接用extensions關(guān)鍵字,建立一個類的extensions格了,擴展一個類看铆;Swift的extensions與Object-C的category 的主要差別是:Object-C的category 要給定一個名字,而Objective-C的extensions是沒有名字的category 盛末,至于Swift 的extensions```則是沒有統(tǒng)一的名字性湿。
所以纬傲,如果有一個Swift類叫做MyClass

class MyClass {
}

這樣就可以直接建立extensions

extension MyClass {
}

此外,Swift除了可以用extensions擴展類之外肤频,甚至可以擴充protocol與結(jié)構(gòu)體(struct)叹括。例如:

protocol MyProtocol {
}

extension MyProtocol {
}

struct MyStruct {
}

extension MyStruct {
}

Category是否可以增加新的成員變量或?qū)傩裕?/h2>

因為Objective-C對象會被編譯成C 的結(jié)構(gòu)體,我們可以在category中增加新的方法宵荒,但是我們卻不可以增加成員變量汁雷。
在iOS4之后,蘋果的辦法是關(guān)聯(lián)對象(Associated Objects)的辦法报咳∠姥叮可以讓我們在Category中增加新的getter/setter,其實原理差不多:既然我們可以用一張表記錄類有哪些方法暑刃。那么我們也可以建立另外一個表格厢漩,記錄哪些對象與這個類相關(guān)。
要使用關(guān)聯(lián)對象(Associated Objects)岩臣,我們需要導(dǎo)入objc/runtime.h溜嗜,然后調(diào)用objc_setAssociatedObject建立setter,用getAssociatedObject建立getter架谎,調(diào)用時傳入:我們要讓那個對象與那個對象之間建立聯(lián)系炸宵,連通時使用的是哪一個key(類型為C字符串)。在以下的例子中谷扣,在MyCategory這個category里面土全,增加一個叫做myVar的屬性(property)。

#import <objc/runtime.h>

@interface MyClass(MyCategory)
@property (retain, nonatomic) NSString *myVar;
@end

@implementation MyClass
- (void)setMyVar:(NSString *)inMyVar
{
    objc_setAssociatedObject(self, "myVar",
           inMyVar, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSString *)myVar
{
    return objc_getAssociatedObject(self, "myVar");
}
@end

setMyVar:中調(diào)用objc_setAssociatedObject時会涎,最后的一個參數(shù)隨是OBJC_ASSOCIATION_RETAIN_NONATOMIC,是用來決定要用哪一個內(nèi)存管理方法裹匙,管理我們傳入的參數(shù),在示例中末秃,傳入的是NSString,是一個Objective-C對象概页,所以必須要retain起來。這里可以傳入的參數(shù)還可以是OBJC_ASSOCIATION_ASSIGN蛔溃、OBJC_ASSOCIATION_COPY_NONATOMIC绰沥、OBJC_ASSOCIATION_RETAIN以及OBJC_ASSOCIATION_COPY,與property語法使用的內(nèi)存管理方法是一致贺待,而當(dāng)MyClass對象在dealloc的時候徽曲,所有通過objc_setAssociatedObject而retain的對象,也都被遺棄釋放麸塞。
雖然不可以在category增加成員變量秃臣,但是卻可以在extensions中聲明。例如:

@interface MyClass()
{
    NSString *myVar;
}
@end

我們還可以將成員變量直接放在@implementation的代碼中:

@implementation MyClass
{
    NSString *myVar;
}
@end

對NSURLSessionTask編寫Category

在寫category的時候,可能會遇到NSURLSessionTask 這個坑鞍麓恕;“ァ!稚虎!
假如在iOS 7以上撤嫩,對NSURLSessionTask寫一個category之后,如果從[NSURLSession sharedSession]產(chǎn)生data task對象蠢终,之后序攘,對這個對象調(diào)用category 的方法,奇怪的是寻拂,會找不到任何selector錯誤程奠。照理說一個data task是NSURLSessionDataTask,繼承自NSURLSessionTask祭钉,為什么我們寫NSURLSessionTask category 沒用呢瞄沙?
切換到iOS 8的環(huán)境下又正常了,可以對這個對象調(diào)用NSURLSessionTask category 里面的方法慌核,但是如果寫成NSURLSessionDataTask 的 category距境,結(jié)果又遇到找不到selector的錯誤。
例如:

@interface NSURLSessionTask (Test)
- (void)test;
@end

@implementation NSURLSessionTask (Test)
- (void)test
{
    NSLog(@"test");
}
@end

然后跑一下:

NSURLSessionDataTask *task = [[NSURLSession sharedSession];
    dataTaskWithURL:[NSURL URLWithString:@"https://www.baidu.com"]];
[task test];

結(jié)果:

*****缺圖一張****

如果有一個category不是直接寫在App里面遂铡,而是寫在某個靜態(tài)庫(static library)肮疗,在編譯時app的最后才把這個庫鏈接進來晶姊,預(yù)想category 并不會讓鏈接器(linker)鏈接(link)進來扒接,你必須要另外在Xcode工程設(shè)定的修改鏈接參數(shù)(other linker flag),加上-ObjC或者-all_load们衙。會是這樣嗎钾怔?但是試了下,并沒有收到unsupported selector的錯誤蒙挑。
NSURLSessionTask是一個Foundation對象宗侦,而Foundation對象往往不是真正的實現(xiàn)與最上層的界面并是同一個。所以忆蚀,我們可以查一個NSURLSessionTask的繼承:

NSURLSessionDataTask *task = [[NSURLSession sharedSession] 
dataTaskWithURL:[NSURL URLWithString:@"https://www.baidu.com"]];
NSLog(@"%@", [task class]);
NSLog(@"%@", [task superclass]);
NSLog(@"%@", [[task superclass] superclass]);
NSLog(@"%@", [[[task superclass] superclass] superclass]);

在iOS8 的結(jié)果是:

__NSCFLocalDataTask
__NSCFLocalSessionTask
NSURLSessionTask
NSObject

在iOS7 的結(jié)果是:

__NSCFLocalDataTask
__NSCFLocalSessionTask
__NSCFURLSessionTask
NSObject

結(jié)論矾利,無論是iOS 8 或 iOS 7,我們新建的data task馋袜,都不是直接產(chǎn)生NSURLSessionDataTask對象男旗,而是產(chǎn)生__NSCFLocalDataTask這樣的私有對象。iOS 8 上欣鳖,__NSCFLocalDataTask并不繼承自NSURLSessionDataTask,而iOS 7上的__NSCFLocalDataTask甚至連NSURLSessionTask都不是察皇。
想知道建立的data task到底是不是NSURLSessionDataTask,可以調(diào)用“[task isKindOfClass:[NSURLSessionDataTask class]],還是會返回YES。其實什荣,-isKindOfClass:是可以重寫掉的矾缓,所以,即使__NSCFLocalDataTask根本就不是 NSURLSessionDataTask稻爬,但是我們還是把__NSCFLocalDataTask-isKindOfClass:寫成:

- (BOOL)isKindOfClass:(Class)aClass
{
    if (aClass == NSClassFromString(@"NSURLSessionDataTask")) {
        return YES;
    }
    if (aClass == NSClassFromString(@"NSURLSessionTask")) {
        return YES;
    }
    return [super isKindOfClass:aClass];
}

也就是說嗜闻,-isKindOfClass:其實并不是那么靈驗,好比你去問產(chǎn)品:這到底還要修改需求嗎桅锄?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末泞辐,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子竞滓,更是在濱河造成了極大的恐慌咐吼,老刑警劉巖,帶你破解...
    沈念sama閱讀 223,207評論 6 521
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件商佑,死亡現(xiàn)場離奇詭異锯茄,居然都是意外死亡,警方通過查閱死者的電腦和手機茶没,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,455評論 3 400
  • 文/潘曉璐 我一進店門肌幽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人抓半,你說我怎么就攤上這事喂急。” “怎么了笛求?”我有些...
    開封第一講書人閱讀 170,031評論 0 366
  • 文/不壞的土叔 我叫張陵廊移,是天一觀的道長。 經(jīng)常有香客問我探入,道長狡孔,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,334評論 1 300
  • 正文 為了忘掉前任蜂嗽,我火速辦了婚禮苗膝,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘植旧。我一直安慰自己辱揭,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 69,322評論 6 398
  • 文/花漫 我一把揭開白布病附。 她就那樣靜靜地躺著问窃,像睡著了一般。 火紅的嫁衣襯著肌膚如雪胖喳。 梳的紋絲不亂的頭發(fā)上泡躯,一...
    開封第一講書人閱讀 52,895評論 1 314
  • 那天,我揣著相機與錄音,去河邊找鬼较剃。 笑死咕别,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的写穴。 我是一名探鬼主播惰拱,決...
    沈念sama閱讀 41,300評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼啊送!你這毒婦竟也來了偿短?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,264評論 0 277
  • 序言:老撾萬榮一對情侶失蹤馋没,失蹤者是張志新(化名)和其女友劉穎昔逗,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體篷朵,經(jīng)...
    沈念sama閱讀 46,784評論 1 321
  • 正文 獨居荒郊野嶺守林人離奇死亡勾怒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,870評論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了声旺。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片笔链。...
    茶點故事閱讀 40,989評論 1 354
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖腮猖,靈堂內(nèi)的尸體忽然破棺而出鉴扫,到底是詐尸還是另有隱情,我是刑警寧澤澈缺,帶...
    沈念sama閱讀 36,649評論 5 351
  • 正文 年R本政府宣布坪创,位于F島的核電站,受9級特大地震影響谍椅,放射性物質(zhì)發(fā)生泄漏误堡。R本人自食惡果不足惜古话,卻給世界環(huán)境...
    茶點故事閱讀 42,331評論 3 336
  • 文/蒙蒙 一雏吭、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧陪踩,春花似錦杖们、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,814評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至傻谁,卻和暖如春孝治,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,940評論 1 275
  • 我被黑心中介騙來泰國打工谈飒, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留岂座,地道東北人。 一個月前我還...
    沈念sama閱讀 49,452評論 3 379
  • 正文 我出身青樓杭措,卻偏偏與公主長得像费什,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子手素,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,995評論 2 361

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

  • *面試心聲:其實這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個offer,總結(jié)起來就是把...
    Dove_iOS閱讀 27,171評論 30 470
  • 1.Difference between shallow copy and deep copy? 淺復(fù)制和深復(fù)制的...
    用心在飛閱讀 992評論 0 9
  • 喜歡就關(guān)注我唄鸳址! 1.設(shè)計模式是什么? 你知道哪些設(shè)計模式泉懦,并簡要敘述稿黍? 設(shè)計模式是一種編碼經(jīng)驗,就是用比較成熟的...
    iOS白水閱讀 1,113評論 0 2
  • 注:此文章來源:Job_Yang 的簡書 1. Object-c的類可以多重繼承么?可以實現(xiàn)多個接口么?Categ...
    廣益散人閱讀 1,350評論 0 13
  • 學(xué)生時代的愛情辕漂,可能注定是心酸的吧 還記得,初三的時候吴超,你每周三周日都會跟我聊天钉嘹,因為只有那個時候,你才有手機鲸阻,每...
    人生幾味閱讀 393評論 0 1