题目来源:http://mrpeak.cn/blog/ios_interview2/
问题及答案
1.NSString 如何计算字符的个数?
NSString是UTF-16编码的, 也就是16位的unichar字符的序列. 所以, 一般遍历其每一个字符的方法就是:
for(int i=0; i<str.length; i++){ unichar ch = [str characterAtIndex: i]; }
对于“👍🏼”这种Emoji,是用2个16位unichar来表示,它的Unicode是U+1F44D, 用(U+D83D U+DC4D)两个字符来表示。
幸好,NSString的rangeOfComposedCharacterSequencesForRange:和rangeOfComposedCharacterSequenceAtIndex:两个方法可以用来处理这种情况.
NSRange range; for(int i=0; i<str.length; i+=range.length){ range = [str rangeOfComposedCharacterSequenceAtIndex:i]; NSString *s = [str attributedSubstringFromRange:range]; }
一次遍历一个子串, 而不是遍历一个unichar了.
URL:http://blog.csdn.net/zhouleizhao/article/details/52816744
2.PKI体系中加密和签名的区别?
加密证书和签名证书都可以用来作非对称加解密。
签名密钥对用于数据的完整性检测,保证防伪造与防抵赖,签名私钥的遗失,并不会影响对以前签名数据的验证,因此,签名私钥无须备份,因此,签名密钥不需要也不应该需要第三方来管理。
而加密密钥对用于数据的加密保护若加密私钥遗失,将导致以前的加密数据无法解密,这在实际应用中是无法接受的,加密私钥应该由可信的第三方(即通常所说的CA)来备份。
URL:http://blog.sina.com.cn/s/blog_49453d720100xran.html
3.如何自己高效实现NSUserdefault?
从使用和原理两方面讲起,使用方面,首先进行调用封装和key键管理,封装是为了使用效率,key键管理是为了方便修改和管理。
从原理方面讲,NSUserdefault 支持的数据类型有NSString、 NSNumber、NSDate、 NSArray、NSDictionary、BOOL、NSInteger、NSFloat等系统定义的数据类型。如果要进行频繁的大数据存储建议使用归档和数据库等底层更优化的方式存储。
4.解析TCP慢启动特性?
TCP在连接过程的三次握手完成后,开始传数据,并不是一开始向网络通道中发送大量的数据包,这样很容易导致网络中路由器缓存空间耗尽,从而发生拥塞。
TCP使用了一个叫慢启动门限(ssthresh)的变量,一旦cwnd>=ssthresh(大多数TCP的实现,通常大小都是65536),慢启动过程结束,拥塞避免阶段开始;
拥塞避免:cwnd的值不再指数级往上升,开始加法增加。此时当窗口中所有的报文段都被确认时,cwnd的大小加1,cwnd的值就随着RTT开始线性增加,这样就可以避免增长过快导致网络拥塞,慢慢的增加调整到网络的最佳值。
URL:https://www.cnblogs.com/edisongz/p/6986527.html
5.如何用HTTP实现长连接?
轮询:隔一段时间访问服务器,服务器不管有没有新消息都立刻返回。 设置HTTP长连接,有过期时间:
在首部字段中设置Connection:keep-alive 和Keep-Alive: timeout=60,表明连接建立之后,空闲时间超过60秒之后,就会失效。如果在空闲第58秒时,再次使用此连接,则连接仍然有效,使用完之后,重新计数,空闲60秒之后过期。
设置HTTP长连接,无过期时间: 在首部字段中只设置Connection:keep-alive,表明连接永久有效。 URL:https://www.cnblogs.com/shoren/p/http-connection.html
6.HTTP 2.0针对同一个域名的多个请求,会建立多少TCP链接?
HTTP 2.0 通信都在一个连接上完成,这个连接可以承载任意数量的双向数据流。相应地,每个数据流以消息的形式发送,而消息由一或多个帧组成,这些帧可以乱序发送,然后再根据每个帧首部的流标识符重新组装。
7.数据库建表的时候索引有什么用?
创建索引可以大大提高系统的性能。 第一,通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。
第二,可以大大加快数据的检索速度,这也是创建索引的最主要的原因。
第三,可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。
第四,在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。
第五,通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。
URL:http://blog.163.com/happy_2010_zyj/blog/static/1511487562010511115227777/
8.Full Text Search为什么快?
全文索引(Full Text Search)用于模糊查询比一般的方法比如like用于模糊查询速度要快的原因是前者是用空间来换时间,在建立全文索引时主要通过分词器(lexer),将被索引的表上的那一列的所有值(即文本,要varchar等类型)分割成一个个token_text(比如,英文分词器BASIC_LEXER以空格,标点符号,_,-,等非字母数字的符号作为分割标记),而且记录这些token_text来自表里的哪些行等信息,最后将这些token_text和这些信息都写到表DRI中。
有了这张表,全文索引才可以快速地查找(无论是模糊还是不模糊查找),但是该表要占据空间的。 URL:http://blog.csdn.net/caomiao2006/article/details/52075917
9.iOS下如何实现指定线程数目的线程池?
控制线程池中的线程数,来设置线程池中的线程数,也就是并发操作数。默认情况下是-1,也就是没有限制,同时运行队列中的全部操作。
[queue setMaxConcurrentOperationCount:2];
创建线程池: 创建线程池有两种方式,第一种是OC得方式,第二种是C语言的方式。 OC版:
OC创建线程池的关键字是:NSOperationQueue OC线程池的单元是NSInvocationOperation对象,
- (void)creatThreadQueue_OC{ NSInvocationOperation *task_1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(taskClick_1) object:nil]; NSInvocationOperation *task_2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(taskClick_2) object:nil]; [OC_Queue addOperation:task_1]; [[NSOperationQueue mainQueue] addOperation:task_2]; }
C语言创建一个线程池,C语言线程的单元式“代码块”--Block
- (void)creatThreadQueue_C{ //serial work dispatch_sync(C_Queue, ^{ [self work_1]; }); dispatch_sync(dispatch_get_main_queue(), ^{ [self work_2]; }); }
URL:http://blog.csdn.net/u012360598/article/details/41925047
10.介绍下iOS设备获取唯一设备号的历史变迁。
从IOS5.0(2011年8月份)开始,苹果宣布将不再支持用uniqueIdentifier方法获取设备的UDID,iOS5以下是可以用的。在2013年3月21日苹果已经通知开发者:从2013年5月1日起,访问UIDIDs的程序将不再被审核通过,替代的方案是开发者应该使用“在iOS 6中介绍的Vendor或Advertising标示符”。
Vindor标示符,也是在iOS 6中新增的,跟advertisingIdentifier一样,该方法返回的是一个 NSUUID对象,可以获得一个UUID。
iOS 6中另外一个新的方法,提供了一个方法advertisingIdentifier,通过调用该方法会返回一个NSUUID实例,最后可以获得一个UUID,由系统存储着的。 URL:http://blog.csdn.net/lcg910978041/article/details/51612953
11.函数式编程当中的 first-class function 是什么意思呢?
First Class。该类型的值可以作为函数的参数和返回值,也可以赋给变量。
结构化程序设计的精髓在于模块复用和访存控制。如果说函数实现了代码复用,那么在支持First Class Function的语言中,高阶函数作为函数之间的胶水,进一步方便了函数的复用。
URL:https://www.zhihu.com/question/27460623
12.如何使用runtime hook一个class的某个方法,又如何hook某个instance的方法?
借助Runtime的Method Swizzling(方法替换)以及Associated Object(关联对象)对相关类进行扩展。
static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ SEL selA = @selector(sendAction:to:forEvent:); SEL selB = @selector(mySendAction:to:forEvent:); Method methodA = class_getInstanceMethod(self,selA); Method methodB = class_getInstanceMethod(self, selB); BOOL isAdd = class_addMethod(self, selA, method_getImplementation(methodB), method_getTypeEncoding(methodB)); if (isAdd) { class_replaceMethod(self, selB, method_getImplementation(methodA), method_getTypeEncoding(methodA)); }else{ method_exchangeImplementations(methodA, methodB); } });
URL:http://blog.csdn.net/lyl123_456/article/details/52462621