iOS面试知识总结之基本概念总结

凡经历过iOS面试的我们总会发觉,即使实际开发中做过许多项目,也难免为一个普通的面试题受挫。这也许不是因为我们技术不过关,而是因为在平时我们忽略了怎样将用到的知识很好的表述出来。闲暇之余我把一些常见的iOS面试问题总结一下,即使不是为了面试,也有助于对基础知识的回顾。 此篇总结在iOS日常开发中经常遇到的基本概念性问题:

1.了解iOS开发者账号类型

  1. “个人”开发者可以申请升级“公司”,可以通过拨打苹果公司客服电话(400 6701 855)来咨询和办理。
  2. 公司账号允许多个开发者进行协作开发,比个人多一些帐号管理的设置,可设置多个Apple ID,分4种管理级别的权限。申请公司账号需要填写公司的邓白氏编码(DUNS Number)。
  3. 需要注意的是,企业账号开发的应用不能上线App Store,适合那些不希望公开发布应用的企业。同样,申请时也需要公司的邓白氏编码(DUNS Number)。

2.Property属性

1.原子性:nonatomic 、atomic 2.读写: readwrite 、readonly 3.方法名:getter=<name>、setter=<name> 4.内存:strong、retain、copy、weak、assign 、unsafe_unretained

atomic:原子性,只有一个线程可以同时访问实例。atomic 是线程安全的,至少在当前的读取器是安全的。虽然它是一个默认属性,但是由于其使用同步锁开销较大,会损耗性能。 nonatomic:非原子性的,可以被多个线程访问。效率要比atomic 高,但是不能保证其在多线程状态下的安全性,在单线程和明确只有一个线程访问的情况下被广泛使用。

readwrite(默认值):表示其同时拥有getter 和 setter 方法; readonly:只读操作,其只有getter 方法,没有setter法 注:如果某个实例只允许被外部读取,而不能写入操作,同时在类实现文件当中可以写入的话,可以在头文件中声明属性为只读的,在实现文件中设置其为可读写的属性,写法如下:

//头文件中声明为:
@property(nonatomic,readonly,copy) NSString *stringA;
//实现文件中声明为:
@property(nonatomic,readwrite,copy) NSString *stringA;

getter=<name>的样式: @property (nonatomic, getter=isOn) BOOL on;

assign:用于值类型(如int,float等) weak: 用于修饰引用类型 unsafe_unretained:只修饰引用类型 区别:

  1. 三者修饰效果相同,即都不会更改所赋新值的引用计数,也不改变旧值的引用计数
  2. assign一般只修饰值类型,虽然也可以修饰引用类型,但是修饰的对象释放后,指针不会自动被置空,此时向对象发消息会崩溃。
  3. weak 不会产生野指针问题。因为weak修饰的对象释放后(引用计数器值为0),指针会自动被置nil,之后再向该对象发消息也不会崩溃。 weak是安全的。
  4. unsafe_unretained与assign的区别在于,其只修饰引用类型。

strong:用于引用类型,强引用。 retain :用于引用类型,强引用。 copy:修饰属性会在内存里拷贝对象。 区别:

  1. 三者都用于修饰引用类型。
  2. strong用于ARC,retain用于MRC。
  3. copy分为浅层复制和深复制两种,NSString、NSArray、NSDictionary等不可变类型都为浅层复制,即其引用计数会+1,而不会创建新的内存。

3.了解沙盒的目录结构

iOS应用沙盒即文件系统目录,与其他应用的文件系统隔离

  • Documents:保存应用运行时生成的需要持久化的数据,如游戏进度、涂鸦软件的绘图等信息, 该目录会被iTunes同步备份。
  • Library/Caches:保存应用运行时生成的需要持久化的数据,iTunes同步设备时不会备份该目录。一般存储体积大、不需要备份的非重要数据,如缓存图片或者离线数据(地图等)。
  • Library/Preference:保存应用的所有偏好设置,iOS的Settings(设置)应用会在该目录中查找应用的设置信息。iTunes同步设备时会备份该目录。
  • tmp:保存应用运行时所需的临时数据,使用完毕后再将相应的文件从该目录删除。应用没有运行时,系统也可能会清除该目录下的文件。iTunes同步设备时不会备份该目录。重新手机、系统磁盘不足时都会被清理

4.理解内存中的区域划分

栈区(stack):由系统自动分配和释放,存放局部变量的值,容量小速度快,有序 :一般由程序员分配和释放,如果不释放,则出现内存泄露。程序会回收您的内存,特点:容量大,速度慢,无序 静态存储区:全局变量(外部变量)和静态变量都存放在静态区域。当程序结束使,系统回收 常量区:存放常量的内存区域,程序结束时,系统回收 代码区:存放二进制代码的区域

5.理解iOS的远程推送

简易推送流程

(1) 应用程序安装后提示用户是否需要接收推送,用户确认后注册消息推送。 (2)App接收到从APNS Server获取的令牌信息; (3)APP将令牌信息发送到自己的服务器端; (4)当需要向用户推送消息时,自己的服务器将向苹果的推送通知服务器(Apple Push Notification Service,以下简称 APNS)发送通知; (5)APNS 会向装有此APP的iPhone设备发送消息

第三方推送的原理(以个推为例)

6.理解Block的使用

  1. Block为什么要用copy a、block在创建的时候默认分配的内存是在栈上,而不是在堆上。这样的话其本身的作用域是属于创建时候 的作用域,一旦在创建的作用域之外调用就会导致程序的崩溃。所以使用了copy将其拷贝到堆内存上。 b、block创建在栈上,而block的代码中可能会用到本地的一些变量,只有将其拷贝到堆上,才能用这些变量
  2. Block为什么不用retain retain这是增加了一次计数,block的内存还是在栈上,并没有存在堆上,存在栈上的block可能随时被系统回收。
  3. 为什么进入block中的对象引用计数需要自动加1 Block执行的是回调,因此block并不知道其中的对象obj创建后会在什么时候被释放,为了不在block使用obj之前,对象已经被释放,block就retain了obj一次
  4. block和函数的关系 Block的使用很像函数指针,不过与函数最大的不同是Block可以访问函数以外、词法作用域以内的外部变量的值。 换句话说,Block不仅 实现函数的功能,还能携带函数的执行环境。
  5. 对于block的理解 block实际上是: 指向结构体的指针 编译器会将block的内部代码生成对应的函数
  6. 对于基本数据类型,进入到block中会被当做常量处理
 //如果需要在block中对num进行修改,需要加上关键字__block
 //(我们也可以用static关键字进行修饰)
  int  num1 = 10;
  void(^block1)() = ^{
       NSLog(@"num1 is %d",num1);
  };
  num1 = 20;
  block1(); //输出10
       
  //改进:使用block,使进入到block块中的变量不被当做常量来使用
  __blockint  num2 = 10;
  void(^block2)() = ^{
     NSLog(@"num2 is %d",num2);
  };
  num2 = 20;
  block2(); //输出20
  1. Block中self的循环引用 block默认创建在栈上,所以对要对其进行执行copy操作,将其拷贝到堆区,便于更好的操作对象。但是执行了copy操作之后,block中使用self,此对象会被retain一次(注意:block在堆区上时才会起到retain作用),会造成循环引用。 解决方法: 在MRC下,使用__block修饰 在ARC下,使用__unsafe_unretained\weak修饰

7.理解循环引用出现的三种情况:

  1. NSTimer NSTimer对象timer作为一个对象A的属性,本意在A的dealloc中释放timer,但是timer没有停止就不会触发dealloc,然后就互相等待,造成循环引用。解决方法是显式的调用timer的关闭方法[timer invaluate],再释放A对象
  2. Block block代码块没有配合weak使用
  3. Delegate 声明delegate时请用assign(MRC)或者weak(ARC)。

循环引用举例:

NSMutableArray *firstArray = [NSMutableArray array]; 
NSMutableArray *secondArray = [NSMutableArray array];
[firstArray addObject:secondArray]; 
[secondArray addObject:firstArray]; 

检测循环引用 Xcode -> Product -> Pofile -> Leaks

8.理解指针的使用

用变量a给出下面的定义原文链接 a) 一个整型数 b) 一个指向整型数的指针 c) 一个指向指针的的指针,它指向的指针是指向一个整型数 d) 一个有10个整型数的数组 e) 一个有10个指针的数组,该指针是指向一个整型数的 f) 一个指向有10个整型数数组的指针 g) 一个指向函数的指针,该函数有一个整型参数并返回一个整型数 h) 一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数

a) int a; // An integer 

b) int *a; // A pointer to an integer

c) int **a; // A pointer to a pointer to an integer

d) int a[10]; // An array of 10 integers

e) int *a[10]; // An array of 10 pointers to integers

f) int (*a)[10]; // A pointer to an array of 10 integers

g) int (*a)(int); // A pointer to a function a that takes an integer argument and returns an integer

h) int (*a[10])(int); // An array of 10 pointers to functions that take an integer argument and return an integer

9、理解iOS中的多线程

1.概念理解: 多线程是针对于单核的CPU来设计的,目的是为了让CPU快速在多个线程之间进行调度。 多线程的优缺点 优点:提高程序的执行效率 缺点:开启线程需要一定的内存空间

同步和异步:决定了可不可以开启新的线程 同步:在当前线程中执行任务,不具备开启新线程的能力 异步:在新的线程中执行任务,具备开启新线程的能力

并行与串行:决定了任务的执行方式 并行:多个任务并发(同时)执行。类型迅雷,多个任务同时开启下载 串行:一个任务执行完毕后,再执行下一个任务。类似浏览器的一个接一个下载

iOS应用程序中都是一个主线程,也成为UI线程 那么主线程的作用就是用来更新UI,显示或者刷新界面 注意:不能将耗时的任务放在主线程上,否则会出现卡顿的现象。

2.iOS的三种多线程编程技术 NSThread 直接操作线程对象,但需要手动管理生命周期,而且经常使用这种方式来查看当前线程 GCD(Grand Central Dispatch) 底层使用的是C语言,灵活方便,可以根据系统负荷来增减线程,性能效率更好 Cocoa NSOperation NSOperation对GCD的封装,使用起来更好理解,将任务封装为NSOpertaion,添加到NSOPerationQueue对象中 子类化NSOpertaion的设计,更具有面向对象(封装,复用)的特性。更加适合在复杂项目中使用

3.进程与线程 Progress和Thread,进程和线程是操作系统里的基本概念 线程与进程的区别: 线程是资源分配的最小单位,也是处理器调度的基本单位,但是进程不是 进程是资源拥有的单位,同一个进程内的线程共享进程里的资源 多进程,允许多个任务同时运行 多线程,允许单个任务分为不同的部分运行

10.了解音频播放相关知识

音频的播放从形式上分为音频播放和音乐播放。 音频播放:通常时间较短,不需要进度控制,和循环控制。使用AudioToolbox.framework。 音乐播放:通常时间较长,需要进行精准控制。使用AVFoundation.framework。

音频播放 AudioToolbox.framework是基于C语言的框架。 原理:将短音频注册的到系统声音服务(System Sound Service)中。System Sound Service是一种简单、底层的声音播放服务。 1.音频播放时间不能超过30秒。 2.数据必须是PCM或者IMA4格式。 3.音频格式必须打包成.caf、.aif、wav中的一种。(这是官方说法,实际发现一些.mp3也可以)。

音乐播放 1.适合播放较大的音频。 2.可以对音频进行精准的播放控制 3.使用AVFoundataion.framework中的AVAudioPlayer来实现。 使用: 1.初始化AVAudioPlayer对象,通常是指定本地文件路径 2.设置播放器属性,例如重复次数,音量大小等。 3.调用play方法播放。

注意:AVAudioPlayer一次只能播放一个音频文件,所有的上一曲和下一曲都是通过创建多个AVAudioPlayer来实现的。

11.了解视频播放相关知识

Apple已经为我们提供了多种方法来实现视频播放,包括MPMoviePlayerController,MPMoviePlayerViewController,AVPlayer,AVPlayerViewController等。而值得注意的是,上述的MPMoviePlayerController与MPMoviePlayerViewController在iOS9.0之后被弃用。下面是四种播放方式的区别:

11.理解OC中的反射机制
  1. class反射:通过类名字符串实例化对象
Class class = NSClassFromString(@“Student”);
Student *student = [[class alloc] init];
  1. 类名转化为字符串
Class class = [student class];
NSString *calssName = NSStringFromClass(class);
  1. SEL的反射
SEL selector = =NSSelectorFromClass(@“setName”);
[stu performSelector:selector withObject:nil];
  1. 通过方法字符串形式实例化方法
 NSStringFromSelector(@selector *( “setName:”));

12.理解一个对象被创建需要的三个步骤

开辟内存空间 初始化参数 返回内存地址值

13.layoutSubView何时调用

1、 初始化方法事不会调用 2、滚动UIScrollview触发 3、旋转屏幕时触发 4、改变View的值时候触发,前提是frame改变了 5、改变UIView的大小时触发

14.理解NSOperationQueue

NSOperationQueue是存放NSOPeration的集合类,可以参考JAVA中的线程和线程池的概念。 虽说是queue,但并不是队列的意思,并不遵守先进先出。 所以我们可以理解为Pool ,即线程池。

15.理解OC是动态运行时语言

OC将数据、对象类型的确定从编译阶段推迟到了运行时。实现这一操作的基础是面向对象语言的多态特性。 这里面有有两个关键字:运行时和多态 运行时:运行时机制使我们知道运行的时候才确定一个对象的类型、以及调用该类别对象指定的方法。 多态:不同的对象以自己的方式来响应相同的消息。子类的指针可以赋值给父类。

16.GCD的queue、main queue中执行的代码一定是在main thread么?

queue中所执行的代码不一定在main thread中。如果queue是在主线程中创建的,那么所执行的代码就是在主线程中执行。如果是在子线程中创建的,那么就不会在main thread中执行。上述说法并不完全正确,queue中所执行的代码不一定在主线程是对的,但是队列Queue中执行的任务是在否在主线程与创建队列所在的线程并无关系。

对于这个问题,首先总结几个知识点: 1.iOS中获取队列的三种方式: 主线程队列: 主线程队列为串行队列,和主线程绑定。同普通串行队列一样,队列中任务一次只能执行一个,但是队列中所有任务都在主线程中执行(经过测试,即使是异步添加的任务,也没有创建新的线程)。

全局队列: 系统全局队列为并发队列,根据不同的优先级(HIGH、DEFAULT、LOW、BACKGROUND)有四个。

自定义队列: 系统提供方法,可以自定义创建串行和并行队列。

2.同步与异步,串行与并行 同步与异步:决定可不可以开启新的线程 同步:在当前线程立即执行添加的任务,不具备开启新线程的能力。 异步:在新的线程中执行任务,具备开启新线程的能力

并行与串行:决定了任务的执行方式 并行:可以多个任务并发(同时)执行。类型迅雷,多个任务同时开启下载 串行:一个任务执行完毕后,再执行下一个任务。类似浏览器的一个接一个下载

对于这个问题,我使用代码测试了使用的情况如下:

总结:队列Queue中执行的任务是在否在主线程与创建队列所在的线程无关。

判断一个任务是不是在主线程,我们可以首先判断同步还是异步,因为异步才具有开启新线程的能力。然而我们还需要注意两点: 1.主线程所在队列为串行队列,添加同步会导致死锁。 2.并非所有的异步任务都不在主线程中,主线程队列中添加异步任务,并不开启新的线程。

17.常见的Http状态码有哪些?

302是请求重定向。 500及以上是服务器错误,如503表示服务器找不到、3840表示服务器返回无效JSON。 400及以上是请求链接错误或者找不到服务器,如常见的404。 200及以上是正确,如常见的是200表示请求正常。 更多参考: Http状态码详细说明

总结

对于细碎知识点的学习,经过了不断的测试和理解,我们才会发现还有太多值得研究的地方。非常感谢评论区不少朋友帮我提出的问题,如果有不对的地方我也会尽快更正。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏H2Cloud

C++中消息自动派发之一 About JSON

1. 闲序   游戏服务器之间通信大多采用异步消息通信。而消息打包常用格式有:google protobuff,facebook thrift, 千千万万种自定...

2453
来自专栏编程

JAVA面试常考系列八

题目一 JDBC是什么? JDBC(Java DataBase Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为...

35611
来自专栏大内老A

WCF技术剖析之二十一:WCF基本异常处理模式[中篇]

通过WCF基本的异常处理模式[上篇], 我们知道了:在默认的情况下,服务端在执行某个服务操作时抛出的异常(在这里指非FaultException异常),其相关的...

20210
来自专栏分布式系统和大数据处理

.Net 项目代码风格参考

代码风格没有正确与否,重要的是整齐划一,这是我拟的一份《.Net 项目代码风格参考》,供大家参考。

1322
来自专栏高爽的专栏

Hession反序列化导致CPU占用飙高

背景 今天发布一个线上服务,暂且称之为O,发布完后,依赖O服务的2个服务C和W大量Time报警,并且这两个服务的CPU占用都飙到了40%左右,平时只有10%的样...

3650
来自专栏熊二哥

快速入门系列--MVC--04模型

model元数据    闲来继续学习蒋金楠大师的ASP.NET MVC框架揭秘一书,当前主要阅读的内容是Model元数据的解析,即使是阅读完的现在,仍然有不少...

1925
来自专栏前端达人

JavaScript基础——回调(callback)是什么

上篇文章《JavaScript基础——你真的了解JavaScript吗?》,我们明白了JavaScript是一个单线程、非阻塞、异步、解释性语言,清楚了什么是单...

1757
来自专栏华章科技

干货:手把手教你用Python读写CSV、JSON、Excel及解析HTML

导读:本文要介绍的这些技法,会用Python读入各种格式的数据,并存入关系数据库或NoSQL数据库。

1362
来自专栏FreeBuf

Windows内核漏洞CVE-2016-0143分析

0x00 背景 4月20日,Nils Sommer在exploitdb上爆出了一枚新的Windows内核漏洞PoC。该漏洞影响所有版本的Windows操作系统,...

2236
来自专栏Golang语言社区

Go并发编程基础(译)

原文:Fundamentals of concurrent programming 译者:youngsterxyf 本文是一篇并发编程方面的入门文章,以Go语言...

4078

扫码关注云+社区