最近公司项目不怎么忙, 闲暇时间把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…