-
Notifications
You must be signed in to change notification settings - Fork 23
请你出一套iOS面试题 #30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
@property(nonatomic, copy) NSString *name;
- (void)testMethod{
__weak __typeof(self)weakSelf = self;
self.name = @"testName";
self.block = ^(UIViewController *vc) {
NSLog(@"weakSelf.name = %@", weakSelf.name);
NSLog(@"self.name = %@", self.name);
};
}
// NextVC.m
/* log:
weakSelf.name = testName
-[NextVC dealloc]
*/
- (void)testMethod{
__weak __typeof(self)weakSelf = self;
self.name = @"testName";
self.block = ^(UIViewController *vc) {
// 延时操作,然后pop,vcu出栈,被释放
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// pop回去后nextVC已经被释放,所以打印是空值
// NSLog(@"weakSelf.name = %@", weakSelf.name);
// vc被block存储,拷贝到堆上,所以可以获取打印的值
NextVC *nextVC = (NextVC *)vc;
NSLog(@"weakSelf.name = %@", nextVC.name);
});
// 强引用,导致循环链
// NSLog(@"self.name = %@", self.name);
// 使用弱引用,避免循环链
// NSLog(@"weakSelf.name = %@", weakSelf.name);
};
self.block(self);
}
|
职业对于初、中级的一般我建议根据情况,了解下面试者对自己的职业规划,可以谈谈技术外的,不限于技术。例如: 你对自己的职业是怎么规划的? 你觉得理想的团队应该如何? |
Swift语法比如,为了寻找所有 100 以内的偶平方数,我们可以对 0..<10 进行 map 来得到所有平方数,然后再过滤掉所有奇数: (1..<10).map { $0 * $0 }.filter { $0 % 2 == 0 } // [4, 16, 36, 64] 通过组合使用 map 和 filter,我们现在可以轻易完成很多数组操作,而不需要引入中间变量。 这会使得最终的代码变得更短更易读。 |
iOS面试题:UIScrollView大概是如何实现的,它是如何捕捉、响应手势的?UIScrollView在滚动过程当中,其实是在修改原点坐标。当手指触摸后, scroll view会暂时拦截触摸事件,使用一个计时器。假如在计时器到点后没有发生手指移动事件,那么 scroll view 发送 tracking events 到被点击的 subview。假如在计时器到点前发生了移动事件,那么 scroll view 取消 tracking 自己发生滚动。 首先了解下UIScrollView对于touch事件的接收处理原理: UIScrollView应该是重载了hitTest 方法,并总会返回itself 。所以所有的touch 事件都会进入到它自己里面去了。内部的touch事件检测到这个事件是不是和自己相关的,或者处理或者除递给内部的view。 Ref |
iOS面试题:HTTP协议的特点,关于HTTP请求GET和POST的区别GET和POST的区别: HTTP超文本传输协议,是短连接,是客户端主动发送请求,服务器做出响应,服务器响应之后,链接断开。HTTP是一个属于应用层面向对象的协议,HTTP有两类报文:请求报文和响应报文。 HTTP请求报文:一个HTTP请求报文由请求行、请求头部、空行和请求数据4部分组成。 HTTP响应报文:由三部分组成:状态行、消息报头、响应正文。 GET请求:参数在地址后拼接,没有请求数据,不安全(因为所有参数都拼接在地址后面),不适合传输大量数据(长度有限制,为1024个字节)。 GET提交、请求的数据会附在URL之后,即把数据放置在HTTP协议头中。 POST请求:参数在请求数据区放着,相对GET请求更安全,并且数据大小没有限制。把提交的数据放置在HTTP包的包体中. GET提交的数据会在地址栏显示出来,而POST提交,地址栏不会改变。 传输数据的大小: GET提交时,传输数据就会受到URL长度限制,POST由于不是通过URL传值,理论上书不受限。 POST的安全性要比GET的安全性高; 通过GET提交数据,用户名和密码将明文出现在URL上,比如登陆界面有可能被浏览器缓存。 HTTPS:安全超文本传输协议(Secure Hypertext Transfer Protocol),它是一个安全通信通道,基于HTTP开发,用于客户计算机和服务器之间交换信息,使用安全套结字层(SSI)进行信息交换,即HTTP的安全版。 Ref |
removeFromSuperview每一个View都和视图结构以及响应者链有直接的关系,但是这篇文章不打算着重的讲这两个方面,主要讲removeFromSuperview方法。将当前视图从其父视图移除,需要调用removeFromSuperview方法。下面是苹果对于这个API的官方定义: Unlinks the receiver from its superview and its window, and removes it from the responder chain. removeFromSuperview就是一个视图节点删除的操作,执行这个方法,就等于在树形结构中找到该节点,从树型数据结构中删除该节点及其子节点,而并非只是删除该节点自己。同时,另一个操作就是把该对象从响应者链中移除。 执行removeFromSuperview方法后,会从父视图中移除,并且将Superview对视图的强引用删除,此时如果没有其他地方再对视图进行强引用,则会从内存中移除。如果还存在其他强引用,视图只是不在屏幕中显示,并没有将该视图从内存中移除。所以如果需要使用该视图,不需要再次创建,而是直接addSubview就可以了。 addSubview多次执行addSubview:操作 一个视图不只是向其他多个页面进行添加操作不会出现问题,而且向同一个视图上执行多次添加操作也是没有问题的,并不会导致视图被多次添加的问题,也不需要在添加之前进行removeFromSuperview操作,这个是在MRC和ARC都是有效的。因为系统在addSubview:方法中进行了一些判断操作,如果当前视图已经添加到其他视图,会将当前视图从其他视图中移除,然后执行添加操作。如果当前视图已经添加到这个视图中,就不会再次执行添加操作。 其实也说不上是坑,可以算是一个了解的知识点吧。在ARC或MRC的情况下,调用removeFromSuperview和addSubview:方法其中之一,都需要在另一个方法已经执行的情况下才会有效,对于多次执行一个同方法系统也是有判断操作的,并不会被执行多次。 例如调用remove方法之后,此时视图已经不在父视图之上了,在多次调用这个方法是不起作用的,而且MRC下引用计数也不会被减少多次。对于addSubview:方法也是一样的,向同一个父视图上添加子视图,不会被重复添加,添加之后引用计数也不会多次+1。 注意点无论是ARC还是MRC中多次调用removeFromSuperview和addSubview:方法,都不会造成造成重复释放和添加。 Ref |
iOS面试题:Scoket连接和HTTP连接的区别:HTTP协议是基于TCP连接的,是应用层协议,主要解决如何包装数据。Socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过Socket,我们才能使用TCP/IP协议。 HTTP连接:短连接,客户端向服务器发送一次请求,服务器响应后连接断开,节省资源。服务器不能主动给客户端响应(除非采用HTTP长连接技术),iPhone主要使用类NSURLConnection。 Socket连接:长连接,客户端跟服务器端直接使用Socket进行连接,没有规定连接后断开,因此客户端和服务器段保持连接通道,双方可以主动发送数据,一般多用于游戏.Socket默认连接超时时间是30秒,默认大小是8K(理解为一个数据包大小)。 Ref |
当面试官问:你有什么想问的?有没有培训制度?这个问题很重要,如果各位老哥是对整个技术了如指掌的,可以忽略这个问题,碰到过一家公司,老人已经都走了,没留下文档,自然也没人带,一个维护项目直接丢给我,面试官也就是我组长整天嫌我菜(没技术面,建议没技术面或太水的公司也别去,画了一个多小时的饼),后来请教了些前辈,基本正规公司,不论是校招还是社招,都会有人带的,放心问,不用担心社招公司不会培养这种 工作内容/我在能力上有没有需要增强的/公司对我的定位主要是想看下工作难度,如果希望寻求技术突破,但项目主要是CRUD,那可能就要认真考虑下了,同时也能问问有什么代表性的难点吗,看下和自己合不合适,另外,一定要问清楚加班的问题,有幸加过一年半,加班是很痛苦,可以完全打乱自己生活节奏的事,建议各位考虑好,仔细考虑自己的加班承受能力 项目组规模其实是怕人太少,整个项目组没几个同行,很虚 说出自己对工作的期望主要是对项目负责人问,一般是二面,仔细想想自己想要的工作环境,看看是不是合适,上班嘛,干的开心才能做的长远 您在公司一天是怎么度过的/您在这家公司工作感觉怎么样挺滑头的一个问题,主要想旁侧敲击下项目整体怎么样,加不加班啊,早上可不可以晚到会啊,中午快到吃饭可不可以早走几分钟啊,我待过两家公司,第一家外包,管理比较自由,吃饭可以早走几分钟,规定是13点40上班但基本都是14点才开始,另外一家公司感觉跟进了军队一样,13:28打铃过了两分钟所有人就全坐好了,这种说实话,有点难受 杂七杂八的主要想到的就是上边的问题,像一些企业文化这种有点虚的,可以酌情考虑,毕竟问太多也不太好 试用期多久一般是三个月,少数公司会一到两个月,可以问问,另外有试岗期的公司,也算是稀有,建议背一遍爱莲说 工资什么时候发侧面反应出这公司怎么样,10号以前发的基本都是好公司,10号到20号的,会很难受,假设你现在发工资的时间往后推迟10天会发生什么 社保公积金这个没什么,越多越好,去找下同学朋友问下,就知道这公司叫的公积金大概什么水平了,按最低标准交的,建议开溜 |
Why? 为什么初始化方法中需要self = [super init]?先大概解释一下self和super。self是对象指针,指向当前消息接收者。super是编译器指令,使用super调用方法是从当前消息接收者类的父类中开始查找方法的实现,但消息接收者还是子类。有关self和super的详细解释可以参阅《深入浅出 Runtime(四):super 的本质》。 Supersuper is a flag that tells the compiler to search for the method implementation in a very different place. It begins in the superclass of the class that defines the method where super appears. |
Runloop机制
|
swift的核心?要回答这个问题,我们可以参考一下刚刚提到的面向对象编程,在面向对象编程里,是从一个 class 开始的,那要是照这样说,在面向协议编程里就是从一个 protocol 了吗?这样解释对不对呢?我们可以在刚刚提到视频里找找答案,如果看过上面的视频,你会发现在上面的视频中 Apple 自己都说: "从一个 protocol 开始,别从 class 开始。" ——Dave Abrahams: 毁你三观教授 protocol 就是协议的意思。当然,可以从protocol 开始,但是从 protocol 开始了之后,该怎么做呢? 是的,这也是我们该思考的问题,我这里不会太着重去介绍 Swift 的基础,因为我默认看我视频的同学都已经掌握了 Swift 的基础了,所以关于 protocol 的概念我也不在详细介绍了,回到我们刚才的问题,现在我们已经有了 protocol,接下来我们要做的就是使用非常强大的 extension 了,额…,关于 extension 的概念我也不再详细介绍了,如果感觉基础不好的同学可以先去看一下基础,然后再来看我的视频吧,关于 extension,可以为现有的 class,struct,enum,protocol 添加新功能,注意刚刚我提到了 protocol,所以我们先现在可以在 protocol 的extension 里添加任何你需要添加的东西了。 那好,功能也添加了,那怎么该怎么使用这个 protocol 呢? 这也是个问题,让我们再分析一下,protocol 不同于 class 或者 struct,因为后两者可以各自调用它们的类型方法或者实例方法,但是 protocol 却不能直接使用,也不能实例化,既然都不行,那该怎么做啊?别着急,既然不能直接用,那我们就要考虑用上面提到的 class 或者 struct 了 |
面试题总结(Part1)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执行完再执行D22.列表页性能优化23.HTTPS(答案待完善)23.音视频相关1. ios内存管理机制iOS内存管理机制的原理是引用计数,当这块内存被创建后,它的引用计数0->1,表示有一个对象或指针持有这块内存,拥有这块内存的所有权,如果这时候有另外一个对象或指针指向这块内存,那么为了表示这个后来的对象或指针对这块内存的所有权,引用计数1->2,之后若有一个对象或指针不再指向这块内存时,引用计数-1,表示这个对象或指针不再拥有这块内存的所有权,当一块内存的引用计数变为0,表示没有任何对象或指针持有这块内存,系统便会立刻释放掉这块内存。 alloc、new :类初始化方法,开辟新的内存空间,引用计数+1; 2. NSThread、GCD、NSOperation多线程1、NSThread
1|[NSThread isMultiThreaded];//BOOL 是否开启了多线程
2|[NSThread currentThread];//NSThread 获取当前线程
3|[NSThread mainThread];//NSThread 获取主线程
4|[NSThread sleepForTimeInterval:1];//线程睡眠1s
5|
2、GCD
1dispatch_sync与dispatch_async//同步和异步操作
2
3dispatch_queue_t;//主要有串行和并发两种;
4 其中:
5 dispatch_queue_create("concurrent_queue", DISPATCH_QUEUE_CONCURRENT)并发;
6 dispatch_queue_create("serial_queue", DISPATCH_QUEUE_SERIAL)串行;
7
8dispatch_once_t;//代码只会被执行一次,用于单例
9dispatch_after;//延迟操作
10dispatch_get_main_queue;//回到主线程操作
11
12
13//Demo单例
14+ (instancetype)sharedInstance {
15 static ZZScreenshotsMonitor *instance = nil;
16 static dispatch_once_t onceToken;
17 dispatch_once(&onceToken, ^{
18 instance = [[self alloc] init];
19 });
20 return instance;
21}
22
23
24
25//Demo:执行顺序
26- (void)viewDidLoad {
27 [super viewDidLoad];
28 dispatch_async(dispatch_get_main_queue(), ^{
29 NSLog(@"1");
30 });
31
32 NSLog(@"2");33
34 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,0);
35
36 dispatch_sync(queue, ^{
37 NSLog(@"3");
38 });
39
40 dispatch_async(dispatch_get_main_queue(), ^{
41
NSLog(@"4");
42 });
43
44 dispatch_async(queue, ^{
45 NSLog(@"5");
46 });
47
48 NSLog(@"6");
49
50 [self performSelector:@selector(delayMethod) withObject:nil afterDelay:0];
51
52 NSLog(@"8");
53}
54
55- (void)delayMethod {
56
57}
58
59打印结果:23658147;其中5和8随机调换
60
61
NSOperation
3.输入一个字符串,判断这个字符串是否是有效的IP地址1+ (BOOL)isValidIP:(NSString *)ipStr {
2 if (nil == ipStr) {
3 return NO;
4 }
5
6 NSArray *ipArray = [ipStr componentsSeparatedByString:@"."];
7 if (ipArray.count == 4) {
8 for (NSString *ipnumberStr in ipArray) {
9 if ([self isPureInt:ipnumberStr]) {
10 int ipnumber = [ipnumberStr intValue];
11 if (!(ipnumber>=0 && ipnumber<=255)) {
12 return NO;
13 }
14 }
15 }
16 return YES;
17 }
18 return NO;
19}
20//是否整形
21- (BOOL)isPureInt:(NSString*)string {
22 NSScanner* scan = [NSScanner scannerWithString:string];
23 int val;
24 return[scan scanInt:&val] && [scan isAtEnd];
25}
26//是否只含有数字
27- (BOOL)validateNumber:(NSString*)number {
28 BOOL res = YES;
29 NSCharacterSet* tmpSet = [NSCharacterSet characterSetWithCharactersInString:@"0123456789"];
30 int i = 0;
31 while (i < number.length) {
32 NSString * string = [number substringWithRange:NSMakeRange(i, 1)];
33 NSRange range = [string rangeOfCharacterFromSet:tmpSet];
34 if (range.length == 0) {
35 res = NO;
36 break;
37 }
38 i++;
39 }
40 return res;
41
42}
43
44
4.大数加法怎么实现?
1/两个大数相加算法
2-(NSString *)addTwoNumberWithOneNumStr:(NSString *)one anotherNumStr:(NSString *)another
3{
4 int i = 0;
5 int j = 0;
6 int maxLength = 0;
7 int sum = 0;
8 int overflow = 0;
9 int carryBit = 0;
10 NSString *temp1 = @"";
11 NSString *temp2 = @"";
12 NSString *sums = @"";
13 NSString *tempSum = @"";
14 int length1 = (int)one.length;
15 int length2 = (int)another.length;
16 //1.反转字符串
17 for (i = length1 - 1; i >= 0 ; i--) {
18 NSRange range = NSMakeRange(i, 1);
19 temp1 = [temp1 stringByAppendingString:[one substringWithRange:range]];
20 NSLog(@"%@",temp1);
21 }
22 for (j = length2 - 1; j >= 0; j--) {
23 NSRange range = NSMakeRange(j, 1);
24 temp2 = [temp2 stringByAppendingString:[another substringWithRange:range]];
25 NSLog(@"%@",temp2);
26 }
27
28 //2.补全缺少位数为0
29 maxLength = length1 > length2 ? length1 : length2;
30 if (maxLength == length1) {
31 for (i = length2; i < length1; i++) {
32 temp2 = [temp2 stringByAppendingString:@"0"];
33 NSLog(@"i = %d --%@",i,temp2);
34 }
35 }else{
36 for (j = length1; j < length2; j++) {
37 temp1 = [temp1 stringByAppendingString:@"0"];
38 NSLog(@"j = %d --%@",j,temp1);
39 }
40 }
41 //3.取数做加法
42 for (i = 0; i < maxLength; i++) {
43 NSRange range = NSMakeRange(i, 1);
44 int a = [temp1 substringWithRange:range].intValue;
45 int b = [temp2 substringWithRange:range].intValue;
46 sum = a + b + carryBit;
47 if (sum > 9) {
48 if (i == maxLength -1) {
49 overflow = 1;
50 }
51 carryBit = 1;
52 sum -= 10;
53 }else{
54 carryBit = 0;
55 }
56 tempSum = [tempSum stringByAppendingString:[NSString stringWithFormat:@"%d",sum]];
57 }
58 if (overflow == 1) {
59 tempSum = [tempSum stringByAppendingString:@"1"];
60 }
61 int sumlength = (int)tempSum.length;
62 for (i = sumlength - 1; i >= 0 ; i--) {
63 NSRange range = NSMakeRange(i, 1);
64 sums = [sums stringByAppendingString:[tempSum substringWithRange:range]];
65 }
66 NSLog(@"sums = %@",sums);
67 return sums;
68}
5.简述KVC和KVO,其中KVO实现原理?
6.Block实现原理;堆上和栈上的数据如何同步?
1 Block类 原存储域 调用copy效果
2 _NSConcreteStackBlock 栈 从栈copy到堆
3 _NSConcreteGlobalBlock 数据域(.data域) 什么也不做
4 _NSConcreteMallocBlock 堆 引用计数+1 7.iOS设计模式适配器模式;
策略模式;
观察者模式;
原型/外观模式;
工厂模式;
桥接模式;
代理模式;
单例模式;
备忘录模式;
生成器模式;
命令模式;
8.多线程有哪些?如何保证多线程中读写分离,加锁方案?
9.如何删除单链表中一个元素?
1Status ListDelete(LinkList *L,int i,ElemType *e){
2 int j;
3 LinkList p,q;
4 p = *L; // 声明一结点p指向链表第一个结点
5 j = 1;
6 while (p->next && j < i) /* 遍历寻找第i个元素 */
7 {
8 p = p->next;
9 ++j;
10 }
11 if (!(p->next) || j > i)
12 return ERROR; /* 第i个元素不存在 */
13 q = p->next;
14 p->next = q->next; /* 将q的后继赋值给p的后继 */
15 *e = q->data; /* 将q结点中的数据给e */
16 free(q); /* 让系统回收此结点,释放内存 */
17 return OK;
18 }
19 10.NSNotificationCenter通知中心的实现原理?
1-(void)postNotification:(NSNotification *)notification;
2-(void)postNotificationName:(NSNotificationName)aName object:(nullable id)anObject;
3-(void)postNotificationName:(NSNotificationName)aName object:(nullable id)anObject userInfo:(nullable NSDictionary *)aUserInfo;
1- (void)addObserver:(id)observer selector:(SEL)aSelector name:(nullable NSNotificationName)aName object:(nullable id)anObject;
2- (id <NSObject>)addObserverForName:(nullable NSNotificationName)name object:(nullable id)obj queue:(nullable NSOperationQueue *)queue usingBlock:(void (^)(NSNotification *note))block NS_AVAILABLE(10_6, 4_0);
11.推送如何实现的?1.由App向iOS设备发送一个注册通知,用户需要同意系统发送推送。2.iOS应用向APNS远程推送服务器发送App的Bundle Id和设备的UDID。3.APNS根据设备的UDID和App的Bundle Id生成deviceToken再发回给App。4.App再将deviceToken发送给远程推送服务器(自己的服务器), 由服务器保存在数据库中。5.当自己的服务器想发送推送时, 在远程推送服务器中输入要发送的消息并选择发给哪些用户的deviceToken,由远程推送服务器发送给APNS。6.APNS根据deviceToken发送给对应的用户。12.SEL的使用和原理?
13.点击事件如何穿透透明的View?1- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
2 UIView *hitView = [super hitTest:point withEvent:event];
3 if(hitView == self){
4 return nil;
5 }
6 return hitView;
7 }
14.RunLoop的实现原理?(答案待完善)
15.简述Runtime,发送消息的过程;
消息转发:1:动态方法解析1+ (BOOL)resolveInstanceMethod:(SEL)selector;
2+ (BOOL)resolveClassMethod:(SEL)selector; 2:备援接收者(重定向)1- (id)forwardingTargetForSelector:(SEL)selector;
2 3:完整的消息转发(NSInvocation)1- (void)forwardInvocation:(NSInvocation *)invocation;
2
16.简述weak的实现原理;
17.写一个单例;1+ (instancetype)sharedInstance {
2 static RMF *instance = nil;
3 static dispatch_once_t onceToken;
4 dispatch_once(&onceToken, ^{
5 instance = [[self alloc] init];
6 });
7
8 return instance;
9 }
18.如何从字符串中得到一个整数?1- (BOOL)isPureNumandCharacters:(NSString *)text
2{
3 for(int i = 0; i < [text length]; ++i) {
4 int a = [text characterAtIndex:i];
5 if ([self isNum:a]){
6 continue;
7 } else {
8 return NO;
9 }
10 }
11 return YES;
12}
19.数组去重方式;数组法1for (NSString *item in originalArr) {
2 if (![resultArrM containsObject:item]) {
3 [resultArrM addObject:item];
4 }
5}
利用NSDictionary1for (NSNumber *n in originalArr) {
2 [dict setObject:n forKey:n];
3}
NSSet1 NSSet *set = [NSSet setWithArray:originalArr];
20.设计一个数据库;(答案待完善)
21.实现多个网络请求ABC执行完再执行D
1 dispatch_group_t group = dispatch_group_create();
2 dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
3 dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
4 dispatch_group_async(group, queue, ^{
5 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
6 //异步执行A
7 dispatch_semaphore_signal(semaphore);
8 });
9 dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
10 });
11
12 dispatch_group_async(group, queue, ^{
13 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
14 //异步执行B
15 dispatch_semaphore_signal(semaphore);
16 });
17 dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
18 });
19
20 dispatch_group_async(group, queue, ^{
21 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
22 //异步执行C
23 dispatch_semaphore_signal(semaphore);
24 });
25 dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
26 });
27
28 dispatch_group_notify(group, queue, ^{
29 //执行D
30 });
22.列表页性能优化如何检测
优化方案
1//1、使用CAShapeLayer和UIBezierPath设置圆角;
2UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:imageView.bounds byRoundingCorners:UIRectCornerAllCorners cornerRadii:imageView.bounds.size];
3CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init];
4maskLayer.frame = imageView.bounds;
5maskLayer.path = maskPath.CGPath;
6imageView.layer.mask = maskLayer;
7
8//2、UIBezierPath和Core Graphics框架画出一个圆角
9UIGraphicsBeginImageContextWithOptions(imageView.bounds.size,NO,1.0);
10[[UIBezierPathbezierPathWithRoundedRect:imageView.boundscornerRadius:imageView.frame.size.width]addClip];
11[imageView drawRect:imageView.bounds];
12imageView.image=UIGraphicsGetImageFromCurrentImageContext();
13UIGraphicsEndImageContext();
14[self.view addSubview:imageView];
23.HTTPS(答案待完善)
23.音视频相关采集视频,音频–》使用iOS原生框架 AVFoundation.framework
|
面试题总结(Part2)1.统计一个字符数组中每个字符出现的次数?2.实现一个反转二叉树;3.如何获取VC上所有的Button?4.排序算法有哪些?(答案待完善)5.self和super区别;6.UIViewController的生命周期;7.UIButton的继承链,如何改变它的点击区域;8.Category9.实现setter方法10.iOS判断一个字符串中是否都是数字11.如何合并两个有序数组?12.GET和POST区别13.面向对象编程的六大原则14.ios Animation15.为什么必须在主线程中操作UI16.显式和隐式动画的区别17.OC内联函数 inline1.统计一个字符数组中每个字符出现的次数?void main()
{
char str[20];
int i,num[256]={0};
printf("please input string:");
scanf("%s",str);
for(i=0;i<strlen(str);i++)
num[(int)str[i]]++;
for(i=0;i<256;i++)
if(num[i]!=0)
printf("字符%c出现%d次\n",(char)i,num[i]);
}
2.实现一个反转二叉树;@interface TreeNode : NSObject
@property (nonatomic, assign) NSInteger val;
@property (nonatomic, strong) TreeNode *left;
@property (nonatomic, strong) TreeNode *right;
@end
- (void)exchangeNode:(TreeNode *)node {
//判断是否存在node节点
if(node) {
//交换左右节点
TreeNode *temp = node.left;
node.left = node.right;
node.right = temp;
}
}
- (TreeNode *)invertTree:(TreeNode *)root
{
//边界条件 递归结束或输入为空情况
if(!root) {
return root;
}
//递归左右子树
[self invertTree:root.left];
[self invertTree:root.right];
//交换左右子节点
[self exchangeNode:root];
return root;
}
3.如何获取VC上所有的Button?
4.排序算法有哪些?(答案待完善)
5.self和super区别;
1.当使用 self 调用方法时,会从当前类的方法列表中开始找,如果没有,就从父类中再找;而当使用 super 时,则从父类的方法列表中开始找,然后调用父类的这个方法。 struct objc_super {
id receiver;
Class superClass;
};
|
NSTimer应该如何避免Retain Cycle?NSTimer准吗? 定时器被添加在主线程中,由于定时器在一个RunLoop中被检测一次,所以如果在这一次的RunLoop中做了耗时的操作,当前RunLoop持续的时间超过了定时器的间隔时间,那么下一次定时就被延后了。 |
Uh oh!
There was an error while loading. Please reload this page.
请你出一套iOS面试题
底层
参考解答: self.name ="object":会调用对象的setName()方法; name =“object":会直接把object赋值给当前对象的name属性。
NSString*obj = [[NSData alloc] init];
obj在编译时和运行时分别时什么类型的对象?参考解答: 编译时是NSString的类型, 运行时是NSData类型的对象
Runloop
的面试题:在程序通过
main()
函数启动后,在主线程开启UIApplicationMain
的Runloop
后,在下面的main()
函数里创建了一个autoreleasepool
,请问如果程序不退出,main()
函数永远不会返回,那么程序中(比如一个VC中)创建的对象是否就永远不会被释放?参考解答: 在程序创建的对象,不是被
main()
函数中的autoreleasepool
管理的,而是由主线程的
Runloop
管理,在某次Runloop
循环中,Runloop
休眠之前调用了对象的release
方法释放。在每次
Runloop
循环中,Runloop
休眠之前会调用了对象的release
方法释放AutoreleasePoolPage
中边界内的对象。Cocoa
参考解答: 两个问题: 1、添加,删除,修改数组内的元素的时候程序会因为找不到对应的方法而崩溃.因为copy就是复制一个不可变NSArray的对象,使用了atomic属性会严重影响性能。
参考解答: 我们在声明一个NSString属性时,对于其内存相关特性,通常有两种选择(基于ARC环境): strong与copy。那这两者有什么区别呢?什么时候该用strong,什么时候该用copy呢?
由于NSMutableString是NSString的子类,所以一个NSString指针 可以指向NSMutableString对象,让我们的strongString指针指向一 个可变字符串是OK的。
而上面的例子可以看出,当源字符串是NSString时,由于字符串是不可变的,所以,不管是strong还是copy属性的对象,都是指向源对象,copy操作只是做了次浅拷贝。当源字符串是NSMutableString时,strong属 性只是增加了源字符串的引用计数,而copy属性则是对源字符串做了次深拷贝,产生一个新的对象,且copy属性对象指向这个新的对象。另外需要注意的是,这个copy属性对象的类型始终是NSString,而不是NSMutableString,因此其是不可变的。
这里还有一个性能问题,即在源字符串是NSMutableString, strong是单纯的增加对象的用计数,而copy操作是执行了一次深拷贝,所以性能上会有所差异。而如果源字符串是NSString时,则没有这个问题。
所以,在声明NSString属性时,到底是选择strong还是copy,可以根据实际情况来定。不过,一般我们将对象声明为NSString时,都不希望它改变,所以大多数情况下,我们建议用copy,以免因可变字符串的修改导致的一些非预期问题。
2.3 __strong的使用场景?
参考解答:
AutoLayout
,是苹果公司提供的一个基于约束布局,动态计算视图大小和位置的库,并且已经集成到了Xcode开发环境里。AutoLayout的实现原理
AutoLayout性能
AutoLayout关于更新的几个方法的区别
参考:Masonry · ming1016/study Wiki
多线程Demo学习 · Issue #21 · FrizzleFur/DailyLearning
性能优化
TableView性能优化
UITableView核心思想
tableView:cellForRowAtIndexPath:
和tableView:heightForRowAtIndexPath:
.UlTableView的优化总结
tableView:cellForRowAtIndexPath:
方法。只是有一点,尽量不要在此时绑定数据,因为目前在屏幕上还没有cell,可以在UITableView的delegate方法tableView:willDisplayCell:forRowAtIndexPath:
中进行数据的填充。需要说明的是,你可能会动态计算cel高度,但最好是不要选择Autolayout。使用Autolayout后,会根据cel的子视图使得求解的约束也越多,从而降低计算速度,影响滑动时FPS。所以,为了使tableview平滑滚动,请使用动态计算高度,不要选择Autolayout。shouldRasterize
要设成YES。drawAtPoint
drawAtPoint:(CGPoint)point forWidth:(CGFloat)width withFont:(UIFont*)font
cellForRow
方法里面设置cell的图片数据源,也就是说如果一个cell的imageview对象开启了一个下载任务,这个时候该cell对象发生了重用,新的image数据源会开启。imageview
对象,就会发生2个下载任务回调给同一个imageview对象。这个时候就有必要做一些处理,避免回调发生时,错误的image数据源刷新了UI。tableview
的时候我们需要手动去取消掉下载操作,当用户停止滑动,再去执行下载操作网络请求
网络Http请求 · Issue #9 · FrizzleFur/DailyLearning
架构设计
设计模式
组件化
知名框架原理
CS基础
职业
The text was updated successfully, but these errors were encountered: