美文网首页
查漏补缺

查漏补缺

作者: 纳兰沫 | 来源:发表于2020-10-22 16:20 被阅读0次

1.NSObject和id的区别

NSObject和id都可以指向任何对象
NSObject对象会在编译时进行检查
id类型不需要编译时检查 不需要强制类型转换

2.id类型, nil , Nil ,NULL和NSNULL的区别?

- id类型 是一个独特的数据类型 可以转换为任何数据类型 id类型的变量可以存放任何数据的对象 在内部处理上 
这种类型被定义为指向对象的指针 实际上是一个指向这种对象的实例变量的指针 id声明的对象具有运行时特性 
即可以指向任意的对象
- nil 是一个实例对象的值 如果要把一个class的对象设置为空的时候 就用nil
- NIl 是一个类对象的值 如果要把一个class的对象设置为空的时候 用Nil
- NULL 指向基本数据类型的空指针
NSNULL 是一个对象 用在不能使用nil的场合

3.SMutableDictionary 中使用setValueForKey 和 setObjectForKey有什么区别?

如果调用setValue仍然是调用了setObject方法 如果参数value为nil 则会调用removeObject移除这个键值对
- setObjectForKey 是SMutableDictionary特有的  value不能为nil 否则会崩溃
- setValueForKey 是kvc的 key必须是字符串类型 setObject的key可以是任意类型

4.NSCache 和NSDictionary 区别?

@NSCache 可以提供自动删减缓存功能 而且保证线程安全 与字典不同 不会拷贝键
@NSCache可以设置缓存上限 限制对象个数和总缓存开销 定义了删除缓存对象的时机 这个机制只对NSCache起到指导作用,不会一定执行
@NSPurgeableData搭配NSCache使用,可以自动清除数据

5.什么是面向过程?(POP--Procedure Oriented Programming)

“面向过程”(Procedure Oriented)是一种以过程为中心的编程思想。就是分析出解决问题所需要的步骤,然后
用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。注重的是实现过程!

6.什么是面向对象?(OOP--Object Oriented Programming)

“面向对象”是一种以对象为中心的编程思想。

面向对象的三大特性:

@封装
隐藏对象的属性和实现细节,仅对外提供公共访问方式,将变化隔离,便于使用,提高复用性和安全性。
@继承
提高代码复用性;建立了类之间的关系;子类可以拥有父类的所有成员变量的方法;继承是多态的前提。
@多态
父类或接口定义的引用变量可以指向子类或具体实现类的实例对象。提高了程序的拓展性。
正因为面向对象编程有着着三种特性,继承、封装、多态,从而使得面向对象编程更具有容易让人接受,更贴近与
人们的生活,比面向对象编程更加方便与快捷,一定程度上降低了程序员的工作量,使程序的可读性也得到了提高,代码的效率也得到了提高

7. 为什么说OC是一门动态语言?

动态语言:是指程序在运行时可以改变其结构,新的函数可以被引进,已有的函数可以被删除等在结构上的变化
动态类型语言: 就是类型的检查是在运行时做的。
OC的动态特性可从三方面:

动态类型(Dynamic typing):  最终判定该类的实例类型是在运行期间
动态绑定(Dynamic binding):在运行时确定调用的方法
动态加载(Dynamic loading):在运行期间加载需要的资源或可执行代码

8.简要说明const,宏,static,extern区分以及使用?

const

const常量修饰符,经常使用的字符串常量,一般是抽成宏,但是苹果不推荐我们抽成宏,推荐我们使用const常量。

- const 作用:限制类型
- 使用const修饰基本变量, 两种写法效果一致 , b都是只读变量
  const int b = 5; 
  int const b = 5;   
- 使用const修饰指针变量的变量 
  第一种: const int *p = &a 和 int const *q = &a; 效果一致,*p 的值不能改,p 的指向可以改; 
  第二种: int * const p = &a;  表示 p 的指向不能改,*p 的值可以改
  第三种: 
  const int * const p = &a; *p 值和 p 的指向都不能改
  
  const 在*左边, 指向可变, 值不可变
  const 在*的右边, 指向不可变, 值可变
  const 在*的两边, 都不可变

* 基本概念:宏是一种批量处理的称谓。一般说来,宏是一种规则或模式,或称语法替换 ,用于说明某一特定输入
(通常是字符串)如何根据预定义的规则转换成对应的输出(通常也是字符串)。这种替换在预编译时进行,称作宏
展开。编译器会在编译前扫描代码,如果遇到我们已经定义好的宏那么就会进行代码替换,宏只会在内存中copy一
份,然后全局替换,宏一般分为对象宏和函数宏。 宏的弊端:如果代码中大量的使用宏会使预编译时间变长。

const与宏的区别?

* 编译检查 宏没有编译检查,const有编译检查;
* 宏的好处 定义函数,方法 const不可以;
* 宏的坏处 大量使用宏,会导致预编译时间过长

static

* 修饰局部变量: 被static修饰局部变量,延长生命周期,跟整个应用程序有关,程序结束才会销毁,被 static 修饰局部变量,只会分配一次内存
* 修饰全局变量: 被static修饰全局变量,作用域会修改,也就是只能在当前文件下使用

extern

声明外部全局变量(只能用于声明,不能用于定义)

常用用法(.h结合extern联合使用)
如果在.h文件中声明了extern全局变量,那么在同一个类中的.m文件对全局变量的赋值必须是:数据类型+变量名
(与声明一致)=XXXX结构。并且在调用的时候,必须导入.h文件。代码如下:

.h
@interface ExternModel : NSObject
extern NSString *lhString;
@end 
.m     
@implementation ExternModel
NSString *lhString=@"hello";
@end

调用的时候:例如:在viewController.m中调用,则可以引入:ExternModel.h,否则无法识别全局变量。当
然也可以通过不导入头文件的方式进行调用(通过extern调用)。

9.什么是指针常量和常量指针?

常量指针本质是指针,常量修饰它,表示这个指针乃是一个指向常量的指针(变量)。
指针指向的对象是常量,那么这个对象不能被更改。

指针常量的本质是一个常量,而用指针修饰它,那么说明这个常量的值应该是一个指针。
指针常量的值是指针,这个值因为是常量,所以不能被赋值

10.静态库和动态库的区别

静态库
@以.a和.framework为文件后缀名
@链接时会被完整的复制到可执行文件中 被多次使用就有多份拷贝
动态库
@以.tbd和.framework为文件后缀名
@链接时不复制 程序运行时由系统动态加载到内存 系统只加载一次 多个程序共用 节省内存

静态库.a和framework的区别是.a主要是二进制文件 不包含资源 需要自己添加头文件 .framework可以包含头文件和资源信息

11.函数指针和 Block区别

相同点
@都是一个代码片段
@函数指针类型和Block类型都可以作为变量和函数类型的类型
不同点
@函数指针只能指向预先定义好的函数代码块 函数地址是在编译连接时就已经确定好的 从内存的角度看 函数指针
只不过是指向代码区的一段可执行代码
@block本质是oc对象 是NSObject的子类 是程序运行过程中在栈内存动态创建的对象 可以向其发送copy消息 
将block对象拷贝到堆内存 以延长其生命周期

12.ViewController 生命周期

- initWithCoder:(NSCoder *)aDecoder:(如果使用storyboard或者xib)
- loadView:加载view
- viewDidLoad:view加载完毕
- viewWillAppear:控制器的view将要显示
- viewWillLayoutSubviews:控制器的view将要布局子控件
- viewDidLayoutSubviews:控制器的view布局子控件完成  
- viewDidAppear:控制器的view完全显示
- viewWillDisappear:控制器的view即将消失的时候
- viewDidDisappear:控制器的view完全消失的时候
- dealloc 控制器销

13.CALayer的frame,bounds,anchorPoint,position

frame          左上角相对于坐标系的位置
bounds         左上角相对于自身坐标系的位置
anchorPoint    锚点在自身坐标系中的相对位置 通常用于做相对的tranform交换
position       锚点在supLayer坐标系中的位置

14.layoutSubview和drawRect

layoutSubviews调用情况

init初始化UIView不会触发调用
addSubview会触发调用
改变view的width和height的时候回触发调用
一个UIScrollView滚动会触发调用
旋转screen会触发调用
改变一个UIView大小的时候会触发superView的layoutSubviews事件
直接调用setLayoutSubviews会触发调用
-(void)viewWillAppear:(BOOL)animated会触发一次调用
-(void)viewDidAppear:(BOOL)animated 看情况,可能有调用

drawRect调用情况

如果UIView没有设置frame大小,直接导致drawRect不能被自动调用。
drawRect在loadView和viewDidLoad这两个方法之后调用
调用sizeToFit后自动调用drawRect
通过设置contentMode值为UIViewContentModeRedraw。那么每次设置或者更改frame自动调用drawRect。
直接调用setNeedsDisplay或者setNeedsDisplayInRect会触发调用

15. layoutIfNeeded , layoutSubViews和 setNeedsLayout区别

@layoutIfNeeded 方法一点被调用,主线程会立即强制重新布局,它会从当前视图开始,一直到完成所有子视图的布局
@layoutSubViews 用来自定义视图尺寸,他是系统自动调用的,开发者不能手动调用,可以重写改方法,让系统在
调整布局时候按照我们希望的方式进行布局.这个方法在旋转屏幕,滑动或者触摸屏幕,修改子视图时候被触发.
@setNeedsLayout 和 layoutIfNeeded相似,唯一不同的是他不会立即强制视图重新布局,而是在下一个布局
周期才会触发更新.他主要用于多个视图布局先后更新的场景

16.程序启动过程

main 函数执行前

1.首先当程序启动时,系统会读取程序的可执行文件(mach-o), 从里面获取动态加载器(dylb)的路径;
2.加载dylb, dylb会初始化运行环境,配合ImageLoader将二进制文件加载到内存中去;
3.动态链接依赖库, 初始化依赖库,初始化 runtime;
4.runtime 会对项目中的所有类进行类结构初始化,调用所有的 load 方法;
5.最后 dylb 会返回 main 函数地址,main 函数被调用,进入程序入口

main 函数执行后

1.内部会调用 UIApplicationMain 函数,创建一个UIApplication对象和它的代理,就是我们项目中的 Appdelegate 类
2.开启一个事件循环(main runloop), 监听系统事件
3.程序启动完毕时,通知代理Appdelegate, 调用 didFinishLaunching 代理方法,在这里会创建 UIWindow,设置它的rootViewController,
4.最后调用 self.window makeKeyAndVisable显示窗口

17.UIScrollView 原理

UIScrollView继承自UIView,内部有一个 UIPanGestureRecongnizer手势。 frame是相对父视图坐标系
来决定自己的位置和大小,而bounds是相对于自身坐标系的位置和尺寸的。改视图 bounds 的 origin 视图本
身没有发生变化,但是它的子视图的位置却发生了变化,因为 bounds 的 origin 值是基于自身的坐标系,当自
身坐标系的位置被改变了,里面的子视图肯定得变化, bounds 和 panGestureRecognize 是实现 
UIScrollView 滑动效果的关键技术点

18.使用 drawRect 有什么影响?

@drawRect 方法依赖 Core Graphics 框架来进行自定义的绘制
@缺点:它处理 touch 事件时每次按钮被点击后,都会用 setNeddsDisplay 进行强制
@重绘;而且不止一次,每次单点事件触发两次执行。这样的话从性能的角度来 说,对 CPU 和内存来说都是欠佳的。
特别是如果在我们的界面上有多个这样的 UIButton 实例,那就会很糟糕了
@这个方法的调用机制也是非常特别. 当你调用 setNeedsDisplay 方法时, UIKit 将会 把当前图层标记为 
dirty,但还是会显示原来的内容,直到下一次的视图渲染周期,才会 将标记为 dirty 的图层重新建立 
Core Graphics 上下文,然后将内存中的数据恢复出 来, 再使用 CGContextRef 进行绘制

19.masksToBounds 和clipsToBounds

masksToBounds 是指子 layer 在超出父 layer时是否被裁剪,YES表示参见,NO 表示不裁剪, 默认是NO
clipsToBounds 是指子 View 在超出父 View时是否被裁剪

20.什么是隐式动画和显示动画

隐式动画是系统框架自动完成的。Core Animation在每个runloop周期中自动开始一次新的事务,即使你不显式的用[CATransaction begin]开始一次事务,任何在一次runloop循环中属性的改变都会被集中起来,然后做一次0.25秒的动画。在iOS4中,苹果对UIView添加了一种基于block的动画方法:+animateWithDuration:animations:。这样写对做一堆的属性动画在语法上会更加简单,但实质上它们都是在做同样的事情。CATransaction的+begin和+commit方法在+animateWithDuration:animations:内部自动调用,这样block中所有属性的改变都会被事务所包含,多用于简单动画效果

 [UIView animateWithDuration:1 animations:^{
        view.center = self.view.center;
    }];

显式动画,Core Animation提供的显式动画类型,既可以直接对layer层属性做动画,也可以覆盖默认的图层行为。我们经常使用的CABasicAnimation,CAKeyframeAnimation,CATransitionAnimation,CAAnimationGroup等都是显式动画类型,这些CAAnimation类型可以直接提交到CALayer上。显式动画可用于实现更为复杂的动画效果

CABasicAnimation *positionAnima = [CABasicAnimation animationWithKeyPath:@"position.y"];
positionAnima.duration = 0.8;
positionAnima.fromValue = @(self.imageView.center.y);
positionAnima.toValue = @(self.imageView.center.y-30);
positionAnima.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
positionAnima.repeatCount = HUGE_VALF;
positionAnima.repeatDuration = 2;
positionAnima.removedOnCompletion = NO;
positionAnima.fillMode = kCAFillModeForwards;
[self.imageView.layer addAnimation:positionAnima forKey:@"AnimationMoveY"];

21.SafeArea, SafeAreaLayoutGuide, SafeAreaInsets 关键词的比较说明

由于 iphoneX 采用了刘海设计,iOS11引入了安全区域(SafeArea)概念

SafeArea是指App 显示内容的区域,不包括StatusBar,Navigationbar,tabbar,和 toolbar, 在
 iPhoneX 中一般是指扣除了statusBar(44像素),和底部home indicator(高度为34像素)的区域.这样操作不会被刘海或者底部手势影响了.
SafeAreaLayoutGuide 是指 Safe Area 的区域范围和限制, 在布局设置中,可以取得他的上下左右4个边界位置进行相应的布局
SafeAreaInsets限定了Safe Area区域与整个屏幕之间的布局关系,一般用上下左右4个值来获取 SafeArea 与屏幕边缘之间的距离

22.内存泄漏可能会出现的几种原因

第一种可能:第三方框架不当使用;
第二种可能:block循环引用;
第三种可能:delegate循环引用;
第四种可能:NSTimer循环引用
第五种可能:非OC对象内存处理
第六种可能:地图类处理
第七种可能:大次数循环内存暴涨

23.是否可以把比较耗时的操作放在 NSNotification中?

如果在异步线程发的通知,那么可以执行比较耗时的操作;
如果在主线程发的通知,那么就不可以执行比较耗时的操作

24.NSOperation取消线程方式?

1.通过 cancel 取消未执行的单个操作

NSOperationQueue *queue1 = [[NSOperationQueue alloc]init];
NSBlockOperation *block1 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"block11");
}];
NSBlockOperation *block2 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"block22");
}];
NSBlockOperation *block3 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"block33");
}];
[block3 cancel];
[queue1 addOperations:@[block1,block2,block3] waitUntilFinished:YES];

2.移除队列里面所有的操作,但正在执行的操作无法移除

[queue1 cancelAllOperations];

3.挂起队列,使队列任务不再执行,但正在执行的操作无法挂起

queue1.suspended = YES;

4.我们可以自定义NSOperation,实现取消正在执行的操作。其实就是拦截main方法。

main方法:
 1、任何操作在执行时,首先会调用start方法,start方法会更新操作的状态(过滤操作,如过滤掉处于“取消”状态的操作)。
 2、经start方法过滤后,只有正常可执行的操作,就会调用main方法。
 3、重写操作的入口方法(main),就可以在这个方法里面指定操作执行的任务。
 4、main方法默认是在子线程异步执行的。

25.什么是序列化和反序列化,用来做什么

序列化  把对象转化为字节序列的过程
反序列  化把直接序列恢复成对象
作用    把对象写到文件或者数据库中,并且读取出来

26.沙盒目录结构是怎样的

Documents:常用目录,iCloud备份目录,存放数据,这里不能存缓存文件,否则上架不被通过
Library
  Caches:存放体积大又不需要备份的数据,SDWebImage缓存路径就是这个
  Preference:设置目录,iCloud会备份设置信息
tmp:存放临时文件,不会被备份,而且这个文件下的数据有可能随时被清除的可能

27.使用 NSUserDefaults 时,如何处理布尔的默认值?(比如返回 NO,不知道是真的 NO 还是没有设置过)

如果使用 - (void)setBool:(BOOL)value forKey:(NSString *)defaultName;方法,来进行存储,就可以获取到正确的 bool 值
如果使用 - (void)setObject:(nullable id)value forKey:(NSString *)defaultName;,需要在获取到值后在转为 bool类型

28.当数据库中的某项数据未 null 时候,通过FMDB获取的数据为

[NSNull null]

相关文章

  • 【Android面试查漏补缺】之事件分发机制详解

    前言 查漏补缺,查漏补缺,你不知道哪里漏了,怎么补缺呢?本文属于【Android面试查漏补缺】系列文章第一篇,持续...

  • 查漏补缺

    如果想让HTML5标签兼容低版本浏览器的话,可以使用 html5shiv js来实现。注意:一定要把它引入到前面。...

  • 查漏补缺

    图文环绕和浮动 最初的CSS只是用来写文章,熟练使用float和clear两个属性来布局: float属性:指定一...

  • 查漏补缺

    1.js字符串转换成数字与数字转换成字符串的实现方法https://www.2cto.com/kf/201612/...

  • 查漏补缺

    浮动原理 1.使用之初:是为了让文字环绕图片,并且不会遮住文字。如果让图片与文字有间距,我们在浮动元素上添加。2....

  • 查漏补缺

    今天数学老师外出学习,我用了一上午的时间给孩子们查漏补缺。 首先,训练朗读:从段落与段落之间的大停顿...

  • 查漏补缺

    1 Python提供了ord()和chr()函数,可以把字母和对应的数字相互转换2 写 u'中' 和 u'\u4e...

  • 查漏补缺

    generator(生成器) 什么是生成器:把一个列表推倒式l = [x for x in range(10)]改...

  • 查漏补缺

    session 判断

  • 查漏补缺

    1 xhtml和html有什么区别? 一个是功能上的差别 主要是XHTML可兼容各大浏览器、手机以及PDA,并且浏...

网友评论

      本文标题:查漏补缺

      本文链接:https://www.haomeiwen.com/subject/fuxlmktx.html