最近公司項目不怎麼忙, 閒暇時間把iOS 在面試中可能會遇到的問題整理了一番, 一部分題目是本身面試遇到的,一部分題目則是網上收錄的, 方便本身鞏固複習, 也分享給你們! 知識點比較多,比較雜,這裏作了分類,下面是分類連接地址;面試
面試知識點整理 - 目錄:編程
iOS | 面試知識整理 - OC基礎 (一)
iOS | 面試知識整理 - OC基礎 (二)
iOS | 面試知識整理 - OC基礎 (三)
iOS | 面試知識整理 - UI 相 關 (四)
iOS | 面試知識整理 - 內存管理 (五)
iOS | 面試知識整理 - 多 線 程 (六)
iOS | 面試知識整理 - 網絡相關 (七)
iOS | 面試知識整理 - 數據持久化 (八)
iOS | 面試知識整理 - Swift 基礎 (九)安全
malloc_size
函數得到)class_getInstanceSize
函數得到)observeValueForKeyPath:ofObject:change:context:
)手動調用willChangeValueForKey:和didChangeValueForKey:
bash
- (void)viewDidLoad {
[super viewDidLoad];
Person *person = [[Person alloc]init];;
[p addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
[p willChangeValueForKey:@"name"];
[p didChangeValueForKey:@"name"];
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
NSLog(@"被觀測對象:%@, 被觀測的屬性:%@, 值的改變: %@\n, 攜帶信息:%@", object, keyPath, change, context);
}
複製代碼
accessInstanceVarlableDirctly
是否容許修改value值,返回YES, 調用_key, _isKey, key, isKey 進行賦值使用場合:服務器
struct category_t
,裏面存儲着分類的對象方法、類方法、屬性、協議信息當咱們發送消息未找到方法實現,就會進入第二步,動態方法解析: 代碼實現以下微信
// 動態方法綁定- 實例法法調用
+ (BOOL)resolveInstanceMethod:(SEL)sel{
if (sel == @selector(run)) {
Method method = class_getInstanceMethod(self, @selector(test));
class_addMethod(self, sel, method_getImplementation(method), method_getTypeEncoding(method));
return YES;
}
return [super resolveInstanceMethod:sel];
}
// 類方法調用
+(BOOL) resolveClassMethod:(SEL)sel....
複製代碼
未找到動態方法綁定,就會進行消息轉發階段網絡
// 快速消息轉發- 指定消息處理對象
- (id)forwardingTargetForSelector:(SEL)aSelector{
if (aSelector == @selector(run)) {
return [Student new];
}
return [super forwardingTargetForSelector:aSelector];
}
// 標準消息轉發-消息簽名
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
if(aSelector == @selector(run))
{
return [NSMethodSignature signatureWithObjCTypes:"v@:"];
}
return [super methodSignatureForSelector:aSelector];
}
- (void)forwardInvocation:(NSInvocation *)anInvocation{
//內部邏輯本身處理
}
複製代碼
運行時
庫,它爲Objective-C語言的動態特性提供支持,咱們所寫的OC代碼在運行時都轉成了runtime相關的代碼,類轉換成C語言對應的結構體,方法轉化爲C語言對應的函數,發消息轉成了C語言對應的函數調用。經過了解runtime以及源碼,能夠更加深刻的瞭解OC其特性和原理該錯誤是基於OC的消息機制:數據結構
@interface Person : NSObject
@end
@implementation Person
@end
@interface Student : Person
@end
@implementation Student
- (instancetype)init{
if (self= [super init]) {
NSLog(@"%@", [self class]);
NSLog(@"%@", [super class]);
NSLog(@"%@", [self superclass]);
NSLog(@"%@", [super superclass]);
}
}
[self class] 和 [super class] 都是給當前類返送消息,spuer 表示在父類中查找
[self superClass] 和 [super superclass] 也是也當前類發消息,返回父類
第一個打印:
Student / Student/ Person / Person
複製代碼
BOOL res1 = [[NSObject class] isKindOfClass:[NSObject class]];
BOOL res2 = [[NSObject class] isMemberOfClass:[NSObject class]];
BOOL res3 = [[Person class] isKindOfClass:[Person class]];
BOOL res4 = [[Person class] isMemberOfClass:[Person class]];
NSLog(@"%d-%d-%d-%d",res1, res2, res3, res4);
複製代碼
- (bool)isMemberOfClass; 比較的是類對象
+ (bool)isMemberOfClass; 比較的是元類
打印結果: 1 ,0, 0, 0async
NSTimer *timer = [NSTimer timerWithTimeInterval:1 repeats:YES block:nil];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
複製代碼
runloop 只能在一種 mode 下運行, 作不一樣的事情,runloop 會切換到對應的 model 下來執行,默認是 kCFRunLoopDefaultMode 若是視圖滑動再回切換到 UITrackingRunLoopMode,若是須要在多種 mode 下運行則須要手動設置 kCFRunLoopCommonModes;編程語言
都會執行,後交換的會先調用.
第一次交換 viewwillAppAppear 和 test1 的指向的方法實現地址發生變化
第二次交換 viewwillAppAppear 和 test2 實際上等因而 test2 和 test1 進行了交換,由於 viewwillAppAppear 已經變爲了 test1了.
調用 --> viewwillAppAppear
實際調用順序 -->test2--->test1-->viewwillAppAppear
造成一個閉環:viewwillAppAppear 也只會調用一次
複製代碼
- (void)start
{
if (observer)
return;
// // 建立信號
semaphore = dispatch_semaphore_create(0);
// 註冊RunLoop狀態觀察
CFRunLoopObserverContext context = {0,(__bridge void*)self,NULL,NULL};
observer = CFRunLoopObserverCreate(kCFAllocatorDefault,
kCFRunLoopAllActivities,
YES,
0,
&runLoopObserverCallBack,
&context);
CFRunLoopAddObserver(CFRunLoopGetMain(), observer, kCFRunLoopCommonModes);
// 在子線程監控時長
dispatch_async(dispatch_get_global_queue(0, 0), ^{
while (YES)
{
// 假定連續5次超時50ms認爲卡頓(固然也包含了單次超時250ms)
long st = dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, 50*NSEC_PER_MSEC));
// Returns zero on success, or non-zero if the timeout occurred.
if (st != 0)
{
if (!observer)
{
timeoutCount = 0;
semaphore = 0;
activity = 0;
return;
}
// kCFRunLoopBeforeSources 即將處理source kCFRunLoopAfterWaiting 剛從睡眠中喚醒
// RunLoop會一直循環檢測,從線程start到線程end,檢測檢測到事件源(CFRunLoopSourceRef)執行處理函數,首先會產生通知,corefunction向線程添加runloopObservers來監聽事件,並控制NSRunLoop裏面線程的執行和休眠,在有事情作的時候使當前NSRunLoop控制的線程工做,沒有事情作讓當前NSRunLoop的控制的線程休眠。
if (activity == kCFRunLoopBeforeSources || activity == kCFRunLoopAfterWaiting)
{
if (++timeoutCount < 3)
continue;
NSLog(@"有點兒卡");
}
}
timeoutCount = 0;
}
});
}
複製代碼
OC的類其實是一個objc_class類型的結構體,包含了實例變量列表: (objc_ivar_list),能夠經過 runtime 函數來獲取這個列表:OBJC_EXPORT Ivar _Nonnull * _Nullable class_copyIvarList(Class _Nullable cls, unsigned int * _Nullable outCount)
例子:
Student *stu = [[Student alloc]init];
stu.stu_name = @"alex";
stu.stu_age = 10;
unsigned int count = 0;
Ivar *list = class_copyIvarList([stu class], &count);
NSMutableDictionary * dict = [NSMutableDictionary dictionary];
for (int i = 0; i< count; i++){
id iVarName = [NSString stringWithUTF8String:ivar_getName(list[i])];
dict[iVarName] = [stu valueForKey:iVarName];
}
NSLog(@"%@",dict);
複製代碼
runtime 很強大.能夠動態的建立一個全新的類或對象
// 添加一個繼承NSObject的類 類名是MyClass
Class MyClass = objc_allocateClassPair([NSObject class], "MyClass", 0);
// 增長實例變量
class_addIvar(MyClass, "_age", sizeof(NSString *), 0, "@");
//註冊這個類到runtime系統中就可使用他了
objc_registerClassPair(MyClass);
//生成了一個實例化對象
id myobj = [[MyClass alloc] init];
//給剛剛添加的變量賦值
[myobj setValue:@30 forKey:@"age"];
// 打印
NSLog(@"age= %@",[myobj valueForKey:@"age"]);
複製代碼
其實呢做爲一個開發者,有一個學習的氛圍跟一個交流圈子特別重要,這是個人微信 你們有興趣能夠添加 邀請小夥伴們進入微信羣裏一塊兒 交流(想要進入的可加小編微信17512010526)
做者:LEON_iOS
連接:www.jianshu.com/p/f0504db3a…