简述类目category优点和缺点
优点:
不需要通过增加子类而增加现有类的行为(方法),且类目中的方法与原始类方法基本没有区别;
通过类目可以将庞大一个类的方法进行划分,从而便于代码的日后的维护、更新以及提高代码的阅读性;
缺点:
无法向类目添加实例变量,如果需要添加实例变量,只能通过定义子类的方式;
类目中的方法与原始类以及父类方法相比具有更高优先级,如果覆盖父类的方法,可能导致super消息的断裂。因此,最好不要覆盖原始类中的方法。
键值编码KVC
键值编码是一种间接访问对象的属性使用字符串来标识属性,而不是通过调用存取方法,直接或通过实例变量访问的机制,非对象类型的变量将被自动封装或者解封成对象,很多情况下会简化程序代码;
KVC的缺点:一旦使用 KVC 你的编译器无法检查出错误,即不会对设置的键、键路径进行错误检查,且执行效率要低于合成存取器方法和自定的 setter 和 getter 方法。因为使用 KVC 键值编码,它必须先解析字符串,然后在设置或者访问对象的实例变量。
键值观察KVO
键值观察机制是一种能使得对象获取到其他对象属性变化的通知 ,极大的简化了代码。
实现 KVO 键值观察模式,被观察的对象必须使用 KVC 键值编码来修 改它的实例变量,这样才能被观察者观察到。因此,KVC是KVO的基础。
KVC机制通过key找到value的原理
当通过KVC调用对象时,比如:[self valueForKey:@”someKey”]时,程序会自动试图通过下面几种不同的方式解析这个调用。
首先查找对象是否带有 someKey 这个方法,如果没找到,会继续查找对象是否带有someKey这个实例变量(iVar),如果还没有找到,程序会继续试图调用 -(id) valueForUndefinedKey:这个方法。如果这个方法还是没有被实现的话,程序会抛出一个NSUndefinedKeyException异常错误。
补充:KVC查找方法的时候,不仅仅会查找someKey这个方法,还会查找getsomeKey这个方法,前面加一个get,或者_someKey以_getsomeKey这几种形式。同时,查找实例变量的时候也会不仅仅查找someKey这个变量,也会查找_someKey这个变量是否存在。
设计valueForUndefinedKey:方法的主要目的是当你使用-(id)valueForKey方法从对象中请求值时,对象能够在错误发生前,有最后的机会响应这个请求。
#include与#import的区别、#import 与@class 的区别
include 和import其效果相同,都是查询类中定义的行为(方法);
import不会引起交叉编译,确保头文件只会被导入一次;
@class 的表明,只定 义了类的名称,而具体类的行为是未知的,一般用于.h 文件;
@class 比#import 编译效率更高。
此外@class 和#import 的主要区别在于解决引用死锁的问题。
UITableViewCell上有个UILabel,显示NSTimer实现的秒表时间,手指滚动cell过程中,label是否刷新,为什么?
这是否刷新取决于timer加入到Run Loop中的Mode是什么。Mode主要是用来指定事件在运行循环中的优先级的,分为:
NSDefaultRunLoopMode(kCFRunLoopDefaultMode):默认,空闲状态
UITrackingRunLoopMode:ScrollView滑动时会切换到该Mode
UIInitializationRunLoopMode:run loop启动时,会切换到该mode
NSRunLoopCommonModes(kCFRunLoopCommonModes):Mode集合
苹果公开提供的Mode有两个:NSDefaultRunLoopMode(kCFRunLoopDefaultMode)
NSRunLoopCommonModes(kCFRunLoopCommonModes)
在编程中:如果我们把一个NSTimer对象以NSDefaultRunLoopMode(kCFRunLoopDefaultMode)添加到主运行循环中的时候, ScrollView滚动过程中会因为mode的切换,而导致NSTimer将不再被调度。当我们滚动的时候,也希望不调度,那就应该使用默认模式。但是,如果希望在滚动时,定时器也要回调,那就应该使用common mode。
对于单元格重用的理解
- 当屏幕上滑出屏幕时,系统会把这个单元格添加到重用队列中,等待被重用,当有新单元从屏幕外滑入屏幕内时,从重用队列中找看有没有可以重用的单元格,若有,就直接用,没有就重新创建一个。
线程与进程的区别和联系?
- 一个程序至少要有进城,一个进程至少要有一个线程.
- 进程:资源分配的最小独立单元,进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.
- 线程:进程下的一个分支,是进程的实体,是CPU调度和分派的基本单元,它是比进程更小的能独立运行的基本单位,线程自己基本不拥有系统资源,只拥有一点在运行中必不可少的资源(程序计数器、一组寄存器、栈),但是它可与同属一个进程的其他线程共享进程所拥有的全部资源。
- 进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。
- 进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。
但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。
TCP和UDP的区别于联系
- TCP为传输控制层协议,为面向连接、可靠的、点到点的通信;
- UDP为用户数据报协议,非连接的不可靠的点到多点的通信;
- TCP侧重可靠传输,UDP侧重快速传输。
TCP连接的三次握手
- 第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
- 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包,即SYN+ACK包,此时服务器进入SYN+RECV状态;
- 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次状态。
Scoket连接和HTTP连接的区别:
- HTTP协议是基于TCP连接的,是应用层协议,主要解决如何包装数据。
- Socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过Socket,我们才能使用TCP/IP协议。
- HTTP连接:短连接,客户端向服务器发送一次请求,服务器响应后连接断开,节省资源。服务器不能主动给客户端响应(除非采用HTTP长连接技术),iPhone主要使用类NSURLConnection。
- Socket连接:长连接,客户端跟服务器端直接使用Socket进行连接,没有规定连接后断开,因此客户端和服务器段保持连接通道,双方可以主动发送数据,一般多用于游戏.Socket默认连接超时时间是30秒,默认大小是8K(理解为一个数据包大小)。
如何进行真机调试
- 1.首先需要用钥匙串创建一个钥匙(key);
- 2.将钥匙串上传到官网,获取iOS Development证书;
- 3.创建App ID即我们应用程序中的Boundle ID;
- 4.添加Device ID即UDID;
- 5.通过勾选前面所创建的证书:App ID、Device ID;
- 6.生成mobileprovision文件;
- 7.先决条件:申请开发者账号 99美刀
APP发布的上架流程
- 1.登录应用发布网站添加应用信息;
- 2.下载安装发布证书;
- 3.选择发布证书,使用Archive编译发布包,用Xcode将代码(发布包)上传到服务器;
- 4.等待审核通过;
- 5.生成IPA:菜单栏->Product->Archive.
网络推送通知原理
首先应用发送通知,系统弹出提示框询问用户是否允许,当用户允许后向苹果服务器(APNS)请求deviceToken,并由苹果服务器发送给自己的应用,自己的应用将DeviceToken发送自己的服务器,自己服务器想要发送网络推送时将deviceToken以及想要推送的信息发送给苹果服务器,苹果服务器将信息发送给应用。
网络七层协议
- 应用层:1.用户接口、应用程序;2.Application典型设备:网关;3.典型协议、标准和应用:TELNET、FTP、HTTP
- 表示层:1.数据表示、压缩和加密presentation2.典型设备:网关3.典型协议、标准和应用:ASCLL、PICT、TIFF、JPEG|MPEG4.表示层相当于一个东西的表示,表示的一些协议,比如图片、声音和视频MPEG。
- 会话层:1.会话的建立和结束;2.典型设备:网关;3.典型协议、标准和应用:RPC、SQL、NFS、X WINDOWS、ASP
- 传输层:1.主要功能:端到端控制Transport;2.典型设备:网关;3.典型协议、标准和应用:TCP、UDP、SPX
- 网络层:1.主要功能:路由、寻址Network;2.典型设备:路由器;3.典型协议、标准和应用:IP、IPX、APPLETALK、ICMP;
- 数据链路层:1.主要功能:保证无差错的疏忽链路的data link;2.典型设备:交换机、网桥、网卡;3.典型协议、标准和应用:802.2、802.3ATM、HDLC、FRAME RELAY;
- 物理层:1.主要功能:传输比特流Physical;2.典型设备:集线器、中继器3.典型协议、标准和应用:V.35、EIA/TIA-232.
对NSUserDefaults的理解
- NSUserDefaults:系统提供的一种存储数据的方式,主要用于保存少量的数据,默认存储到library下的Preferences文件夹。
SDWebImage原理
调用类别的方法:
- 从内存中(字典)找图片(当这个图片在本次程序加载过),找到直接使用;
- 从沙盒中找,找到直接使用,缓存到内存。
- 从网络上获取,使用,缓存到内存,缓存到沙盒。
对于Run Loop的理解
- RunLoop,是多线程的法宝,即一个线程一次只能执行一个任务,执行完任务后就会退出线程。主线程执行完即时任务时会继续等待接收事件而不退出。非主线程通常来说就是为了执行某一任务的,执行完毕就需要归还资源,因此默认是不运行RunLoop的;
- 每一个线程都有其对应的RunLoop,只是默认只有主线程的RunLoop是启动的,其它子线程的RunLoop默认是不启动的,若要启动则需要手动启动;
在一个单独的线程中,如果需要在处理完某个任务后不退出,继续等待接收事件,则需要启用RunLoop; - NSRunLoop提供了一个添加NSTimer的方法,可以指定Mode,如果要让任何情况下都回调,则需要设置Mode为Common模式;
- 实质上,对于子线程的runloop默认是不存在的,因为苹果采用了懒加载的方式。如果我们没有手动调用[NSRunLoop currentRunLoop]的话,就不会去查询是否存在当前线程的RunLoop,也就不会去加载,更不会创建。
SQLite中常用的SQL语句
- 创建表:creat table 表名 (字段名 字段数据类型 是否为主键, 字段名 字段数据类型, 字段名 字段数据类型...);
-
增: insert into 表名 (字段1, 字段2...) values (值1, 值2...);
insert into Strdents (姓名,性别,出生日期) values ('开心朋朋','男','1980/6/15') -
删: delete from 表名 where 字段 = 值;
delete from a where name='开心朋朋'(删除表a中列值为开心朋朋的行) -
改:update <表名> set <列名=更新值> [where <更新条件>]
update tongxunlu set 年龄=18 where 姓名='蓝色小名' - **查 **:select <列名> from <表名> [where <查询条件表达试>] [order by <排序的列名>[asc或desc]]
select * from a
内存的使用和优化的注意事项
重用问题:如UITableViewCells、UICollectionViewCells、UITableViewHeaderFooterViews设置正确的reuseIdentifier,充分重用;
尽量把views设置为不透明:当opque为NO的时候,图层的半透明取决于图片和其本身合成的图层为结果,可提高性能;
不要使用太复杂的XIB/Storyboard:载入时就会将XIB/storyboard需要的所有资源,包括图片全部载入内存,即使未来很久才会使用。那些相比纯代码写的延迟加载,性能及内存就差了很多;
选择正确的数据结构:学会选择对业务场景最合适的数组结构是写出高效代码的基础。比如,数组: 有序的一组值。使用索引来查询很快,使用值查询很慢,插入/删除很慢。字典: 存储键值对,用键来查找比较快。集合: 无序的一组值,用值来查找很快,插入/删除很快。gzip/zip压缩:当从服务端下载相关附件时,可以通过gzip/zip压缩后再下载,使得内存更小,下载速度也更快。
延迟加载:对于不应该使用的数据,使用延迟加载方式。对于不需要马上显示的视图,使用延迟加载方式。比如,网络请求失败时显示的提示界面,可能一直都不会使用到,因此应该使用延迟加载。
数据缓存:对于cell的行高要缓存起来,使得reload数据时,效率也极高。而对于那些网络数据,不需要每次都请求的,应该缓存起来,可以写入数据库,也可以通过plist文件存储。
处理内存警告:一般在基类统一处理内存警告,将相关不用资源立即释放掉重用大开销对象:一些objects的初始化很慢,比如NSDateFormatter
和NSCalendar
,但又不可避免地需要使用它们。通常是作为属性存储起来,防止反复创建。
避免反复处理数据:许多应用需要从服务器加载功能所需的常为JSON或者XML格式的数据。在服务器端和客户端使用相同的数据结构很重要;
使用Autorelease Pool:在某些循环创建临时变量处理数据时,自动释放池以保证能及时释放内存;
正确选择图片加载方式:详情阅读细读UIImage加载方式
堆和栈的区别
管理方式:
对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生memory leak。
申请大小:
栈:栈顶的地址和栈的最大容量是系统预先规定好的,如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。
堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。
碎片问题:
对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出