学习OC

2021-07-14  本文已影响0人  鄭经仁

1.函数和队列的区别?同步函数和异步函数的区别?串行队列和并行队列的区别?什么是栅栏函数 且有什么注意点?

栅栏方法(dispatch_barrier_async):将线程中的任务分割开来
队列是存放任务的 函数是执行任务的 函数是可以添加到队列里执行的
同步 必须要得到方法的返回值才能继续执行 异步 可以跳过执行
并发 允许多任务同时执行 有并发队列和全局并发队列
串行 只能一个一个执行 有串行队列和 主队列
异步函数且不是主队列 会开线程
并发队列 开多条线程
串行队列 开一条线程

2.什么是死锁现象 什么函数队列容易产生?

死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,同步主队列,同步串行添加任务

3.UITabBarController控制器中view的内部结构? 导航控制器呢?

UITabBarController最底下是它自己的View 上面有一个存放子控制器的View的View 底部有一个UITabBar UITabBar里面又有UITabBarButton
UInavigationcontroller栈顶控制器的view有一个存放子控制器的View,的View 顶部有一个navigationbar navigationbar里面又有navigationbaritem

4.frame和bounds区别?

5.UIScrollview底层实现?

要添加拖拽手势、修改bounds的Y值 偏移量需要取反、限制Y值

6.GCD底层实现?

1. 基于XNU内核实现
2. dispatch queue: 管理block
3. dispatch source: 处理事件

7.单例的实现方式有几种?

第一种方式,重写+allocWithZone
+(instancetype)allocWithZone:(struct _NSZone *)zone{
    static id instance = nil;
    @synchronized (self) { //为了线程安全,加上互斥锁
        if (instance == nil) {
            instance = [super allocWithZone:zone];
        }
    }
    return instance;
}
.第二种方式,不用重写+allocWithZone:方法,而是直接用@synchronized
+(instancetype)sharedSingleton{
    static id instance = nil;
    @synchronized (self) {
        if (!instance) {
            instance = [[self alloc] init];
        }
    }
    return instance;
}
第三种方式,通过 GCD 的 dispatch_once 来实现单例,同样可以在保证线程安全的前提下来实现单例
+(instancetype)sharedSingleton{
    static id instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[self alloc] init];
    });
    return instance;
}

8.runloop有几个源?

9.事件传递原理?

其实就是touch点击事件传递到appliction然后传递给window,然后再传给view,并且查找合适的view,通过hittest拦截处理,拦截处理的时候判断是否能支持接受事件点击

10.如何寻找最合适的View?

先判断自己是否能接收触摸事件,再判断触摸的当前点在不在自己身上,如果在自己身上,它会从后往前遍历子控件,遍历出每一个控件后,重启前两步,如果没有符合条件的子控件,那么自身就是最合适的View

11.hitest原理?事件传递?

// 判断自己能否接收事件
if(self.userInteractionEnabled == NO || self.hidden == YES || self.alpha <= 0.01){
    return nil;
}
// 触摸点在不在自己身上
if ([self pointInside:point withEvent:event] == NO) {
    return nil;
}
// 从后往前遍历自己的子控件(重复前面的两个步骤)
int count = (int)self.subviews.count;
for (int i = count -1; i >= 0; i--) {
    UIView *childV = self.subviews[i];
    // point必须得要跟childV相同的坐标系.
    // 把point转换childV坐标系上面的点
    CGPoint childP = [self convertPoint:point toView:childV];
    UIView *fitView = [childV hitTest:childP withEvent:event];
    if (fitView) {
        return fitView;
    } 
}
// 如果没有符合条件的子控件,那么就自己最适合处理
return self;

12.self 和 super的区别?

self 访问的类本身,super访问的是父类

13.kvc和kvo有关系吗?

KVO建立在 KVC 之上

14.static和const区别?

const,只读的全局变量,其值不可修改.
static,规定此全局变量只在当前模块(文件)中可见.
static const,既是只读的,又是只在当前模块中可见的.

15.控制器的View 生命周期?

loadview viewDidLoad viewWillAppear viewwilllayoutsubviews viewdidayoutsubviews viewdidappear viewwillDISappear viewdiddisappear

16.一个控件不能接受事件的原因?

不接收用户交互userInteractionEnabled = NO
当一个控件隐藏时Hidden = YES
当一个控件为透明白时

17.drawrect有什么影响?

缺点:它处理touch事件时每次按钮被点击后,都会用setNeddsDisplay进行强制重绘;而且不止一次,每次单点事件触发两次执行。这样的话从性能的角度来说,对CPU和内存来说都是欠佳的。

18.appdelegate生命周期?

首次运行:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions=====> 程序首次运行
- (void)applicationDidBecomeActive:(UIApplication *)application===> 程序重新激活 !
首次关闭(home):
- (void)applicationWillResignActive:(UIApplication *)application===> 程序将挂起 !
- (void)applicationDidEnterBackground:(UIApplication *)application===> 程序进入后台 !
再次运行:
- (void)applicationWillEnterForeground:(UIApplication *)application===> 程序进入前台 !
- (void)applicationDidBecomeActive:(UIApplication *)application===> 程序重新激活 !
再次关闭:
- (void)applicationWillResignActive:(UIApplication *)application===> 程序将挂起 !
- (void)applicationDidEnterBackground:(UIApplication *)application===> 程序进入后台 !
终止程序:
- (void)applicationWillTerminate:(UIApplication*)application===> 程序将终止 !

19.oc的类信息存放在哪里?

对象方法、属性、成员变量、协议信息,存放在class对象中
类方法,存放在元类对象中
成员变量的具体值,存放在实例对象

20.对象的isa指针指向哪里?

实例对象的isa指向class对象
class对象的isa指向元类对象
元类对象的isa指向基类的元类对象

21.如何给分类添加属性?

22.有几种解决循环引用的方式?

__weak
__unsafe_unretained
__block

23.数组copy之后是新对象还是原对象,里面的元素呢

原数组

24.面向对象和面向过程的区别

面向过程主要是用过程来推导结果,优点是:性能快,缺点是:扩展性不强,不易维护
对象当中封装了对应的解决方法的细节,仅仅对外提供接口,供外部使用.外部无须知道对象内部是如何解决问题的,优点是: 扩展性强,易维护,缺点是: 相对于面向过程性能较差

25.指针函数和函数指针的区别

指针函数本质是一个函数,其返回值为指针。
函数指针本质是一个指针,其指向一个函数。

26.Nsobejct对象本质 是结构体,block本质上也是一个OC对象

27.main函数前后执行的方法

1.main函数之前,获取可执行文件,加载初始化运行环境,初始化依赖库,runtime初始化,返回main函数地砖,调用main函数
2.main函数之后,创建UIApplication对象,设置APPDelegate,开启runloop循环,加载plist文件,调用APPDelegate方法

28.UIview和CALayer

每当创建一个UIview都会创建一个calayer,界面绘制实际是clayer实现的,uiview可以设置coler等属性的原因是UIView有个重要属性layer,可以返回它的主CALayer实例,所以可以调用CALayer的一部分属性和方法,View可以接受并处理事件,而 Layer 不可以
UIView 继承 UIResponder,而 UIResponder 是响应者对象,可以对iOS 中的事件响应及传递,CALayer 没有继承自 UIResponder

28.RunLoop 的五种CFRunLoopMode

kCFRunLoopDefaultMode:默认模式,主线程是在这个运行模式下运行
UITrackingRunLoopMode:跟踪用户交互事件(用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他Mode影响)
UIInitializationRunLoopMode:在刚启动App时第进入的第一个 Mode,启动完成后就不再使用
GSEventReceiveRunLoopMode:接受系统内部事件,通常用不到
kCFRunLoopCommonModes:伪模式,不是一种真正的运行模式,是同步Source/Timer/Observer到多个Mode中的一种解决方案
滑动tableView时,定时器Nstimer同时添加到UITrackingRunLoopMode和kCFRunLoopDefaultMode上。
那么如何把timer同时添加到多个mode上呢?就要用到NSRunLoopCommonModes了

29.layoutIfNeeded和setNeedsLayout的区别

-layoutSubviews方法:这个方法,默认没有做任何事情,需要子类进行重写
-setNeedsLayout方法: 标记为需要重新布局,异步调用######layoutIfNeeded刷新布局,不立即刷新,但layoutSubviews一定会被调用
-layoutIfNeeded方法:如果,有需要刷新的标记,立即调用layoutSubviews进行布局(如果没有标记,不会调用layoutSubviews)

30.TCP为什么是三次握手和四次挥手

https://blog.csdn.net/yu876876/article/details/81560122

上一篇下一篇

猜你喜欢

热点阅读