IOS某外派岗位面试

前言:考核基础有没有盲区,是否有意识写出正确代码

001 循环引用的原因,它会造成怎样的后果以及如何避免?

循环引用的原因是对象在作用域结束后无法回收,会造成内存泄漏。

1.NSTimer 在创建的时候会默认对当前self有个强引用,这里可以用一个weakself对象进行持有,在dealloc方法中,一定要先使用[self.timer invalidate];

然后将timer=nil;

timerWithTimeInterval创建的timer需要手动添加到runloop中,而scheduledTimerWithTimeInterval创建的timer会自动添加到runloop中,是DefaultMode,但是在一个tableview的上放置的timer,那需要timerWithTimeInterval来创建,手动添加到NSRunLoopCommonModes中

2.block中使用对象需要在block外面进行__weak将self转化成weakself,避免循环引用;在block函数作用域中需要将weakself中一个局部__strong变量进行转化,为了让在作用域范围之后被回收。

3.Delegate,一般在声明delegate的时候都要使用弱引用weak

002 我们一般开发会用到CoreFundation对象,这些非指针对象,这些在ARC管理下会有一些编译问题,可能做一些处理,你能说一下原因么?

这个意思就是说当我们用到一些比较古老的MRC代码的时候如何在ARC下运行起来

在MRC代码会爆出'retain' is unavailable: not available in automatic reference counting mode

可以在Xcode编译进行调整targets---build phase--complie sources里找到对应的文件添加flag

开启:-fobjc-arc 关闭-fno-objc-arc

targets--build settings 搜automatic reference counting; yes --开启 no--关闭

其中的原因是ARC=LLVM+runtime

003 为什么要使用关联对象?

它使得可以在Runtime为某个类对象绑定一个对象

属性在分类中编译器是不能生成的,需要关联对象手动生成.具体如下:

@interface MyObject (set)

@property (nonatomic, assign) NSInteger pageValue;

@end

#import "MyObject+set.h"

#import <objc/runtime.h>

@implementation MyObject (set)

- (NSInteger)pageValue{

    return  [objc_getAssociatedObject(self, @selector(pageValue)) intValue];

}

- (void)setPageValue:(NSInteger)pageValue{

        objc_setAssociatedObject(self, @selector(pageValue), @(pageValue), OBJC_ASSOCIATION_ASSIGN);

}

@end

在分类中,因为累的实力变量的布局以及固定,使用@property已经无法向固定的布局中添加新的实例变量(有可能会覆盖子类的实例变量),使用关联对象

objc_getAssociatedObject和objc_setAssociatedObject两个方法来模拟构成属性的三个要素。

三要素:

生成实例变量;生成getter方法--property;生成setter方法--setProperty

004 GCD里有个优先级,这个优先级是怎么体现的?

dispatch_set_target_queue(serialQueue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0));

GCD 串行 并发队列中线程是怎样执行的

007 OC提供哪些工具或者方法来解决线程不安全?

1.atomic 修饰符,它只是保证了属性的setter和getter方法内部是线程安全的。

2.锁 如下图各种所得消耗性能

 

 

008 锁--一般加锁会有开销,开销成本体现在哪里?

枷锁的目的是保证共享资源在任意时间里,只有一个线程访问,这样就可以避免多线程导致共享数据错乱的问题

两个常见的锁:互斥锁自旋锁

互斥锁加锁失败后,线程会释放CPU,给其他线程

自旋锁加锁失败后,线程会忙等待,直到它拿到锁

对于互斥锁佳作失败而阻塞的现象,是由操作系统内核实现的。互斥锁加锁失败后会从余台陷入内核态,让内核帮忙切换线程。

存在一定开销成本。(切换上下文的成本)

  • 当线程加锁失败时,内核会把线程的状态从「运行」状态设置为「睡眠」状态,然后把 CPU 切换给其他线程运行;
  • 接着,当锁被释放时,之前「睡眠」状态的线程会变为「就绪」状态,然后内核会在合适的时间,把 CPU 切换给该线程运行。

如果你能确定被锁住的代码执行时间很短(内存管理中自旋锁引用计数+-1),就不应该用互斥锁,而应该选用自旋锁,否则使用互斥锁。

自旋锁是通过CAS函数(Compare and Swap)包含两个步骤

1.查看锁的状态,如果锁是空闲的,则执行第2步;如果不是空闲就在这里等待

2.将锁设置成当前线程持有

009 UIView和CALayer 的联系和区别?

  • 联系

每一个 view 中都有一个 layer,view 持有并管理这个 layer,且这个 view 是 layer 的代理。

  • 区别

UIView 负责响应事件,参与响应链,为 layer 提供内容。

CALayer 负责绘制内容,动画。

事件响应链

hit-test寻找hit-test view 也就是触摸事件所在的view

发生触摸事件后系统将事件放在一个由UIApplication管理的队列中,UIApplication将事件发送给KeyWindown,KeyWindown在视图树中寻找一个最适合的view来响应事件

1.view自身是否能够接受触摸事件,

2.触摸点是否在自己范围内

3.从后往前遍历subviews,重复执行1和2

如果没有找到符合条件的子试图,自己就是最合适的

但是需要保证视图 isUserInteractionEnabled 为 YES,isHidden 为 NO,alpha 大于 0.01。

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;   
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event;

通过 Hit-testing 找到了触摸 view 之后。调用这个 view 的 touches 方法来做具体处理:

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;

如果这个 view 调用了 [super touches] 方法,则事件顺着响应者链向上传递(子视图向父视图)。

其顺序为view-->super--->superview-->viewController-->rootViewController-->window-UIApplication

如果到最后UIApplication都没有处理,则丢弃。

App在处理交互事件时会创建新的UIView,也会修改现有的View,然后就会更新约束,调整布局,再渲染并显示

0010 如果我用CAAnimation做一个动画,类似于一个红包雨场景,从上到下这个运动过程,当运动到中间的时候,红包view的frame,指向的是哪里?

CALayer层 考核是否使用过CAAnimation动画交互场景

每个 CALayer 有一个 presentationLayer 属性,当CAAnimation发生时,你在屏幕上看到的实际上是 presentation layer 的改变。如果你访问 presentation layer,QuartzCore 将会计算现有的帧状态,并且使用这个帧状态去构建 presentation layer 对象。因为动画状态在动画执行期间一直处于改变,因此你将会获得近似值。

 

在GitHub上搜红包关键字 很多demo

隐式动画 修改layer可动画属性 系统完成的

显式动画 是创建CAAnimation对象提交到Layer执行的动画。

0011 界面卡顿的一些情况,界面卡顿的原因是什么?

在一个16.6毫秒的垂直信号到来之前CPU和GPU的工作没有完成

CPU层面:

1.尽量用轻量级对象例如K线用CASharpLayer

2.不要频繁调用UIView 的相关属性

3.提前计算好布局,例如朋友圈炸好评排布

4.Autolayout会比直接设置frame消耗更多CPU资源

5.图片的size最好与UIImageView的size保持一致

6.控制一下线程的最大并发量

7.尽量把耗时的操作异步子线程中,执行完成之后返回到主线程进行数据刷新操作

GPU层面:

1.尽量避免短时间内大量图片的显示,尽可能将多张图片合成一张进行显示

2.GPU能处理的最大纹理尺寸是4096X4096,一旦超过这个尺寸,就会占用GPU资源进行处理

3.尽量减少视图的数量和层次

4.减少透明度的视图,不透明就设置opaque为YES

5.尽量避免离屏渲染

怎么解决阴影圆角渲染造成的卡顿问题?

 UIBezierPathh 画 CAShapeLayer

// Create a mask layer.
CAShapeLayer *maskLayer = [CAShapeLayer new];
maskLayer.frame = self.bounds;// Define our path, capitalizing on UIKit's corner rounding magic.
UIBezierPath *newPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:self.layer.cornerRadius];maskLayer.path = newPath.CGPath;// Apply the mask.
self.layer.mask = maskLayer;

0012 一般开发的时候会用到约束,怎么做给界面添加的约束是刚刚好的?

NSLayoutConstraint

0013 http和https区别?

0014 https 中证书校验过程?

https://juejin.im/post/6844903545272041479

0015 算法题

本地机子上有2K-3K个通讯录,远端也有2K-3K个通讯录,怎么比较快的找到这两个集合之间差别的部分,它的时间复杂度是怎样的?

O(N+M)

class Solution {

public:

    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {

        unordered_set<int> result_set; // 存放结果

        unordered_set<int> nums_set(nums1.begin(), nums1.end()); //nums1 存入set中

        for (int num : nums2) {

            // 发现nums2的元素 在nums_set里又出现过

            if (nums_set.find(num) != nums_set.end()) {

                result_set.insert(num);

            }

        }

        return vector<int>(result_set.begin(), result_set.end());

    }

};

参考文献:

https://www.cnblogs.com/xiaolincoding/p/13675202.html

https://www.jianshu.com/p/c94de311e226

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值