1 copy可变变量:在赋值指针的同时也会复制指针指向的内存区域。深拷贝,例如NSMutableString对象。
2 copy不可变变量:等同于strong,还是浅拷贝,例如NSString对象。
因为block是一段代码,即不可变的,所以并不会深拷贝。
如果【block内部】使用了【外部声明的强引用】访问【对象A】,那么【block内部】会自动产生于一个【强引用】指向【对象A】
如果【block内部】使用了【外部声明的弱引用】访问【对象A】,那么【block内部】会自动产生于一个【弱引用】指向【对象A】
TCP和UDP的区别于联系:
TCP为传输控制层协议,为面向连接、可靠的、点到点的通信;
UDP为用户数据报协议,非连接的不可靠的点到多点的通信;
TCP侧重可靠传输,UDP侧重快速传输。
Scoket连接和HTTP连接的区别:
HTTP协议是基于TCP连接的,是应用层协议,主要解决如何包装数据。Socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过Socket,我们才能使用TCP/IP协议。
HTTP连接:短连接,客户端向服务器发送一次请求,服务器响应后连接断开,节省资源。服务器不能主动给客户端响应(除非采用HTTP长连接技术),iPhone主要使用类NSURLConnection。
Socket连接:长连接,客户端跟服务器端直接使用Socket进行连接,没有规定连接后断开,因此客户端和服务器段保持连接通道,双方可以主动发送数据,一般多用于游戏.Socket默认连接超时时间是30秒,默认大小是8K(理解为一个数据包大小)。
HTTP协议的特点,关于HTTP请求GET和POST的区别:HTTP超文本传输协议,是短连接,是客户端主动发送请求,服务器做出响应,服务器响应之后,链接断开。HTTP是一个属于应用层面向对象的协议,HTTP有两类报文:请求报文和响应报文。
GET请求:参数在地址后拼接,没有请求数据,不安全(因为所有参数都拼接在地址后面),不适合传输大量数据(长度有限制,为1024个字节)。
POST请求:参数在请求数据区放着,相对GET请求更安全,并且数据大小没有限制。把提交的数据放置在HTTP包的包体中.
POST的安全性要比GET的安全性高;
通过GET提交数据,用户名和密码将明文出现在URL上,比如登陆界面有可能被浏览器缓存。
HTTPS:安全超文本传输协议(Secure Hypertext Transfer Protocol),它是一个安全通信通道,基于HTTP开发,用于客户计算机和服务器之间交换信息,使用安全套结字层(SSI)进行信息交换,即HTTP的安全版
XML数据解析方式各有什么不同,JSON解析有哪些框架?
XML数据解析的两种解析方式:DOM解析和SAX解析;
DOM解析必须完成DOM树的构造,在处理规模较大的XML文档时就很耗内存,占用资源较多,读入整个XML文档并构建一个驻留内存的树结构(节点树),通过遍历树结构可以检索任意XML节点,读取它的属性和值,通常情况下,可以借助XPath查询XML节点;
SAX与DOM不同,它是事件驱动模型,解析XML文档时每遇到一个开始或者结束标签、属性或者一条指令时,程序就产生一个事件进行相应的处理,一边读取XML文档一边处理,不必等整个文档加载完才采取措施,当在读取解析过程中遇到需要处理的对象,会发出通知进行处理。因此,SAX相对于DOM来说更适合操作大的XML文档。
JSON解析:性能比较好的主要是第三方的JSONKIT和iOS自带的JSON解析类,其中自带的JSON解析性能最高,但只能用于iOS5之后。
如何制作一个静态库/动态库,他们的区别是什么?
Xcode6支持制作静态库/动态库 framework
无论是动态库还是静态库都是区分真机和模拟器的,需要lipo命令进行合并
静态库编译静态库文件装入程序空间,动态库是文件动态装入内存
动态库执行到相关函数才会被调用,节省空间
SDWebImage原理
从内存中(字典)找图片(当这个图片在本次程序加载过),找到直接使用;
从沙盒中找,找到直接使用,缓存到内存。
从网络上获取,使用,缓存到内存,缓存到沙盒。
strong / weak / unsafe_unretained 的区别?
weak只能修饰OC对象,使用weak不会使计数器加1,对象销毁时修饰的对象会指向nil
strong等价与retain,能使计数器加1,且不能用来修饰数据类型
unsafe_unretained等价与assign,可以用来修饰数据类型和OC对象,但是不会使计数器加1,且对象销毁时也不会将对象指向nil,容易造成野指针错误
什么时候会发生「隐式动画」?
当改变CALayer的一个可做动画的属性,它并不能立刻在屏幕上体现出来.相反,它是从先前的值平滑过渡到新的值。这一切都是默认的行为,你不需要做额外的操作,这就是隐式动画
Push Notification 是如何工作的?
推送通知分为两种,一个是本地推送,一个是远程推送
本地推送:不需要联网也可以推送,是开发人员在APP内设定特定的时间来提醒用户干什么
远程推送:需要联网,用户的设备会于苹果APNS服务器形成一个长连接,用户设备会发送uuid和Bundle idenidentifier给苹果服务器,苹果服务器会加密生成一个deviceToken给用户设备,然后设备会将deviceToken发送给APP的服务器,服务器会将deviceToken存进他们的数据库,这时候如果有人发送消息给我,服务器端就会去查询我的deviceToken,然后将deviceToken和要发送的信息发送给苹果服务器,苹果服务器通过deviceToken找到我的设备并将消息推送到我的设备上,这里还有个情况是如果APP在线,那么APP服务器会于APP产生一个长连接,这时候APPF服务器会直接通过deviceToken将消息推送到设备上
什么是 Runloop?
是一个与线程相关的机制,可以理解为一个循环,在这个循环里面等待事件然后处理事件.而这个循环是基于线程的,在Cocoa中每个线程都有它的runroop,通过他这样的机制,线程可以在没有事件要处理的时候休息,有事件运行,减轻CPU压力,这题可以衍生出为什么在滑动时会导致定时器失败
什么是 Protocol,Delegate 一般是怎么用的?
协议是一个方法签名的列表,在其中可以定义若干个方法,遵守该协议的类可以实现协议里的方法,在协议中使用@property只会生成setter和getter方法的声明
delegate用法:成为一个类的代理,可以去实现协议里的方法
为什么 UIScrollView 的滚动会导致 NSTimer 失效?
定时器里面有个runoop mode,一般定时器是运行在defaultmode上但是如果滑动了这个页面,主线程runloop会转到UITrackingRunLoopMode中,这时候就不能处理定时器了,造成定时器失效,原因就是runroop mode选错了,解决办法有2个,一个是更改mode为NSRunLoopCommonModes(无论runloop运行在哪个mode,都能运行),还有种办法是切换到主线程来更新UI界面的刷新
什么时候会发生 EXC BAD ACCESS 异常?
访问一个僵尸对象,访问僵尸对象的成员变量或者向其发消息
死循环
NSNotification 和 KVO 的使用场景?
KVO使用场景:当一个对象的特定属性改变的时候,需要被通知一个或者多个对象的时候
NSNotification使用场景:跨层级传递值,多个对象通知多个对象
使用 Block 时需要注意哪些问题?
在block内部使用外部指针且会造成循环引用情况下,需要用__weak修饰外部指针
__weak typeof(self) weakSelf = self;
在block内部如果调用了延时函数还使用弱指针会取不到该指针,因为已经被销毁了,需要在block内部再将弱指针重新强引用一下__strong typeof(self) strongSelf = weakSelf;
如果需要在block内部改变外部变量的话,需要在用__block修饰外部变量
有哪些常见的 Crash 场景?
访问了僵尸对象
访问了不存在的方法
数组越界
在定时器下一次回调前将定时器释放,会Crash
MVC:这个设计模型大部分应用应该都在用,介绍下MVC就好
2.单例:单例在项目中用的还是蛮多的,像登录界面,对一些第三方框架二次封装等等
3.KVC/KVO:这个用的应该也很多,KVC用来替换掉系统的tabbar,用KVO来监听偏移量来完成下拉刷新,改变导航条背景颜色这些
4.工厂方法:这个用的更多了,设置一些自定义View肯定要用到这个设计模式
谈谈iOS开发中Debug和Release的区别和使用
在 iOS开发中,我们经常会调试程序和发布程序,但是有很多人对 Debug 和 Release 不是太了解.下面是我对 Debug 和 Release 的简单理解,希望对大家在开发中有所启迪:
Debug : 调试版本,主要是让程序员使用,在调试的过程中调用 Debug 会启动更多的服务来监控错误,运行速度相对较慢,而且比较耗能.
Release : 发布版本,主要是让用户使用, 在使用的过程中会去掉那些繁琐的监控服务,运行速度相对较快,而且比较节约内存.
建议 : 在程序开发完成以后,建议在测试的时候 把 Debug 和 Release 两个版本都测试一下,在提测的时候以 Release 测试的情况为准. 因为 Release 状态下测试的情况,是用户使用的真是情景.
在程序调试的过程中, Xcode 默认的情况是 Debug ,如果想修改成 Release 情景下测试.
需要选择 Edit Scheme ---> info --->Build Configuration 选择 Release 进行测试;
应用内购买(In-App Purchases)是怎么回事?IAP能够为用户带来哪些新体验?
应用内购买可以让开发者通过苹果的Store Kit框架在应用中内嵌一个商店。
通过应用内购买,开发者可以开发一个基本的应用,并且在应用商店销售额外的功能和内容,例如:
杂志应用可以让用户购买和下载新的内容
游戏应用可以让用户购买新的关卡和内容
网游应用可以让用户购买游戏内的虚拟道具
带来哪些新的体验:个人感觉,首先,苹果提供了安全的交易平台。其次,让更多的付费应用转变为免费+应用内购买的模式,用户可以提前体验应用的功能,对增值的服务和内容采取应用内购买的模式,让用户和开发者达到双赢的目的。
具体的内容可以参考In-App Purchase Programming Guide
iOS应用开发流程:
注册APP ID
注册成为苹果开发者
开发
真机调试
打包和发布
等待审核
上线
Provisioning Profiles
Provisioning Profiles是一个配置文件,可以在https://developer.apple.com配置
在开发时,我们需要为应用配置Development Provisioning Profile,它将App ID, 开发者证书,以及测试Device绑定在一起。
在上架时,我们需要为应用配置Distribution Provisioning Profile, 他将App ID和开发者证书绑定在一起,在上传应用时需要指定这个文件。
const 意味着"只读",下面的声明都是什么意思?
const int a;
int const a;
const int *a;
int* const a;
intconst*const a ;
前两个的作用是一样,a是一个常整型数。
第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)。
第四个意思a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。
最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。
函数体内 static 变量的作用范围为该函数体,不同于 auto 变量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值;
在模块内的 static 全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;
在模块内的 static 函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明它的模块内;
在类中的 static 成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;
在类中的 static 成员函数属于整个类所拥有,这个函数不接收 this 指针,因而只能访问类的static 成员变量。
#include和#import 其效果相同,都是导入类中定义的行为(方法);
#import 不会引起交叉编译,确保头文件只会被导入一次;
@class 表明只定义了类的名称,而具体类的行为是未知的,一般用于.h 文件
@class比#import编译效率更高。此外@class和#import的主要区别在于解决引用死锁的问题。
@public:对象的实例变量的作用域在任意地方都可以被访问 ;
@protected:对象的实例变量作用域在本类和子类都可以被访问 ;
@private:实例变量的作用域只能在本类(自身)中访问 .
block和代理的区别
代理回调更面向过程,block更面向结果。
如果需要在执行的不同步骤时被通知,你就要使用代理。
如果只需要请求的消息或者失败的详情,应该使用block。
block更适合与状态无关的操作,比如被告知某些结果.
block之间是不会相互影响的。
但是代理更像一个生产流水线,每个回调方法是生产线上的一个处理步骤,一个回调的变动可能会引起另一个回调的变动。要是一个对象有超过一个的不同事件,应该使用代理。
监测循环引用工具:
FBRetainCycleDetector。
类别和类扩展的区别
ategory和extensions的不同在于后者可以添加属性。另外后者添加的方法是必须要实现的。
extensions可以认为是一个私有的Category。
KVC/KVO
KVC,即是指 [NSKeyValueCoding], 一个非正式的 Protocol,提供一种机制来间接访问对象的属性。KVO 就是基于 KVC 实现的关键技术之一。
一个对象拥有某些属性。比如说,一个 Person 对象有一个 name 和一个 address 属性。以 KVC 说法,Person 对象分别有一个 value 对应他的 name 和 address 的 key。
Key-Value Observing (KVO) 建立在 KVC 之上,它能够观察一个对象的 KVC key path 值的变化。
KVO支持实例变量,KVC一定是属性
OC中没有多继承,可以用委托代理Protocol来实现。
协议不是类,它是定义了一个其他对象可以实现的接口,Delegate:它本身是一个设计模式,它的意思是委托别人去做某事
Notification 和 KVO区别
两者都是观察者模式,不同的是,KVO是被观察者直接发送消息给观察者,是对象间的交互,而通知则是观察者和被观察者通过通知中心对象之间进行交互,即消息由被观察者发送到通知中心对象,再由中心对象发给观察者,两者之间并不进行直接的交互
NSNotification 通知中心
苹果提供的一种消息机制, 观察者只要向消息中心注册, 即可接受其他对象发送来的消息,消息发送者和消息接受者两者可以互相一无所知,完全解耦。NSNotification可以应用于任意时间和任何对象,观察者可以有多个, 这也正是他跟delegate的区别
多态:不同对象以自己的方式响应相同的消息的能力叫做多态。运行时机制使我们直到运行时才去决定一个对象的类别,以及调用该类别对象指定方法。
isMemberOfClass 和 isKindOfClass 联系与区别
联系:两者都能检测一个对象是否是某个类的成员
区别:isKindOfClass 不仅用来确定一个对象是否是一个类的成员,也可以用来确定一个对象是否派生自该类的类的成员 ,而isMemberOfClass 只能做到第一点。
举例:如 ClassA派 生 自NSObject 类 , ClassA *a = [ClassA alloc] init];,[a isKindOfClass:[NSObject class]] 可以检查出 a 是否是 NSObject派生类 的成员,但 isMemberOfClass 做不到。
。
栈与 堆
栈区(stack)由编译器自动分配释放 ,存放方法(函数)的参数值, 局部变量的值等,栈是向低地址扩展的数据结构,是一块连续的内存的区域。即栈顶的地址和栈的最大容量是系统预先规定好的。
堆区(heap)一般由程序员分配释放, 若程序员不释放,程序结束时由OS回收,向高地址扩展的数据结构,是不连续的内存区域,从而堆获得的空间比较灵活。
全局区(静态区)(static),全局变量和静态变量的存储是放在一块 的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后有系统释放。
深拷贝和浅拷贝
浅复制:两个实例的指针仍指向内存中的同一资源,只复制指针值而不是实际资源;
深复制:不仅复制指针值,还复制指向指针所指向的资源
不手动指定autoreleasepool
Autorelease对象出了作用域之后,会被添加到最近一次创建的自动释放池中,并会在当前的 runloop 迭代结束时释放。
有a、b、c、d 4个异步请求,如何判断a、b、c、d都完成执行?如果需要a、b、c、d顺序执行,该如何实现?
对于这四个异步请求,要判断都执行完成最简单的方式就是通过GCD的group来实现:
dispatch_queue_tqueue= dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
dispatch_group_tgroup = dispatch_group_create();
dispatch_group_async(group,queue, ^{/*任务a */});
dispatch_group_async(group,queue, ^{/*任务b */});dispatch_group_async(group,queue, ^{/*任务c */});
dispatch_group_async(group,queue, ^{/*任务d */});
dispatch_group_notify(group,dispatch_get_main_queue(), ^{// 在a、b、c、d异步执行完成后,会回调这里});
当然,我们还可以使用非常老套的方法来处理,通过四个变量来标识a、b、c、d四个任务是否完成,然后在runloop中让其等待,当完成时才退出runloop。但是这样做会让后面的代码得不到执行,直到Run loop执行完毕。
要求顺序执行,那么可以将任务放到串行队列中,自然就是按顺序来异步执行了。
dispatch_barrier_async的作用
在并行队列中,为了保持某些任务的顺序,需要等待一些任务完成后才能继续进行,使用 barrier 来等待之前任务完成,避免数据竞争等问题。
dispatch_barrier_async 函数会等待追加到Concurrent Dispatch Queue并行队列中的操作全部执行完之后,然后再执行 dispatch_barrier_async 函数追加的处理,等 dispatch_barrier_async 追加的处理执行结束之后,Concurrent Dispatch Queue才恢复之前的动作继续执行。
打个比方:比如你们公司周末跟团旅游,高速休息站上,司机说:大家都去上厕所,速战速决,上完厕所就上高速。超大的公共厕所,大家同时去,程序猿很快就结束了,但程序媛就可能会慢一些,即使你第一个回来,司机也不会出发,司机要等待所有人都回来后,才能出发。 dispatch_barrier_async 函数追加的内容就如同 “上完厕所就上高速”这个动作。
(注意:使用 dispatch_barrier_async ,该函数只能搭配自定义并行队列 dispatch_queue_t 使用。不能使用: dispatch_get_global_queue ,否则 dispatch_barrier_async 的作用会和 dispatch_async 的作用一模一样。 )
原文链接:http://www.jianshu.com/p/3409bc848428
应用的生命周期
启动程序
willFinishLaunchingWithOptions
didFinishLaunchingWithOptions
applicationDidBecomeActive
按下home键
applicationWillResignActive
applicationDidEnterBackground
双击home键,再打开程序
applicationWillEnterForeground
applicationDidBecomeActive
当程序将要退出是被调用,通常是用来保存数据
applicationWillTerminate
UIViewController的完整生命周期
-[ViewController initWithNibName:bundle:];
-[ViewController init];
-[ViewController loadView];
-[ViewController viewDidLoad];
-[ViewController viewWillDisappear:];
-[ViewController viewWillAppear:];
-[ViewController viewDidAppear:];
-[ViewController viewDidDisappear:];
Storyboard和标准NIB文件的差别
xib是一个基于xml的描述文件,可以实现可视化编程。一个工程中可以有多个xib文件,一个xib文件对应着一个视图控制器和多个视图。
storyboard是多个xib文件集合的描述文件,也采用xml格式,也可以实现可视化编程,而且在多个视图控制器的情况下,storyboard可以描述个视图控制器之间的导航关系。