PS 初衷: 記錄面試題不僅僅是為了針對(duì)于我們的面試,而是在有時(shí)候可以提醒在我們用某些東東的時(shí)候會(huì)自主的想這是為什么,從而避免一些 BUG 產(chǎn)生。
以下是從 CocoaChina 招人的事結(jié)了,放出面試題,分享一下 看到的面試題,個(gè)人不知道學(xué)習(xí)啥的時(shí)候看看,嘗試解答。
- 1、下面代碼在按鈕點(diǎn)擊后,在
ARC
下會(huì)發(fā)生什么,MRC
下呢?為什么 ?
@property(nonatomic, assign) void(^block)();
- (void)viewDidLoad {
[super viewDidLoad];
int value = 10;
void(^blockC)() = ^{
NSLog(@"just a block === %d", value);
};
NSLog(@"%@", blockC);
_block = blockC;
}
- (IBAction)action:(id)sender {
NSLog(@"%@", _block);
}
- 2、在
ARC
環(huán)境下這段代碼為什么不會(huì)崩潰?
@property(nonatomic, weak) void(^block)();
- (void)viewDidLoad {
[super viewDidLoad];
void(^ __weak blockA)() = ^{
NSLog(@"just a block");
};
_block = blockA;
}
- (IBAction)action:(id)sender {
_block();
}
- 3、下面是一個(gè)員工表,
manager_id
表示對(duì)應(yīng)的boss
的ID
。通過(guò)一個(gè)SQL
找出下表中比boss
工資還高的人。。。。
id name salary manager_id
1 Noah 70000 NULL
2 西蘭花 80000 1
3 椰菜花 80000 NULL
4 沒錢花 80000 3
輸出格式為:
name
西蘭花
- 4、寫一個(gè)函數(shù),輸入一個(gè)數(shù)如 38,拆分 3 + 8 = 11,1 + 1 = 2,最后 2 無(wú)法拆分就返回(偽代碼也行)
- 5、通過(guò)
runtime
添加的“關(guān)聯(lián)對(duì)象”和類的實(shí)例變量有什么區(qū)別?使用時(shí)要注意什么? - 6、用一個(gè)生活中的例子來(lái)說(shuō)說(shuō)同步和異步。
- 7、線程間通信在 OC 中有幾種方式?分別是?常用那種?
- 8、使用快速枚舉迭代一個(gè)可變數(shù)組時(shí)需要注意什么問題?怎么避免?
- 9、什么是面向?qū)ο蟮亩鄳B(tài)性?
- 10、
UIViewController
的presentViewController
和UINavigationController
的pushViewController
方法分別多用于什么交互場(chǎng)景? - 11、
NSOperation
和GCD
的區(qū)別是什么?前者多用于什么場(chǎng)景? - 12、面向接口編程指的是什么?為什么說(shuō)面向?qū)崿F(xiàn)編程是一種錯(cuò)誤的編程方式?
- 13、在iOS開發(fā)中遇到那些類族
(Class Cluster)
?如NSNumber
這種。為什么需要這種設(shè)計(jì)方式? - 14、
javascript
的原型鏈和 OC 的繼承有什么區(qū)別? - 15、
Hybrid
開發(fā)的優(yōu)勢(shì)在哪里?目前有那些框架可以實(shí)現(xiàn)Hybrid
開發(fā)? - 16、使用了
ARC
是不是就等于沒有內(nèi)存泄漏了?如果不是的話請(qǐng)舉例。 - 17、下面代碼中為什么可以直接用
self
?
[UIView animateWithDuration:1 animations:^{
self.view.backgroundColor = [UIColor yellowColor];
}];
下面這段代碼可以用 self
嗎?為什么?
- (void)doSomething {
[BlockClass doSomethingUseBlock:^{
NSLog(@"%@", self);
}];
}
- 18、進(jìn)程的內(nèi)存布局是怎樣的?
- 19、在
GCD
中,那幾種場(chǎng)景會(huì)出現(xiàn)死鎖的現(xiàn)象?怎么避免? - 20、怎么用
NSOperation
封裝一個(gè)異步請(qǐng)求?這個(gè)Operation
需要放到NSOperationQueue
里調(diào)度的。 - 21、
CoreFoundation
和Foundation
有什么區(qū)別? - 22、怎么判斷兩個(gè)鏈表是雙交的?
- 23、怎么判斷一個(gè)鏈表存在環(huán)?
- 24、當(dāng)一個(gè)
View
的bounds
原點(diǎn)不為0的時(shí)候會(huì)出現(xiàn)什么情況? - 25、OC的數(shù)組是怎么實(shí)現(xiàn)的?和C的數(shù)組區(qū)別在?簡(jiǎn)單說(shuō)一下即可。
- 26、
weak
和assign
有什么區(qū)別? - 27、
setNeedLayout
的作用是什么? - 28、什么時(shí)候用
NS_OPTIONS
,NS_ENUM
?
對(duì)以上部分問題進(jìn)行解答
1-2 、 對(duì) Block 及其關(guān)鍵字的理解
1、在 ARC 下直接打印處兩個(gè)不一樣的 block, _block 還是其本身值。
在 MAC 下直接 崩潰,注意此處是 assgin 的關(guān)鍵字,此時(shí) _block 相當(dāng)于是已經(jīng)被釋放了。
2、此處直接打印 “just a block”,在ARC下,本類內(nèi)該 block 是沒有被釋放的。
4、考察我們的函數(shù)思維
- (void)testGetValueNumber:(NSInteger)testNumber {
while (testNumber >= 10) {
testNumber = [self getTotalValueNumberWithTestNumber:testNumber];
}
}
- (NSInteger)getTotalValueNumberWithTestNumber:(NSInteger)number {
NSString *numberStr = [NSString stringWithFormat:@"%ld",number];
// 如果是個(gè)位數(shù)則直接返回
if (numberStr.length < 2) {
return number;
}
NSInteger allValue = 0;
// 獲取每一項(xiàng)的數(shù)
for (NSInteger i = 0; i < numberStr.length; i++) {
NSInteger locationNumber = [[numberStr substringWithRange:NSMakeRange(i, 1)] integerValue];
allValue += locationNumber;
}
return allValue;
}
5、通過(guò) runtime 添加的“關(guān)聯(lián)對(duì)象”和類的實(shí)例變量有什么區(qū)別, 考察 Associated Objects 的理解。
這個(gè)問題其實(shí),按我的理解可以劃分為兩個(gè)問題:
- 關(guān)聯(lián)對(duì)象 和 常規(guī) Property 有什么區(qū)別 ?
- Property 和 實(shí)例變量有什么區(qū)別的?
先理解 Associated Objects 實(shí)現(xiàn)原理,首先可以再次回顧 雷純鋒 所畫的圖:
PS : 圖源自: Objective-C Associated Objects 的實(shí)現(xiàn)原理
簡(jiǎn)而言之的說(shuō),訪問的方式不一樣的,用的場(chǎng)景不一樣。
- 關(guān)聯(lián)對(duì)象:是存儲(chǔ)在單獨(dú)的哈希表中,被關(guān)聯(lián)對(duì)象本身的存儲(chǔ)并沒有直接的關(guān)系; 一般我們常用在 為現(xiàn)有的類添加屬性時(shí)。
- Property: 直接通過(guò)訪問屬性本質(zhì)上通過(guò)消息機(jī)制,一般設(shè)置值時(shí)用它。
- 實(shí)例變量:是在運(yùn)行期查找成員的偏移量,這樣就計(jì)算出了成員相應(yīng)位置的內(nèi)存地址,從而直接訪問其內(nèi)存,速度更快;一般簡(jiǎn)單取值時(shí),以及 init dealloc 中盡量用 實(shí)例變量。
7、線程間的通信
此處看經(jīng)典的兩個(gè)例子:
- 異步加載圖片,主線程顯示圖片的例子
dispatch_async(dispatch_get_global_queue(0, 0), ^{
dispatch_async(dispatch_get_main_queue(), ^{
//回到主線程更新
});
});
- 并行時(shí),結(jié)束時(shí)的一個(gè)標(biāo)志, dispatch_group_notify 最后時(shí)執(zhí)行
// 創(chuàng)建 dispatch_group
dispatch_group_t group = dispatch_group_create();
// 添加到 group 中
dispatch_group_async(group, queue, ^{
NSLog(@"block 1");
});
dispatch_group_async(group, queue, ^{
NSLog(@"block 2");
});
dispatch_group_async(group, queue, ^{
NSLog(@"block 3");
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"end");
});
NSLog(@"go");
8、使用快速枚舉迭代一個(gè)可變數(shù)組時(shí)需要注意什么問題?怎么避免?
不要在可變數(shù)組中直接刪除,通過(guò) 倒敘遍歷的方式避免。
9、什么是面向?qū)ο蟮亩鄳B(tài)性?
直接的說(shuō):對(duì)于不同對(duì)象響應(yīng)同一個(gè)方法時(shí)做出的不同反應(yīng)。
常見的場(chǎng)景:不同的子類共用父類的方法,或者這么說(shuō)他們各自以自己的方式響應(yīng)相同的消息 。
明顯的好處: 如果父類有的方法,那么子類不能調(diào)用,那么每次都得子類自己再寫一個(gè)方法,就顯的有點(diǎn)麻煩啦。
13、在iOS開發(fā)中遇到那些類族(Class Cluster) ?如NSNumber這種。為什么需要這種設(shè)計(jì)方式?
- 類族: 其實(shí)應(yīng)該說(shuō) 類簇,是一種設(shè)計(jì)模式,它管理了一組隱藏在公共接口下的私有類。
NSNumber *testChar = [NSNumber numberWithChar:’t’];
NSNumber *testInt = [NSNumber numberWithInt:10];
NSNumber *testFloat = [NSNumber numberWithFloat:20.0];
NSNumber *testDouble = [NSNumber numberWithDouble:1.0];
- 好處:可以隱藏抽象基類背后的復(fù)雜細(xì)節(jié),使用者只需調(diào)用基類簡(jiǎn)單的方法就可以返回不同的子類實(shí)例。
16、使用了ARC 是不是就等于沒有內(nèi)存泄漏了?如果不是的話請(qǐng)舉例。
- 循環(huán)引用的情況: Delegate, Block, NSTimer, 這里可展開的太多了,也是我們平常接觸比較多的。
- CoreFundation/CoreGraphics 相關(guān)函數(shù)
CGBitmapContextCreate(, , , , , , )
CGImageRelease(CGImageRef image)
這兩者都是配套使用的哦,這個(gè)可能平時(shí)直接使用的不多的。
18、進(jìn)程的內(nèi)存布局是怎樣的?
- 進(jìn)程: 一個(gè)正在運(yùn)行的程序可以看做一個(gè)進(jìn)程。
- 內(nèi)存布局:代碼段、全局/靜態(tài)存儲(chǔ)區(qū)、常量區(qū)、自由存儲(chǔ)區(qū)、堆、棧。
這一塊可以再次回顧內(nèi)存相關(guān)的東東: 對(duì)于內(nèi)存的幾點(diǎn)筆記
19、在 GCD 中,那幾種場(chǎng)景會(huì)出現(xiàn)死鎖的現(xiàn)象?怎么避免?
這個(gè)問題看到一篇不錯(cuò)的文章總結(jié),直接巧這里: 說(shuō)說(shuō)GCD中的死鎖。
文章中舉例說(shuō)明了,我們可能遇到的三種場(chǎng)景:
- 主線程調(diào)用主線程
- 同步串行隊(duì)列嵌套自己
- 信號(hào)量阻塞主線程
話說(shuō)自己真的好像基本沒有遇到過(guò)哎,??????
20、怎么用 NSOperation 封裝一個(gè)異步請(qǐng)求?這個(gè)Operation 需要放到NSOperationQueue 里調(diào)度的?
真心說(shuō)平時(shí) NSOperation 用的也不多的,但作為 GCD 的更高層封裝,有著直接取消和依賴的特征,確實(shí)是有其優(yōu)勢(shì)的。
-
我認(rèn)為此處考察的主要是 NSOperation 的異步執(zhí)行,對(duì)其子類 NSInvocationOperation 和 NSBlockOperation 用法的考察。
- NSInvocationOperation 默認(rèn)直接是執(zhí)行同步的,需要添加到 NSOperationQueue 中去才會(huì)去執(zhí)行異步的。
- 當(dāng)然也可以直接用 NSBlockOperation 添加多任務(wù)來(lái)進(jìn)行異步任務(wù)的。
NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(request) object:nil];
[operationQueue addOperation:operation];
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^(){
NSLog(@"Main :%@",[NSThread currentThread]);
}];
[operation addExecutionBlock:^() {
NSLog(@"Excution:%@", [NSThread currentThread]);
}];
[operation start];
- 需要調(diào)度,可以設(shè)置最大操作數(shù)目的。
// 最大并發(fā)數(shù)為4
[operationQueue setMaxConcurrentOperationCount:4];
21、CoreFoundation 和 Foundation 有什么區(qū)別?
#import <Foundation/Foundation.h>
#import <CoreFoundation/CoreFoundation.h>
- Core Foundation是一個(gè)通用的C框架,而Foundation是一個(gè)通用的Objective-C框架。
- 兩者都提供集合類,運(yùn)行循環(huán)等,并且許多 Foundation 類是圍繞 CF 類的再次包裝。
- CF大多是開源的,而 Foundation 是封閉源。
注意下,Core Foundation 中 __bridge 關(guān)鍵字, 很強(qiáng)大的。
25、OC的數(shù)組是怎么實(shí)現(xiàn)的?和C的數(shù)組區(qū)別在?簡(jiǎn)單說(shuō)一下即可。
這個(gè)問題我是懵逼的,然后找到了一篇文章 NSMutableArray原理揭露, 才略微了解下的,這篇文章可以拜讀下,哈哈。
27、setNeedLayout 的作用是什么?
簡(jiǎn)單的說(shuō),調(diào)用 setNeedLayout 之后,后續(xù)會(huì)調(diào)用 layoutSubviews, 然后陸續(xù)調(diào)整 當(dāng)前視圖及子視圖的布局。
28、什么時(shí)候用NS_OPTIONS,NS_ENUM?
- 1、NS_ENUM 枚舉項(xiàng)的值為 NSInteger,NS_OPTIONS 枚舉項(xiàng)的值為 NSUInteger;
- 2、NS_ENUM 定義通用枚舉,NS_OPTIONS 定義位移枚舉;
- 3、NS_ENUM 是每一個(gè)值自動(dòng)被賦予從0開始依次累加1的值,而 NS_OPTIONS 是手動(dòng)被賦予一個(gè)帶有一個(gè)bit偏移量的值:類似1 << 0、 1 << 1、 1 << 2等。
此處參考: 詳解枚舉NS_OPTIONS與NS_ENUM的區(qū)別與格式, 說(shuō)的很詳細(xì)。直接用時(shí)感覺就是第二個(gè)的區(qū)別,也就是 NS_OPTIONS 可以同時(shí)用多個(gè)枚舉值,而NS_ENUM 只能用一個(gè)枚舉值。
Finally: 自我吐槽
發(fā)現(xiàn)自己從事 iOS 工作也算有一段時(shí)間啦, 發(fā)現(xiàn)現(xiàn)在和去年好像是差不多的水準(zhǔn),除了業(yè)務(wù)能力熟悉了下,技術(shù)水準(zhǔn)貌似木有提高哎,涉及到稍微底層還是懵逼哦,??????,只能自我安慰其他非技術(shù)方面有些進(jìn)步啦。。。