iOS面试题--原理篇

2020-06-28  本文已影响0人  文博同学

runtime怎么添加属性、方法等

是否可以把比较耗时的操作放在NSNotificationCenter中

runtime 如何实现 weak 属性

首先要搞清楚weak属性的特点

weak策略表明该属性定义了一种“非拥有关系” (nonowning relationship)。
为这种属性设置新值时,设置方法既不保留新值,也不释放旧值。此特质同assign类似;
然而在属性所指的对象遭到摧毁时,属性值也会清空(nil out)

作为一个开发者,有一个学习的氛围跟一个交流圈子特别重要,这是一个我的iOS交流群:413038000,不管你是大牛还是小白都欢迎入驻 ,分享BAT,阿里面试题、面试经验,讨论技术, 大家一起交流学习成长!

推荐阅读

iOS开发——最新 BAT面试题合集(持续更新中)

那么runtime如何实现weak变量的自动置nil?

runtime对注册的类,会进行布局,会将 weak 对象放入一个 hash 表中。
用 weak 指向的对象内存地址作为 key,当此对象的引用计数为0的时候会调用对象的 dealloc 方法,
假设 weak 指向的对象内存地址是a,那么就会以a为key,在这个 weak hash表中搜索,找到所有以a为key的 weak 对象,从而设置为 nil。

weak属性需要在dealloc中置nil么

// 模拟下weak的setter方法,大致如下
- (void)setObject:(NSObject *)object
{
    objc_setAssociatedObject(self, "object", object, OBJC_ASSOCIATION_ASSIGN);
    [object cyl_runAtDealloc:^{
        _object = nil;
    }];
}

一个Objective-C对象如何进行内存布局?(考虑有父类的情况)

Objective-C 对象的结构图
ISA指针
根类(NSObject)的实例变量
倒数第二层父类的实例变量
...
父类的实例变量
类的实例变量

一个objc对象的isa的指针指向什么?有什么作用?

下面的代码输出什么?

@implementation Son : Father
- (id)init
{
    self = [super init];
    if (self) {
        NSLog(@"%@", NSStringFromClass([self class]));
        NSLog(@"%@", NSStringFromClass([super class]));
    }
    return self;
}
@end
    -(Class)class {
      return object_getClass(self);
    }

runtime如何通过selector找到对应的IMP地址?(分别考虑类方法和实例方法)

objc中的类方法和实例方法有什么本质区别和联系

类方法

1 类方法是属于类对象的
2 类方法只能通过类对象调用
3 类方法中的self是类对象
4 类方法可以调用其他的类方法
5 类方法中不能访问成员变量
6 类方法中不能直接调用对象方法
7 类方法是存储在元类对象的方法缓存中

实例方法

1 实例方法是属于实例对象的
2 实例方法只能通过实例对象调用
3 实例方法中的self是实例对象
4 实例方法中可以访问成员变量
5 实例方法中直接调用实例方法
6 实例方法中可以调用类方法(通过类名)
7 实例方法是存放在类对象的方法缓存中

使用runtime Associate方法关联的对象,需要在主对象dealloc的时候释放么?

1.调用 -release :引用计数变为零
 * 对象正在被销毁,生命周期即将结束.
 * 不能再有新的 __weak 弱引用,否则将指向 nil.
 * 调用 [self dealloc]
2\. 父类调用 -dealloc
 * 继承关系中最直接继承的父类再调用 -dealloc
 * 如果是 MRC 代码 则会手动释放实例变量们(iVars)
 * 继承关系中每一层的父类 都再调用 -dealloc
3\. NSObject 调 -dealloc
 * 只做一件事:调用 Objective-C runtime 中的 object_dispose() 方法
4\. 调用 object_dispose()
 * 为 C++ 的实例变量们(iVars)调用 destructors
 * 为 ARC 状态下的 实例变量们(iVars) 调用 -release
 * 解除所有使用 runtime Associate方法关联的对象
 * 解除所有 __weak 引用
 * 调用 free()

_objc_msgForward函数是做什么的?直接调用它将会发生什么?

能否向编译后得到的类中增加实例变量?能否向运行时创建的类中添加实例变量?为什么?

runloop和线程有什么关系?

runloop的mode作用是什么?

以+scheduledTimerWithTimeInterval...的方式触发的timer,在滑动页面上的列表时,timer会暂定回调,为什么?如何解决?

猜想runloop内部是如何实现的?

不手动指定autoreleasepool的前提下,一个autorealese对象在什么时刻释放?(比如在一个vc的viewDidLoad中创建)

苹果是如何实现autoreleasepool的?

objc_autoreleasepoolPush
objc_autoreleasepoolPop
objc_aurorelease

GCD的队列(dispatch_queue_t)分哪两种类型?背后的线程模型是什么样的?

苹果为什么要废弃dispatch_get_current_queue?

如何用GCD同步若干个异步调用?(如根据若干个url异步加载多张图片,然后在都下载完成后合成一张整图)

// 创建队列组
dispatch_group_t group =  dispatch_group_create();

// 获取全局并发队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

// 往队列组中添加耗时操作
dispatch_group_async(group, queue, ^{
    // 执行耗时的异步操作1
});

// 往队列组中添加耗时操作
dispatch_group_async(group, queue, ^{
    // 执行耗时的异步操作2
});

// 当并发队列组中的任务执行完毕后才会执行这里的代码
dispatch_group_notify(group, queue, ^{
    // 如果这里还有基于上面两个任务的结果继续执行一些代码,建议还是放到子线程中,等代码执行完毕后在回到主线程

    // 回到主线程
    dispatch_async(group, dispatch_get_main_queue(), ^{
        // 执行相关代码...
    });
});

dispatch_barrier_async的作用是什么?

dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block);
-(void)barrier
{
    dispatch_queue_t queue = dispatch_queue_create("12342234", DISPATCH_QUEUE_CONCURRENT);

    dispatch_async(queue, ^{
        NSLog(@"----1-----%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"----2-----%@", [NSThread currentThread]);
    });

    // 在它前面的任务执行结束后它才执行,在它后面的任务等它执行完成后才会执行
    dispatch_barrier_async(queue, ^{
        NSLog(@"----barrier-----%@", [NSThread currentThread]);
    });

    dispatch_async(queue, ^{
        NSLog(@"----3-----%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"----4-----%@", [NSThread currentThread]);
    });
}

以下代码运行结果如何?

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSLog(@"1");
    dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"2");
    });
    NSLog(@"3");
}

lldb(gdb)常用的调试命令?

BAD_ACCESS在什么情况下出现?

如何调试BAD_ACCESS错误

image image

简述下Objective-C中调用方法的过程(runtime)

什么是method swizzling(俗称黑魔法)

image image

objc中向一个nil对象发送消息将会发生什么?

struct objc_class
{
// isa指针指向Meta Class,因为Objc的类的本身也是一个Object,
// 为了处理这个关系,runtime就创造了Meta Class,
// 当给类发送[NSObject alloc]这样消息时,实际上是把这个消息发给了Class Object
Class isa OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
Class super_class OBJC2_UNAVAILABLE; // 父类
const char *name OBJC2_UNAVAILABLE; // 类名
long version OBJC2_UNAVAILABLE; // 类的版本信息,默认为0
long info OBJC2_UNAVAILABLE; // 类信息,供运行期使用的一些位标识
long instance_size OBJC2_UNAVAILABLE; // 该类的实例变量大小
struct objc_ivar_list *ivars OBJC2_UNAVAILABLE; // 该类的成员变量链表
struct objc_method_list **methodLists OBJC2_UNAVAILABLE; // 方法定义的链表
// 方法缓存,对象接到一个消息会根据isa指针查找消息对象,
// 这时会在method Lists中遍历,
// 如果cache了,常用的方法调用时就能够提高调用的效率。
// 这个方法缓存只存在一份,不是每个类的实例对象都有一个方法缓存
// 子类会在自己的方法缓存中缓存父类的方法,父类在自己的方法缓存中也会缓存自己的方法,而不是说子类就不缓存父类方法了
struct objc_cache *cache OBJC2_UNAVAILABLE;
struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; // 协议链表
#endif
} OBJC2_UNAVAILABLE;

objc中向一个对象发送消息[obj foo]和objc_msgSend()函数之间有什么关系?

什么时候会报unrecognized selector的异常?

使用系统的某些block api(如UIView的block版本写动画时),是否也考虑循环引用问题?

[UIView animateWithDuration:duration animations:^
{ [self.superview layoutIfNeeded]; }];

[[NSOperationQueue mainQueue] addOperationWithBlock:^
{ self.someProperty = xyz; }];

[[NSNotificationCenter defaultCenter] addObserverForName:@"someNotification"
            object:nil
             queue:[NSOperationQueue mainQueue]
        usingBlock:^(NSNotification * notification)
        { self.someProperty = xyz; }];

作为一个开发者,有一个学习的氛围跟一个交流圈子特别重要,这是一个我的iOS交流群:413038000,不管你是大牛还是小白都欢迎入驻 ,分享BAT,阿里面试题、面试经验,讨论技术, 大家一起交流学习成长!

推荐阅读

iOS开发——最新 BAT面试题合集(持续更新中)

上一篇下一篇

猜你喜欢

热点阅读