iOS 头条一面 面试题

作者 : 开心源码 本文共3959个字,预计阅读时间需要10分钟 发布时间: 2022-05-13 共220人阅读

原文地址

1、如何高效的切圆角?

切圆角共有以下三种方案:

  • cornerRadius + masksToBounds:适用于单个视图或者视图不在列表上且量级较小的情况,会导致离屏渲染。

  • CAShapeLayer+UIBezierPath:会导致离屏渲染,性能消耗严重,不推荐使用。

  • Core Graphics:不会导致离屏渲染,推荐使用。

2、什么是隐式动画和显式动画?

隐式动画指的是改变属性值而产生的默认的过渡动画(如background、cornerRadius等),不需要初始化任何类,系统自己解决的动画属性;显式动画是指自己创立一个动画对象并附加到layer上,如 CAAnimation、CABasicAnimation、CAKeyframeAnimation

3、UIView 和 CALayer 的区别?

UIView 是 CALayer 的 delegate,UIView 可以响应事件,而 CALayer 则不能。

4、离屏渲染?

iOS 在不进行预合成的情况下不会直接在屏幕上绘制该图层,这意味着 CPU 和 GPU 必需先准备好屏幕外上下文,而后才能在屏幕上渲染,这会造成更多时间时间和更多的内存的消耗。

5、Objective – C 能否支持方法重载(overloading)?

不支持。方法重载(overloading):允许创立多项名称相同但输入输出类型或者个数不同的方法。

// 这两个方法名字是不一样的,尽管都是writeToFile开头-(void) writeToFile:(NSString *)path fromInt:(int)anInt;-(void) writeToFile:(NSString *)path fromString:(NSString *)aString;

注:Swift 是支持的。

func testFunc() {}func testFunc(num: Int) {}

6、KVC 的应用场景及注意事项

KVC(key-Value coding) 键值编码,指iOS开发中,可以允许开发者通过Key名直接访问对象的属性,或者者给对象的属性赋值。不需要调用明确的存取方法,这样即可以在运行时动态访问和修改对象的属性,而不是在编译时确定。
它的四个主要方法:

- (nullable id)valueForKey:(NSString *)key;                          //直接通过Key来取值- (void)setValue:(nullable id)value forKey:(NSString *)key;          //通过Key来设值- (nullable id)valueForKeyPath:(NSString *)keyPath;                  //通过KeyPath来取值- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;  //通过KeyPath来设值

应用场景:

  • 动态取值和设值
  • 访问和改变私有变量
  • 修改控件的内部属性

注意事项:

  • key 不要传 nil,会导致崩溃,可以通过重写setNilValueForKey:来避免。
  • 传入不存在的 key 也会导致崩溃,可以通过重写valueForUndefinedKey:来避免。

7、如何异步下载多张小图最后合成一张大图?

使用Dispatch Group追加block到Global Group Queue,这些block假如一律执行完毕,就会执行Main Dispatch Queue中的结束解决的block。

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);dispatch_group_t group = dispatch_group_create();dispatch_group_async(group, queue, ^{ /*加载图片1 */ });dispatch_group_async(group, queue, ^{ /*加载图片2 */ });dispatch_group_async(group, queue, ^{ /*加载图片3 */ }); dispatch_group_notify(group, dispatch_get_main_queue(), ^{        // 合并图片});

8、NSTimer 有什么注意事项?在 dealloc 中调用[timer invalidate];会避免循环引用吗?

  • 时间延后。假如 timer 处于耗时较长的 runloop 中,或者者当前 runloop 处于不监视 timer 的 mode 时(如 scrollView 滑动时)。它在下次 runloop 才会触发,所以可能会导致比预期时间要晚。
  • 循环引用。target 强引用 timer,timer 强引用 target。

时间延后

使用 dispatch_source_t来提高时间精度。

dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);if (timer) {    dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, interval * NSEC_PER_SEC), interval * NSEC_PER_SEC, (1ull * NSEC_PER_SEC) / 10);    dispatch_source_set_event_handler(timer, block);    dispatch_resume(timer);}

循环引用
在 dealloc 中调用 [timer invalidate];不会避免循环引用。由于 timer 会对 target 进行强引用,所以在 timer 没被释放之前,根本不会走 target 的 dealloc 方法。
可以通过以下几种方法来避免:

假如 iOS 10 及以上,可以使用nit(timeInterval:repeats:block:)。target 不再强引用 timer。记得在 dealloc 中调用 [timer invalidate];,否则会造成内存泄漏。

timer = Timer(timeInterval: 1.0, repeats: true, block: { [weak self] (timer) in    self?.timerFunc()})
  • 使用中间件的方式来避免循环引用。
// 定义@implementation WeakTimerTarget{    __weak target;    SEL selector;}- (void)timerDidFire:(NSTimer *)timer {    if(target) {        [target performSelector:selector withObject:timer];    } else{        [timer invalidate];    }}@end// 使用WeakTimerTarget *target = [[WeakTimerTarget alloc] initWithTarget:self selector:@selector(tick)];timer = [NSTimer scheduledTimerWithTimeInterval:30.0 target:target selector:@selector(timerDidFire:) ...];

9、对 property 的了解

@property = ivar + getter + setter;

10、Notification 的注意事项

在哪个线程发送通知,就在哪个线程接受通知。

11、Runloop的了解

一般来讲,一个线程一次只能执行一个任务,执行完成后线程就会退出。假如我们需要一个机制,让线程能随时解决事件但并不退出,通常的代码逻辑 是这样的:

function loop() {    initialize();    do {        var message = get_next_message();        process_message(message);    } while (message != quit);}

12、对 OC 中 Class 的源码了解?其中 cache 的了解?

Class 的底层用 struct 实现,源码如下:

struct _class_t {    struct _class_t *isa;    struct _class_t *superclass;    void *cache;    void *vtable;    struct _class_ro_t *ro;};

Cache用于缓存最近使用的方法。一个类只有一部分方法是常用的,每次调用一个方法之后,这个方法就被缓存到cache中,下次调用时 runtime 会先在 cache 中查找,假如 cache 中没有,才会去 methodList 中查找。以此提升性能。

13、项目优化做了哪些方面?

  • 删除无用资源文件及代码
  • 在合适的地方加缓存
  • 耗时长的代码异步执行

14、如何一劳永逸的检测包的裂变(检测包的大小)?

这个不知道,希望理解的朋友可以在评论区指出来。

15、实现一个判断 IP 地址能否合法的方法

func isIPAddress(str: String) -> Bool {    guard !str.isEmpty else { return false }    var isIPAddress = false    let coms = str.components(separatedBy: ".")    for com in coms {        if let intCom = Int(com), intCom >= 0, intCom <= 255 {            isIPAddress = true        } else {            isIPAddress = false            return isIPAddress        }    }    return isIPAddress}

资料推荐

假如你正在跳槽或者者正准备跳槽不妨动动小手,增加一下咱们的交流群1012951431来获取一份详细的大厂面试资料为你的跳槽多添一份保障。

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » iOS 头条一面 面试题

发表回复