圖片發(fā)自簡書App
前一陣在趣直播平臺上看了我就叫Sunny怎么了 大神的iOS 面試小灶直播飒货,總結下直播的內容鱼鼓。
簡歷中的問題
1.項目描述過于簡單寬泛
- 項目規(guī)模娃弓?
- 你在其中的職責
- 詳細介紹使用的技術
- 遇到的問題凸舵、坑以及如何解決的贮竟?
2.專業(yè)技能前篇一律
- 在列舉技術名詞時最好寫出用這個技術干了什么崎逃?
比如“熟練應用Objc runtime 技術,曾使用它做了ViewController 進入和退出時的AOP 埋點”
3.格式眉孩、拼寫个绍、細節(jié)
- Object-C
- Foudation
- ios
- xCode
4.提供更多的信息來體現你的特別
- Blog
- GitHub
- 技術探索
- 對技術的個人理解
- 做過什么有意思的事兒
我就叫Sunny怎么了 的一般套路
- 最近的工作,App浪汪,負責哪些模塊(考察前一份工作的難度)
- 找個最熟悉的業(yè)務巴柿,描述一下設計結構,UI層級死遭,控件的使用广恢,布局,交互效果等(考察基本業(yè)務能力呀潭,熟練程度钉迷,質量)
- 考察幾個基礎的問題至非,如內存管理,多線程
- 從簡歷里熟練或掌握的技術中找?guī)讉€深聊
- 找面試者研究過的糠聪,有心得或熟練的東西聊
- 考慮更深度的問題
- 溝通是否順暢
幾個面試題
property
-
@property
能使用哪些關鍵字及作用是什么荒椭?
答:
屬性 | 作用 |
---|---|
strong | 釋放舊對象將舊對象的值賦予輸入對象,再提高輸入對象的索引計數為1 |
weak | weak不增加對對象的引用計數舰蟆,也不持有對象趣惠,因此不能決定對象的釋放。它比assign多了一個功能身害,當對象消失后自動把指針變成nil |
assign | 簡單賦值味悄,不更改索引計數,適用于基礎數據類型(NSInteger CGFloat)和C數據類型(int float double char 等)簡單數據類型 |
copy | 對應mutableCopy塌鸯。此屬性只對那些實行了NSCopying協(xié)議的對象類型有效侍瑟。根據調用類型不同,決定是深拷貝還是淺拷貝界赔,一般都是淺拷貝丢习,只復制了指針,內容還是同一份 |
atomic | 和 nonatomic用來決定編譯器生成的getter和setter是否為原子操作淮悼,atomic 設置成員變量的@property屬性時 默認為是atomic 提供線程安全咐低。在多線程環(huán)境下,原子操作是必要的否則會引起錯誤的結果袜腥。 |
nonatomic | 非原子性訪問對于屬性賦值的時候不加鎖见擦,多線程并發(fā)訪問會提高性能,如果不加此屬性則默認是兩個訪問方法都為原子型事務訪問羹令。 |
readonly | 此標記說明屬性是只讀的 |
readwrite | 此標記說明屬性會被當成讀寫的 這也是默認的屬性 |
unsafe_unretained | 跟weak類似鲤屡,聲明一個弱引用,但是當引用計數為0時福侈,變量不會自動設置為nil |
getter | 指定 get 方法酒来,并需要實現這個方法。必須返回與聲明類型相同的變量肪凛,沒有參數 |
setter | 指定 set 方法堰汉,并需要實現這個方法。帶一個與聲明類型相同的參數伟墙,沒有返回值(返回空值) |
- 下面這4種寫法的區(qū)別
@property (nonatomic, strong) NSArray *array0;
@property (nonatomic, copy) NSArray *array1;
@property (nonatomic, strong) NSMutableArray *array2;
@property (nonatomic, copy) NSMutableArray *array3;
答:
array0如果傳進來的是mutableArray 翘鸭,如果里面元素被改變的話,會可能出現問題戳葵;
array1標準寫法就乓,當傳經來的是mutableArr時,會變成不可變版本,但里面元素不會復制一份生蚁,都是淺拷貝噩翠;
array2是標準寫法;
array3當設置時守伸,會被變成不可變版本绎秒,后續(xù)如果調用mutableArr的消息,會導致crash尼摹;
基本內存管理
下面對象分別在什么時候釋放见芹?
- (void)ARCProblem{
id obj0 = @"sunny";
__weak id obj1 = obj0;
id obj2 = [NSObject new];
__weak id obj3 = [NSObject new];
{
id obj4 = [NSObject new];
}
__autoreleasing id obj5 = [NSObject new];
__unsafe_unretained id obj6 = self;
}
- obj0 是一個字符串,分配在常量區(qū)蠢涝,所以不會釋放
- obj1 是weak 指向obj0 會生成一個map 來映射對象和指針的關系玄呛,當對象釋放時,會反向查找所有的指針和二,將指針置為nil徘铝。這里obj0 是個常量,不會被釋放惯吕,所以obj1不會釋放
- obj2 當對象用完就會釋放
- obj3 這行語句結束就會釋放
- obj4 定義在一個scope里惕它,scope結束就會釋放
- obj5 會加到自動釋放池中,會在最近的
AutoreleasePool pop
被釋放 - obj6 可能隨時都會被釋放
UIViewController
這樣寫會發(fā)生什么废登?
- (void)viewDidLoad {
[super viewDidLoad];
self.view = nil;
}
第一次self.view 時會調用loadView方法加載view 淹魄,當加載結束后會調用viewDidLoad
。有可能遞歸調用堡距,但是如果之后沒有操作self.view 就不會遞歸甲锡,屏幕上會黑屏。
UITableView
UITableViewDataSource
和 UITableViewDelegate
中的主要方法有哪些羽戒,調用順序和時機是怎樣的缤沦?
block 內存管理
如何解決下面代碼的問題
- (void)blockRetailCycleProblem{
self.block = ^{
NSLog(@"%@",@[self]);
}
}
解決方案:
- (void)blockRetainCycleAnswer0{
__weak typeof(self) weakSelf;
self.block = ^{
NSLog(@"%@",@[weakSelf]);
}
}
- (void)blockRetainCycleAnswer1{
__weak typeof(self) weakSelf;
self.block = ^{
__weak typeof(weakSelf) strongSelf = weakSelf;
NSLog(@"%@",@[weakSelf]);
}
}
- (void)blockRetainCycleAnswer2{
__weak typeof(self) weakSelf;
self.block = ^{
__weak typeof(weakSelf) strongSelf = weakSelf;
if(strongSelf){
NSLog(@"%@",@[strongSelf]);
}
}
}
前兩種都有weakself 都有提前被釋放的可能,會導致crash易稠,第三種比較全面
block 內存管理 Extension
下面的 self 用不用 weak 缸废?
- (void)blockRetainCycleProblemExt{
[UIView animateWithDuration:1 animations:^{
self.view.frame = CGRectMake(1,2,3,4);
}]
}
那這個呢?
[UIView animateWithDuration:1 delay:10000 options:0 animations:^{
self.view.frame = CGRectMake(1,2,3,4);
}]
動畫block 是瞬間執(zhí)行的驶社,不會持有self的
代碼規(guī)范改錯
typedef enum{
UserSex_Man,
UserSex_woman
}UserSex;
@interface UserModel : NSObject
@property(nonatomic, strong) NSString* name;
@property (assign, nonatomic) int age;
@property (nonatomic, assign) UserSex sex;
- (id)initUserModelWithUserName:(NSString*)name withAge:(int)age;
- (void)doLogin;
@end
修改如下:
typedef NS_ENUM(NSUInteger, XXUserGender){
XXUserGenderUndefine,
XXUserGenderMale,
XXUserGenderFemale,
XXUserGenderSark
};
@interface XXUserModel : NSObject
@property (nonatomic, copy) NSString* identifier;
@property (nonatomic, copy) NSString* name;
@property (nonatomic, assign) NSUInteger age;
@property (nonatomic, assign) XXUserGender sex;
+ (instancetype)modelWithIdentifier:(NSString *)identifier;
- (void)login;
@end
理解應用架構
-
MVC
和MVVM
的理解 -
Stack
和Heap
分別的使用企量,如果管理? -
ARC
是如何實現的衬吆? -
Autorelease
對象何時釋放? -
AutoreleasePool
是如何實現的 - 理解
Class
與對象模型 - 理解
RunLoop
深入理解消息機制
問題:從寫入[obj foo] 這行代碼知道運行時foo 被調用绳泉,盡量詳細描述中間都發(fā)生了什么逊抡?
掌握:objc_msgSend 的關鍵調用,后續(xù)如何通過selector 從isa 找到IMP ,若運行時沒有找到foo 會如何?
精通:編譯器如何編譯成objc_msgSend冒嫡、消息cache 機制拇勃、消息轉發(fā)機制、objc_msgSend 的各個版本孝凌、objc_msgSend 的實現方咆、跳板機制等
魔法數字
//64位,下面會輸出什么蟀架,為什么瓣赂?
- (void)magicNumberProblem{
//Tagged Pointer
NSLog(@"%@",11529223390768879413UL);
}
輸出sunny,在64位下,指針的空間很大片拍,比實際指向的值還大煌集,所以采用Tagged Pointer 機制,直接在指針的地址里存放值捌省。
另辟蹊徑的block 調用
void (^block)(void) = ^{
NSLog(@"block get called");
}
禁止調用block();
答:
[UIView animateWithDuration:1 animations:block];
//or
dispatch_async(dispatch_get_main_queue(), block);
[[NSBlockOperation blockOperationWithBlock:block] start];
[[NSInvocation invocationWithMethodSignature:[NSMethodSignatrue signatureWithObjCTypes:"v@?"]] invokeWithTarget:block];
//"v@?" 為block 的簽名 v 表示返回值苫纤,@?表示第一個參數 為block 本身
//NSInvocation 一般用法
NSMethodSignature *signature = [self methodSignatureForSelector:@selector(description)];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
invocation.target = self;
invocation.selector = @selector(description);
[invocation invoke];
//比較黑
[block invoke];
//block 是NSBlock 類型
//經查找NSBlock 里有這些實例方法
- (void)copy;
- (void)copyWithZone:({_NSZone=} *)arg0;
- (void)invoke;
- (void)performAfterDelay:(double)arg0;
//更黑
//Block內部結構
struct Block layout{
void *isa;
volatile int32_t flag;
int32_t reserved;
void (*invoke)(void *,...);
struct Block_descriptor_1 *descriptor;
};
void *pBlock = (__bridge void*)block;//取到block的首地址
void (*invoke)(void *,...) = *((void **)pBlock + 2);//取到invoke函數的偏移量地址 32位加3
invoke(pBlock);
//節(jié)點
__strong void(^cleaner)(void) __attribute__((cleanup(blockCleanUp), unused)) = block;
asm("callq *0x10(%rax)");//匯編 真正調用方式
談談iOS 進階
- 要去聯(lián)想、理解纲缓、有自己的思考卷拘、對技術的主見
- 抽象、領悟祝高、類比能力
- 看書栗弟、看博客、實戰(zhàn)總結褂策、刨根問底
- 進階速度
純日常開發(fā) < 純看書横腿、博客 < 自己試驗、Demo < 寫博客 < 系統(tǒng)性分享和討論 < 提供完整的開源方案 - 對技術保持好奇
- 對原理刨根問底
- 不甘于重復勞動
- 多思考斤寂,多懷疑
- 相信實踐耿焊,不要輕信"大神"