1.线程与进程的区别和联系?
答:进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。
程和线程的主要差别在于它们是不同的操作系统资源管理方式。
进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。
线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。
2.属性readwrite,readonly,assign,retain,copy,nonatomic 各是什么作用,在那种情况下用?
assign用于简单数据类型,如NSInteger,double,bool,
retain和copy用于对象,
readwrite是可读可写特性;需要生成getter方法和setter方法时
readonly是只读特性 只会生成getter方法 不会生成setter方法 ;不希望属性在类外改变
assign是赋值特性,setter方法将传入参数赋值给实例变量;仅设置变量时;
retain表示持有特性,setter方法将传入参数先保留,再赋值,传入参数的retaincount会+1;
copy表示赋值特性,setter方法将传入对象复制一份;需要完全一份新的变量时。
nonatomic非原子操作,决定编译器生成的setter getter是否是原子操作,atomic表示多线程安全,一般使用nonatomic
- 内存管理的几条原则是什么?按照默认法则,哪些关键字生成的对象需要手动释放?哪些情况下不需要手动释放,会直接进入自动释放池?
•当使用new、alloc或copy方法创建一个对象时,该对象引用计数器为1。如果不需要使用该对象,可以向其发送release或autorelease消息,在其使用完毕时被销毁。
•如果通过其他方法获取一个对象,则可以假设这个对象引用计数为1,并且被设置为autorelease,不需要对该对象进行清理,如果确实需要retain这个对象,则需要使用完毕后release。
•如果retain了某个对象,需要release或autorelease该对象,保持retain方法和release方法使用次数相等。
4.SDWebImage****实现原理:
**先把plceholderImage显示,然后根据URL开始处理图片 -> 从缓存中查找图片是否已经下载 -> 先从内存缓存中查找是否有图片,如果内存缓存中有图片缓存,直接回调,如果内存缓存中么有,从硬盘查找是否已经有缓存 -> 如果从硬盘读取到了图片,将图片添加到内存缓存中,回调展示图片 ->如果从硬盘中没有读取到图片,说明没有缓存,需要下载 ->生成下载器开始下载图片,下载完后对图片解码处理,然后回调展示图片,将图片保存到内存缓存和硬盘缓存中
**
1.问题: 1> 图片文件缓存的时间有多长
答案: 一周
2.SDWebImage的内存缓存是用什么实现的
答案: NSCache
3.SDWebImage的最大并发数是多少
答案:6
4.SBWebImage
支持动图嘛??
答案:GIF
5.SDWebImage是如何区别不同格式的图像
答案:根据图像数据第一个字节来判断
PNG: 压缩比没有JPG高,但是无损压缩,解压性能高,苹果推荐的图像格式
CIF 序列帧动画,特点.只支持256中颜色,是最流行的时候载1998-1999 有专利的
6
SDWebImage 缓存图片的名称是怎么确定的
md5 在终端输入md5 -s 输入你的图片地址,即可寻找
如果单纯使用 文件名保存, 重名几率高
- TCP和UDP的区别(考得最多。。快被考烂了我觉得- -\)
1、TCP是面向链接的,虽然说网络的不安全不稳定特性决定了多少次握手都不能保证连接的可靠性,但TCP的三次握手在最低限度上(实际上也很大程度上保证了)保证了连接的可靠性;
而UDP不是面向连接的,UDP传送数据前并不与对方建立连接,对接收到的数据也不发送确认信号,发送端不知道数据是否会正确接收,当然也不用重发,所以说UDP是无连接的、不可靠的一种数据传输协议。
2、也正由于1所说的特点,使得UDP的开销更小数据传输速率更高,因为不必进行收发数据的确认,所以UDP的实时性更好。
知道了TCP和UDP的区别,就不难理解为何采用TCP传输协议的MSN比采用UDP的QQ传输文件慢了,但并不能说QQ的通信是不安全的,
因为程序员可以手动对UDP的数据收发进行验证,比如发送方对每个数据包进行编号然后由接收方进行验证啊什么的,
即使是这样,UDP因为在底层协议的封装上没有采用类似TCP的“三次握手”而实现了TCP所无法达到的传输效率。
6. ****什么时候用长连接****,****短连接****?
长连接多用于操作频繁,点对点的通讯,而且连接数不能太多情况,。每个TCP连接都需要三步握手,这需要时间,如果每个操作都是先连接,再操作的话那么处理速度会降低很多,所以每个操作完后都不断开,次处理时直接发送数据包就OK了,不用建立TCP连接。例如:数据库的连接用长连接,如果用短连接频繁的通信会造成socket错误,而且频繁的socket 创建也是对资源的浪费。
而像WEB网站的http服务一般都用短链接,因为长连接对于服务端来说会耗费一定的资源,而像WEB网站这么频繁的成千上万甚至上亿客户端的连接用短连接会更省一些资源,如果用长连接,而且同时有成千上万的用户,如果每个用户都占用一个连接的话,那可想而知吧。所以并发量大,但每个用户无需频繁操作情况下需用短连好。
总之,长连接和短连接的选择要视情况而定。
- 在项目什么时候选择使用GCD,什么时候选择NSOperation?
项目中使用NSOperation的优点是NSOperation是对线程的高度抽象,在项目中使用它,会使项目的程序结构更好,子类化NSOperation的设计思路,是具有面向对象的优点(复用、封装),使得实现是多线程支持,而接口简单,建议在复杂项目中使用。
项目中使用GCD的优点是GCD本身非常简单、易用,对于不复杂的多线程操作,会节省代码量,而Block参数的使用,会是代码更为易读,建议在简单项目中使用。
**8. iOS ****的沙盒目录结构是怎样的****?****App
Bundle ****里面都有什么****?****
**
1.沙盒结构
·
Application:存放程序源文件,上架前经过数字签名,上架后不可修改
·
Documents:常用目录,iCloud备份目录,存放数据,这里不能存缓存文件,否则上架不被通过
·
Library :
Caches:存放体积大又不需要备份的数据,SDWebImage缓存路径就是这个
Preference:设置目录,iCloud会备份设置信息
tmp:存放临时文件,不会被备份,而且这个文件下的数据有可能随时被清除的可能
2.App Bundle 里面有什么
·
Info.plist:此文件包含了应用程序的配置信息.系统依赖此文件以获取应用程序的相关信息
·
可执行文件:此文件包含应用程序的入口和通过静态连接到应用程序target的代码
·
资源文件:图片,声音文件一类的
·
其他:可以嵌入定制的数据资源
9 . app开发完成后还需要做哪些工作?(加分题)
·
用户行为统计工具(友盟, Flurry, Google Analytics等)
·
Apple Store 销售分析工具(如 App annie)
·
App crash收集工具(例如Crashlytics , 腾讯的Bugly,友盟)
·
App测试发布工具(Test Flight)
·
App Push (APNS, 极光)
·
App Analytics 可以看作是AppStore 的后台, 能看到自己的App下载量, 流量从哪里来的, 并将App看作一个整体, 来统计整体的一些数据, 可以看作时黑盒行为, 不干预正常App
·
友盟统计时通过开发者基于其SDK在App中植入代码(比如在执行关键操作发送数据统计给服务器), 来统计, 分析得到用户使用App的行为
·
10.谈谈swift的使用
·
记得去年十月份的时间,我看了一个数据,就是各个语言的使用排名,当时OC 排第三,swift是第十六,到今年三月份,也就是前些天,我看了一下,OC 排第十五,swift是第十四。Swift替代oc肯定是个趋势,之前公司的项目,一些模块我都用swift进行了替换。具体说一下Swift与OC的主要区别,我觉得两者主要的区别就是语法区别,其他大抵相同
·
<1.在Swift中使用let定义常量,用var定义变量,常量一经赋值不允许修改,变量赋值后可以修改,Swift 能够根据右边的代码,推导出变量的准确类型;
·
<2.Swift对数据类型要求异常严格,不会做隐式转换;
·
<3.Swift中的一大特色就是Optional可选项,定义变量时,如果指定为可选项,表示该变量可以有一个指定类型的值,也可以是nil;
·
<4.还有一个区别就是Swift中构造函数可以重载,就是init的括号内写一堆参数,OC中替代方式是 initWithXXX…..
- 动画都是怎么用的?做过哪些demo?app里有用吗?如果要停止动画怎么做?
·
Core Animation中可以直接使用的类有基本动画、帧动画、组动画、以及转场动画。所有动画作用在CALayer上的,而非UIView,而且动画执行都是在后台操作的,不会阻塞主线程。使用分为四个步骤:创建动画对象,设置动画属性,把动画添加到某个CALayer对象上,停止动画时可以调用remove移除动画,也可用stop进行停止。
·
之前自己做过一个demo(在手机上演示),这些动画也是参考了别人的,然后自己做了一些优化。
- 谈一谈MVVM的使用,你觉得它有什么缺点?
·
MVVM 模式和MVC 模式一样,主要目的是分离视图(View)和模型(Model),但MVC存在的问题是,模型的代码很少,控制器的代码一不小心就越来越多,另外就是不好测试。在MVVM中,view和view
controller都不直接引用model,而是引用视图模型,这样的优点是,低耦合,view可以独立Model变化和修改;可重用性,一个视图逻辑放在一个viewmodel里,可以让很多view重用这段视图逻辑;还有就是便于独立开发以及代码测试。
·
缺点就是,毕竟多过了一道,数据传输过程中,业务逻辑会稍微复杂一点,bug就比较难定位;另外一个是,可能有一些人对这个设计模式并不熟悉,如果团队开发时还需要再学习,可能会影响开发效率。
12.加密你都是怎么用?
加密这一块,主要分两块,一个是登录时的密码加密、一个是文件加密。
登录密码用的是基于MD5的“hmac+时间戳”,生成一个32位的字符。这种加密是不可逆的,注册的时候,要把密码hmac一下发到服务器。后续登录时,1.将客户端的密码hmac一下,然后拼接一下时间字符串,再hmac一下发到服务器;2.服务器接收到这个密文后,将原先保存在服务的密码做同样的操作,最后对比一下,如果相同就登录成功。(时间不一致的情况,可以让服务器端加上前一分钟的时间再对比一下即可)
关于文件加密,可以用对称加密,客户端和服务器端放同样的钥匙,进行加密解密。由于非对称加密效率太低,一般不用与大文件加密。有的时候非对称加密和对称加密结合使用,例如:用非对称加密将对称加密的密钥加密后,发到客户端,然后再对文件进行对称加密。
对称加密、非对称加密 、MD5 区别:
md5
加密不可逆,一般用于密码的加密,通过钥匙串保存在沙盒里面;
对称和非对称是可逆的,用于文件加密;
对称加密:客户端和服务器都一把钥匙,一般用于文件和视频;
非对称加密:比较慢;
**13. lldb****(gdb)常用的调试命令?
**
P 打印数字
po 表达式 打印对象,会调用对象description方法。是print-object的简写
bt 打印调用堆栈,是thread backtrace的简写,加all可打印所有thread的堆栈。
**n next ****下一步
**
**c cuntinue ****继续
**
- 常见的Http状态码有哪些?
• 300是请求重定向, 这类状态码代表需要客户端采取进一步的操作才能完成请求
• 304如果网页自请求者上次请求后没有更新,则用304代码告诉搜索引擎机器人,可节省带宽和开销。加载上次缓存.
• 500及以上是服务器错误,如503表示服务器找不到、3840表示服务器返回无效JSON。
• 400及以上是请求链接错误或者找不到服务器,如常见的404。
• 200及以上是正确,如常见的是200表示请求正常。
• 100及以上是请求接受成功。
15 . AFN3.0和2.0的区别
在AFNetworking
3.0之前,底层是通过封装NSURLConnection来实现的。
在AFNetworking
3.0之后,也就是在iOS 9.0 之后,NSURLConnection被弃用,苹果推荐使用NSURLSession来管理网络请求,所以AFNetworking 3.0之后,底层是通过封装NSURLSession来实现的。
从AFNetworking 3.0中之后,下面三个方法被弃用了。
• AFURLConnectionOperation
• AFHTTPRequestOperation
• AFHTTPRequestOperationManager
依次被下面三个类代替了,同时请求方法也跟着改变了,所以AFNetworking 3.0以后发生了很大的变化。
• AFURLSessionManager
• AFHTTPSessionManager
• AFNetworkReachabilityManager
- instruments三大功能
• Time Profiler:分析代码的执行时间,找出导致程序变慢的原因。
• Allocations:监测内存使用/分配情况
迅速膨胀的内存可以很快让程序毙命,所以要多加防范。
• Leaks:找到引发内存泄漏的起点
17 . UIViewController的生命周期
• xib/storyboard:-initWithCoder:,而非xib/storyboard的是-initWithNibName:然后-init
• -loadView
• -viewDidLoad
• -viewWillAppear:
• -viewDidAppear:
• -viewWillDisappear:
• -viewDidDisappear:
- Pod的实现原理
• 1、第三方库会被编译成.a静态库供我们真正的工程使用。
• CocoaPods会将所有的第三方库以target的方式组成一个名为Pods的工程,该工程就放在刚才新生成的Pods目录下。整个第三方库工程会生成一个名称为libPods.a的静态库提供给我们自己的CocoaPodsTest工程使用。
• 对于资源文件,CocoaPods提供了一个名为Pods-resources.sh的bash脚本,该脚本在每次项目编译的时候都会执行,将第三方库的各种资源文件复制到目标目录中。
• 2、我们的工程和第三方库所在的工程会由一个新生成的workspace管理
• 为了方便我们直观的管理工程和第三方库,CocoaPodsTest工程和Pods工程会被以workspace的形式组织和管理,也就是我们刚才看到的CocoaPodsTest.xcworkspace文件。
• 3、原来的工程设置已经被更改了,这时候我们直接打开原来的工程文件去编译就会报错,只能使用新生成的workspace来进行项目管理。
• 4、CocoaPods通过一个名为Pods.xcconfig的文件来在编译时设置所有的依赖和参数。
•
19 .分类和扩展
• Category:在没有原类.m文件的基础上,给该类添加方法;类别可以在不获悉,不改变原来代码的情况下往里面添加新的方法,只能添加,不能删除修改。并且如果类别和原来类中的方法产生名称冲突,则类别将覆盖原来的方法,因为类别具有更高的优先级。
• Extension:一种特殊形式的类别,主要在一个类的.m文件里声明和实现延展的作用,就是给某类添加私有方法或是私有变量.
• 两个的区别:延展可以添加属性并且它添加的方法是必须要实现的。延展可以认为是一个私有的类目。而Category只能为对象添加方法.
•
20 . 响应者链条
• UIResponder类,窗口上的view及控制器都是派生于该类的,调用UIResponder类提供的方法或属性,可以捕捉到窗口上的所有响应事件,并处理,
• 响应者链条是由多个响应者对象连接起来的链条,其中响应者对象是能处理事件的对象,所有View和viewController都是响应者对象,利用响应者链条能让多个控制处理同一个触摸事件,如果当前View不能处理当前事件,那么事件将会沿着响应者链传递,直到遇到能处理该事件的响应者
• 1)接收事件的initial view如果不能处理该事件并且她不是顶层的View,则事件会往它的父View进行传递。
• 2).initial view的父View获取事件后如果仍不能处理,则继续往上传递,循环这个过程。如果顶层的View还是不能处理这个事件的话,则会将事件传递给它们的ViewController,
• 3).如果ViewController也不能处理,则传递给Window(UIWindow),此时Window不能处理的话就将事件传递UIApplication,最后如果连Application也不能处理,则废弃该事件
- 堆(stack)和栈(heap)区别
• 1.管理:栈由编译器管理,堆由程序员管理
• 2.大小:栈向低地址扩展,内存区域连续,栈顶地址和栈的容量是固定的;堆向高地址扩展,内存区域不连续,大小取决于虚拟内存,堆得可用空间更大
• 3.碎片:栈不会产生碎片,堆容易产生碎片
• 4.分配:堆动态分配,栈动态和静态分配.
• 动态分配:堆,手工释放,栈,编译器释放
• 静态分配:编译器释放
• 5.效率:栈有底层软硬件支持,效率比堆高
•
- 你在做iOS开发时如何选择Delegate, Notification, KVO设计模式?
•
delegate的优势:
•
1.非常严格的语法。所有将听到的事件必须是在delegate协议中有清晰的定义。
•
2.如果delegate中的一个方法没有实现那么就会出现编译警告/错误
•
3.在一个应用中的控制流程是可跟踪的并且是可识别的;
•
•
4.能够接收调用的协议方法的返回值。这意味着delegate能够提供反馈信息给controller
•
缺点:
•
1.需要定义很多代码:1.协议定义;2.controller的delegate属性;3.在delegate本身中实现delegate方法定义
•
2.在释放代理对象时,需要小心的将delegate改为nil。一旦设定失败,那么调用释放对象的方法将会出现内存crash
•
3.在一个controller中有多个delegate对象,并且delegate是遵守同一个协议,但还是很难告诉多个对象同一个事件,不过有可能。
•
•
•
notification 的 优势 :
•
1.不需要编写多少代码,实现比较简单
•
2.对于一个发出的通知,多个对象能够做出反应,即一对多的方式实现简单
•
3.controller能够传递context对象(dictionary),context对象携带了关于发送通知的自定义的信息
•
缺点 :
•
1.在编译期不会检查通知是否能够被观察者正确的处理;
•
2.在释放注册的对象时,需要在通知中心取消注册;
3.在调试的时候应用的工作以及控制过程难跟踪;
•
4.controller和观察者需要提前知道通知名称、UserInfo dictionary keys。如果这些没有在工作区间定义,那么会出现不同步的情况;
6.通知发出后,controller不能从观察者获得任何的反馈信息(相比较delegate)。
•
根据我开发iOS应用的经历,我发现有些过分的使用通知模式。我个人不是很喜欢使用通知中心。我发现用通知中心很难把握应用的执行流程。Userlnfo dictionaries的keys到处传递导致失去了同步,而且在公共空间需要定义太多的常量。对于一个工作于现有的项目的开发者来说,如果过分的使用通知中心,那么很难理解应用的流程。
•
我觉得使用命名规则好的协议和协议方法定义对于清晰的理解controllers间的通信是很容易的。努力的定义这些协议方法将增强代码的可读性,以及更好的跟踪你的app。代理协议发生改变以及实现都可通过编译器检查出来.
- 谈谈多线程安全问题的几种解决方案?何为线程同步,如何实现的?分线程回调主线程方法是什么,有什么作用?
•
(1)、多线程的作用:可以解决负载均衡问题,充分利用cpu资源 。为了提高CPU的使用率,采用多线程的方式去同时完 成几件事情而互不干扰,
•
(2)、大多情况下,要用到多线程的主要是需要处理大量的IO操作时或处理的情况需要花大量的时间等等,比如:读写文 件、视频图像的采集、处理、显示、保存等。 (3)、ios有三种主要方法:1、NSThread。2、NSOperation。3、GCD。 (4)解决方案:使用锁:锁是线程编程同步工具的基础。锁可以让你很容易保护代码中一大块区域以便你可以确保代码的正 确性。使用POSIX互斥锁@synchronized指令。
•
(5)回到主线程的方法:
dispatch_async(dispatch_get_main_queue(), ^{ });
•
作用:主线程是显示UI界面,子线程多数是进行数据处理
**24.****你和后端服务器是怎么进行交互的
**
•
在需求确定,定下了开发的周期后,就需要准备开发了。
•
iOS、安卓及后端各端主要负责人员在了解完需求后,开始分析本期需求需要哪些接口,是否需要新的接口,是否需要改动原有的接口等。在三端统一后,后端接口负责人确定哪天出接口文档及接口假数据。为什么要三端一起定接口呢?因为即使是后端接口负责人,也不一定对原有的业务和原有的接口全部都了解,任何一方的了解加起来才能确定是否可行。
如果App还没有开发过,首先开发一款新的App,那么iOS、安卓端的架构师,或者主要开发负责人,需要与后端接口负责人共同分析需求,然后初步写出第一版本接口文档,然后各方再各自好好看看、分析分析接口是否合理,参数是否合理,结构是否合理等。这数据的结构会决定着整个网络框架的搭建。
**25. runloop****和线程有什么关系?
**
**
**
,run loop和线程是紧密相连的,可以这样说run loop是为了线程而生,没有线程,它就没有存在的必要。Run loops是线程的基础架构部分, Cocoa 和CoreFundation 都提供了 run loop 对象方便配置和管理线程的run loop
1, 主线程的run loop默认是启动的。
iOS的应用程序里面,程序启动后会有一个如下的main()函数
int main(intargc, char* argv[]) {
@autoreleasepool
{
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
重点是UIApplicationMain()函数,这个方法会为main thread设置一个NSRunLoop对象,这就解释了:为什么我们的应用可以在无人操作的时候休息,需要让它干活的时候又能立马响应。
2, 对其它线程来说,run loop默认是没有启动的,如果你需要更多的线程交互则可以手动配置和启动,如果线程只是去执行一个长时间的已确定的任务则不需要。
- **你最近遇到过的一个技术挑战(难题)是什么?怎么解决的?
**
首先,你应该明白:人家感兴趣的不是哪个问题,而是你解决问题的方法,和你描述解决问题方法的方式。
如果你说,哦,没遇到什么有挑战的,一般上Stackoverflow, google上搜一下就解决了。
此乃必死答案。
如果你说,啊,在两年前。。。
什么?我不信一个优秀的一直在进步的程序员不会遇到任何挑战,那么说这两年来你都在固步自封了?
如果你说,啊,就在上个月,我在编写$#%!#$%语言,实现#$%!#$框架时发现#$!!##$接口出现#$%!问题,!#$!@%#%^...
万能“挑战问题”答案模
我(最近的一个时间)在做(怎样的一个产品/程序),这个产品/程序的目的是(帮助用户完成什么事),其中有一个(什么模块),为了实现(什么功能),用到了(什么技术),但是(遇到了什么挑战/难点/bug),我通过(怎样的手段)定位问题所在,问题出现的原因是(简要的点到技术点的描述),我在(至少两个资料来源)上找到了参考,最后基于(怎样的决策标准)决定采用(何种解决方法),运用了(哪种技术),最后成功解决了问题/实现了功能,结果是这个产品/程序(对用户,系统,性能,可用性,资源等产生了何种正面的影响)。下一步,我认为我应该研究(何种更先进的方式),进一步(怎样让产品/程序做得更好)。
参考答案:
最近公司项目中的用户账号出现被盗现象,原因是通信安全问题处理不好。因为公司的项目已经是好几年的老项目了,包括服务端的接口好多是老接口,原来是没有处理任何加密的,因此很容易被盗取账号。现在我们的技术VP要求针对这个问题,做一个版本。因为主动接受挑战,所以这个重任落在了我的身上,由我来牵头做好这个需求。
这真的是一个很有挑战性的技术项目。步骤如下:
•
需要调研市场上比较有名的App,他们是如何做好安全通信问题的;
•
写好技术文档,将调研结果反馈出来并写出自己的技术方案;
•
开初步技术方案评审会,会有VP及各组Leader参与,会上会提出各种问题,并给予一一解答,然后做会议记录,会后继续完善文档;
•
开跨部分评审会,只有所有都通过了,才能立项。
•
技术立项,然后写好各方向所需要做的工作文档
为什么要这么麻烦?因为我们既要兼容以前的所有版本,又要保证技术安全,那就不会自己就能说了算的,而且也不仅仅是客户端的问题。**
**
**你一般是如何调试Bug的?
Bug分为测试中的Bug和线上的Bug:
•
线上Bug:项目使用了友盟统计,因此会有崩溃日志,通过解析dYSM可以直接定位到大部分bug崩溃之处。解决线上bug需要从主干拉一个新的分支,解决bug并测试通过后,再合并到主干,然后上线。若是多团队开发,可以将fix bug分支与其他团队最近要上线的分支集成,然后集成测试再上线。
•
测试Bug:能根据描述直接定位bug出错之处,则好处理;若无法直观定位,则根据bug类型分几种处理方式,比如崩溃的bug可以通过instruments来检测、数据显示错误的bug,则需要阅读代码一步步查看逻辑哪里写错。
对于开发中出现的崩溃或者数据显示不正常,那就需要根据经验或者相关工具来检测可能出错之处。当然,团队内沟通解决是最好的。**
网友评论