前言
YY面试题方向。请做参考。
一 你对meta class的理解
二 weak为何会解决block中的循环引用的问题,你对weak和block底层实现的理解
https://www.jianshu.com/p/2bf505398f51
https://www.jianshu.com/p/51d04b7639f1
三 NSNotification,KVO为何会产生内存泄漏?如果确实内存泄漏了,你该怎么办?NSNotification的底层实现?你怎么来设计一个NSNotification?
四 GCD开线程之后耗时操作,如果中间出了问题,你怎么杀掉这个线程?GCD的底层实现?
五 Block的底层实现?
六 Https为什么比Http更安全?为什么需要证书?中间发生了什么?
七 JavascriptBridge的底层实现?RN和JSPatch的底层实现?
八 Base64的底层实现?
九 NSTimer为什么会造成内存泄漏?顺便说说Runloop和线程的底层实现?
https://blog.csdn.net/ggghub/article/details/50240225
https://www.jianshu.com/p/0e8323c3eaf1
https://www.jianshu.com/p/296f182c8faa
十 TableView在reloadData的时候是异步还是同步的?
网上看了一大圈, 没有找到满意的答案.所以自己测试一波.
//
// ViewController.m
// TestProject2
//
// Created by MustangYM on 2018/5/15.
// Copyright © 2018年 YY Inc. All rights reserved.
//
#import "ViewController.h"
@interface ViewController ()<UITableViewDelegate , UITableViewDataSource>
@property (strong, nonatomic) UITableView *tableView;
@property (strong, nonatomic) NSArray *dataArray;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//随便添加一个TableView,frame啥的都写好,没啥.
[self.view addSubview:self.tableView];
__weak __typeof (self) wself = self;
//模拟网络请求2.0之后刷新TableView
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.dataArray = @[@"sd",@"adasd",@"dx",@"bb",@"dsc",@"fnn",@"ll",@"qq",@"pp",@"fgh"];
[wself testTableView];
});
}
- (void)testTableView{
NSLog(@"执行tableView刷新动作");
[self.tableView reloadData];
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"我就看你什么时候打印");
});
//通过这个方法猜测tableView里面做了些什么
//实际打印结果也显示,tableview的一个计算还是异步的,只是渲染才是在子线程
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"开子线程的任务");
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"开子线程的任务完成");
});
});
//阻塞主线程,我试过1000次,和30次打印出来顺序一样,为了方便截图,少搞点了.
for (int i = 0; i < 30; i++) {
NSLog(@"↓");
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return self.dataArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"id"];
cell.textLabel.text = self.dataArray[indexPath.row];
NSLog(@"cell的刷新%ld--%@",indexPath.row,[NSThread currentThread]);
return cell;
}
打印:
2018-05-28 16:03:40.396447+0800 TestProject2[30423:7231574] 执行tableView刷新动作
2018-05-28 16:03:40.396850+0800 TestProject2[30423:7231574] ↓
2018-05-28 16:03:40.396865+0800 TestProject2[30423:7231667] 开子线程的任务
2018-05-28 16:03:40.396978+0800 TestProject2[30423:7231574] ↓
2018-05-28 16:03:40.397121+0800 TestProject2[30423:7231574] ↓
2018-05-28 16:03:40.397209+0800 TestProject2[30423:7231574] ↓
2018-05-28 16:03:40.397301+0800 TestProject2[30423:7231574] ↓
2018-05-28 16:03:40.397379+0800 TestProject2[30423:7231574] ↓
2018-05-28 16:03:40.397472+0800 TestProject2[30423:7231574] ↓
2018-05-28 16:03:40.397561+0800 TestProject2[30423:7231574] ↓
2018-05-28 16:03:40.397652+0800 TestProject2[30423:7231574] ↓
2018-05-28 16:03:40.397736+0800 TestProject2[30423:7231574] ↓
2018-05-28 16:03:40.397829+0800 TestProject2[30423:7231574] ↓
2018-05-28 16:03:40.397914+0800 TestProject2[30423:7231574] ↓
2018-05-28 16:03:40.397996+0800 TestProject2[30423:7231574] ↓
2018-05-28 16:03:40.398077+0800 TestProject2[30423:7231574] ↓
2018-05-28 16:03:40.398344+0800 TestProject2[30423:7231574] ↓
2018-05-28 16:03:40.398517+0800 TestProject2[30423:7231574] ↓
2018-05-28 16:03:40.398703+0800 TestProject2[30423:7231574] ↓
2018-05-28 16:03:40.398849+0800 TestProject2[30423:7231574] ↓
2018-05-28 16:03:40.399066+0800 TestProject2[30423:7231574] ↓
2018-05-28 16:03:40.399224+0800 TestProject2[30423:7231574] ↓
2018-05-28 16:03:40.399383+0800 TestProject2[30423:7231574] ↓
2018-05-28 16:03:40.399540+0800 TestProject2[30423:7231574] ↓
2018-05-28 16:03:40.399686+0800 TestProject2[30423:7231574] ↓
2018-05-28 16:03:40.399824+0800 TestProject2[30423:7231574] ↓
2018-05-28 16:03:40.399970+0800 TestProject2[30423:7231574] ↓
2018-05-28 16:03:40.400199+0800 TestProject2[30423:7231574] ↓
2018-05-28 16:03:40.400456+0800 TestProject2[30423:7231574] ↓
2018-05-28 16:03:40.400601+0800 TestProject2[30423:7231574] ↓
2018-05-28 16:03:40.400735+0800 TestProject2[30423:7231574] ↓
2018-05-28 16:03:40.400878+0800 TestProject2[30423:7231574] ↓
2018-05-28 16:03:40.402492+0800 TestProject2[30423:7231574] cell的刷新0--<NSThread: 0x600000076640>{number = 1, name = main}
2018-05-28 16:03:40.408460+0800 TestProject2[30423:7231574] cell的刷新1--<NSThread: 0x600000076640>{number = 1, name = main}
2018-05-28 16:03:40.409611+0800 TestProject2[30423:7231574] cell的刷新2--<NSThread: 0x600000076640>{number = 1, name = main}
2018-05-28 16:03:40.410355+0800 TestProject2[30423:7231574] cell的刷新3--<NSThread: 0x600000076640>{number = 1, name = main}
2018-05-28 16:03:40.410973+0800 TestProject2[30423:7231574] cell的刷新4--<NSThread: 0x600000076640>{number = 1, name = main}
2018-05-28 16:03:40.411662+0800 TestProject2[30423:7231574] cell的刷新5--<NSThread: 0x600000076640>{number = 1, name = main}
2018-05-28 16:03:40.412281+0800 TestProject2[30423:7231574] cell的刷新6--<NSThread: 0x600000076640>{number = 1, name = main}
2018-05-28 16:03:40.412832+0800 TestProject2[30423:7231574] cell的刷新7--<NSThread: 0x600000076640>{number = 1, name = main}
2018-05-28 16:03:40.413406+0800 TestProject2[30423:7231574] cell的刷新8--<NSThread: 0x600000076640>{number = 1, name = main}
2018-05-28 16:03:40.414019+0800 TestProject2[30423:7231574] cell的刷新9--<NSThread: 0x600000076640>{number = 1, name = main}
2018-05-28 16:03:40.417503+0800 TestProject2[30423:7231574] 我就看你什么时候打印
2018-05-28 16:03:40.417669+0800 TestProject2[30423:7231574] 开子线程的任务完成
结论
实验结果表明tableview从数据到界面整个过程,那肯定是开子线程去计算,然后回到主线程做UI的一个刷新渲染,这是一个异步的过程. 即使是这样,reloaddata这个动作还是会受到主线程中所有耗时任务的干扰。如同德莱文扔出去的斧子,现在回来了,但是德莱文双手都拿着炸鸡,所以斧子只能先等等。
网友评论