2019年IOS面试题总结(一)
文章目录
- 2019年IOS面试题总结(一)
-
- 1. ios内存管理机制
- 2. NSThread、GCD、NSOperation多线程
- 3.输入一个字符串,判断这个字符串是否是有效的IP地址
- 4.大数加法怎么实现?
- 5.简述KVC和KVO,其中KVO实现原理?
- 6.Block实现原理;堆上和栈上的数据如何同步?
- 7.iOS设计模式
- 8.多线程有哪些?如何保证多线程中读写分离,加锁方案?
- 9.如何删除单链表中一个元素?
- 10.NSNotificationCenter通知中心的实现原理?
- 11.推送如何实现的?
- 12.SEL的使用和原理?
- 13.点击事件如何穿透透明的View?
- 14.RunLoop的实现原理?(答案待完善)
- 15.简述Runtime,发送消息的过程;
- 16.简述weak的实现原理;
- 17.写一个单例;
- 18.如何从字符串中得到一个整数?
- 19.数组去重方式;
- 20.设计一个数据库;(答案待完善)
- 21.实现多个网络请求ABC执行完再执行D
- 22.列表页性能优化
- 23.HTTPS(答案待完善)
- 23.音视频相关
1. ios内存管理机制
iOS内存管理机制的原理是引用计数,当这块内存被创建后,它的引用计数0->1,表示有一个对象或指针持有这块内存,拥有这块内存的所有权,如果这时候有另外一个对象或指针指向这块内存,那么为了表示这个后来的对象或指针对这块内存的所有权,引用计数1->2,之后若有一个对象或指针不再指向这块内存时,引用计数-1,表示这个对象或指针不再拥有这块内存的所有权,当一块内存的引用计数变为0,表示没有任何对象或指针持有这块内存,系统便会立刻释放掉这块内存。
- alloc、new :类初始化方法,开辟新的内存空间,引用计数+1;
- retain :实例方法,不会开辟新的内存空间,引用计数+1;
- copy : 实例方法,把一个对象复制到新的内存空间,新的内存空间引用计数+1,旧的不会;其中分为浅拷贝和深拷贝,浅拷贝只是拷贝地址,不会开辟新的内存空间;深拷贝是拷贝内容,会开辟新的内存空间;
- strong :强引用; 引用计数+1;
- release :实例方法,释放对象;引用计数-1;
- autorelease : 延迟释放;autoreleasepool自动释放池;当执行完之后引用计数-1;
- 还有是initWithFormat和stringWithFormat 字符串长度大于9时,引用计数+1;
- assign : 弱引用 ;weak也是弱引用,两者区别:assign不但能作用于对象还能作用于基本数据类型,但是所指向的对象销毁时不会将当前指向对象的指针指向nil,有野指针的生成;weak只能作用于对象,不能作用于基本数据类型,所指向的对象销毁时会将当前指向对象的指针指向nil,防止野指针的生成。
2. NSThread、GCD、NSOperation多线程
- 1、NSThread
NSThread是封装程度最小最轻量级的,使用更灵活,但要手动管理线程的生命周期、线程同步和线程加锁等,开销较大;
[NSThread isMultiThreaded];//BOOL 是否开启了多线程
[NSThread currentThread];//NSThread 获取当前线程
[NSThread mainThread];//NSThread 获取主线程
[NSThread sleepForTimeInterval:1];//线程睡眠1s
- 2、GCD
GCD基于C语言封装的,遵循FIFO
dispatch_sync与dispatch_async//同步和异步操作
dispatch_queue_t;//主要有串行和并发两种;
其中:
dispatch_queue_create("concurrent_queue", DISPATCH_QUEUE_CONCURRENT)并发;
dispatch_queue_create("serial_queue", DISPATCH_QUEUE_SERIAL)串行;
dispatch_once_t;//代码只会被执行一次,用于单例
dispatch_after;//延迟操作
dispatch_get_main_queue;//回到主线程操作
//Demo单例
+ (instancetype)sharedInstance {
static ZZScreenshotsMonitor *instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
});
return instance;
}
//Demo:执行顺序
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"1");
});
NSLog(@"2");
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,0);
dispatch_sync(queue, ^{
NSLog(@"3");
});
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"4");
});
dispatch_async(queue, ^{
NSLog(@"5");
});
NSLog(@"6");
[self performSelector:@selector(delayMethod) withObject:nil afterDelay:0];
NSLog(@"8");
}
- (void)delayMethod {
NSLog(@"7");
}
打印结果:23658147;其中5和8随机调换
- NSOperation
NSOperation基于GCD封装的,比GCD可控性更强;可以加入操作依赖(addDependency)、设置操作队列最大可并发执行的操作个数(setMaxConcurrentOperationCount)、取消操作(cancel)等,需要使用两个它的实体子类:NSBlockOperation和NSInvocationOperation,或者继承NSOperation自定义子类;NSBlockOperation和NSInvocationOperation用法的主要区别是:前者执行指定的方法,后者执行代码块,相对来说后者更加灵活易用。NSOperation操作配置完成后便可调用start函数在当前线程执行,如果要异步执行避免阻塞当前线程则可以加入NSOperationQueue中异步执行
3.输入一个字符串,判断这个字符串是否是有效的IP地址
+ (BOOL)isValidIP:(NSString *)ipStr {
if (nil == ipStr) {
return NO;
}
NSArray *ipArray = [ipStr componentsSeparatedByString:@"."];
if (ipArray.count == 4) {
for (NSString *ipnumberStr in ipArray) {
if ([self isPureInt:ipnumberStr]) {
int ipnumber = [ipnumberStr intValue];
if (!(ipnumber>=0 && ipnumber<=255)) {
return NO;
}
}
}
return YES;
}
return NO;
}
//是否整形
- (BOOL)isPureInt:(NSString*)string {
NSScanner* scan = [NSScanner scannerWithString:string];
int val;
return[scan scanInt:&val] && [scan isAtEnd];
}
//是否只含有数字
- (BOOL)validateNumber:(NSString*)number {
BOOL res = YES;
NSCharacterSet* tmpSet = [NSCharacterSet characterSetWithCharactersInString:@"0123456789"];
int i = 0;
while (i < number.length) {
NSString * string = [number substringWithRange:NSMakeRange(i, 1)];
NSRange range = [string rangeOfCharacterFromSet:tmpSet];
if (range.length == 0) {
res = NO;
break;
}
i++;
}
return res;
}
4.大数加法怎么实现?
使用字符串实现;
/两个大数相加算法
-(NSString *)addTwoNumberWithOneNumStr:(NSString *)one anotherNumStr:(NSString *)another
{
int i = 0;
int j = 0;
int maxLength = 0;
int sum = 0;
int overflow = 0;
int carryBit = 0;
NSString *temp1 = @"";
NSString *temp2 = @"";
NSString *sums = @"";
NSString *tempSum = @"";
int length1 = (int)one.length;
int length2 = (int)another.length;
//1.反转字符串
for (i = length1 - 1; i >= 0 ; i--) {
NSRange range = NSMakeRange(i, 1);
temp1 = [temp1 stringByAppendingString:[one substringWithRange:range]];
NSLog(@"%@",temp1);
}
for (j = length2 - 1; j >= 0; j--) {
NSRange range = NSMakeRange(j, 1);
temp2 = [temp2 stringByAppendingString:[another substringWithRange:range]];
NSLog(@"%@",temp2);
}
//2.补全缺少位数为0
maxLength = length1 > length2 ? length1 : length2;
if (maxLength == length1) {
for (i = length2; i < length1; i++) {
temp2 = [temp2 stringB