.div_spearte { height: 16px; } .button_half_width { background-color: red; color: white; border-width: 0; width: 45%; font-size: 12px; } .button_full_width { background-color: red; color: white; border-width: 0; width: 95%; font-size: 20px; } .title1 { color: red; font-size: 14px; padding-left: 10px; } .title1 .title2 { color: blue; font-size: 12px; } .textarea_one_line { width: 95%; height: 16px; } .textarea_decription_multiline { width: 95%; height: 80px; } .textarea_one_appRouteUrl { width: 95%; height: 70px; } .textarea_one_browseUrl { width: 95%; height: 80px; }
.div_spearte { height: 16px; } .button_half_width { background-color: red; color: white; border-width: 0; width: 45%; font-size: 12px; } .button_full_width { background-color: red; color: white; border-width: 0; width: 95%; font-size: 20px; } .title1 { color: red; font-size: 14px; padding-left: 10px; } .title1 .title2 { color: blue; font-size: 12px; } .textarea_one_line { width: 95%; height: 16px; } .textarea_decription_multiline { width: 95%; height: 80px; } .textarea_one_appRouteUrl { width: 95%; height: 70px; } .textarea_one_browseUrl { width: 95%; height: 80px; }
小程序测试页面

小程序首页


日志
Document
点击跳转test1
点击跳转test2
Document
点击跳转test1
点击跳转test2
小程序测试页面

小程序首页


日志

必备知识架构-线程与网络-①线程

[toc]

知识架构

iOS知识库

Android知识库

目录

1
2
3
4
5
>1、多线程的原理
>2、多线程的优缺点
>3、多线程在iOS开发中的应用
>4、iOS中三种多线程技术(NSThread、NSOperation/NSOperationQueue、GCD)
>
1
2
3
4
5
6
>线程间通信的体现:
>1. 一个线程传递数据给另一个线程
>2. 在一个线程中执行完特定任务后,转到另一个线程继续执行任务
>
>附:其他传值方法总结
>
1
2
3
4
5
6
7
8
>1、通常的做法/不好的做法
>2、合理的做法(使用多线程异步执行)
>1)、先说说简单的多线程同步问题(异步线程里没有再开启异步线程)
>2)、真正的线程同步问题(异步线程里再开启异步线程)
>3)、其他补充
>附1:多个请求依次执行
>附2:并发数控制
>
1
2
>1、线程安全
>
1
2
3
>1、在使用SQLite过程中,如果多条线程同时操作同一数据库会造成什么问题,怎么解决?
>2、串行队列与并行队列的区别
>

一、多线程介绍

< 返回目录

1、多线程的原理

同一时间,CPU只能处理1条线程,只有1条线程在工作(执行)。多线程并发(同时)执行,其实是CPU快速地在多条线程之间调度(切换)。如果CPU调度线程的时间足够快,就造成了多线程并发执行的假象。
思考:如果线程非常非常多,会发生什么情况?
答:CPU会在N多线程之间调度,CPU会累死,消耗大量的CPU资源,每条线程被调度执行的频次会降低(线程的执行效率降低)。

2、多线程的优缺点

1
2
3
4
5
6
7
8
多线程的优点
能适当提高程序的执行效率
能适当提高资源利用率(CPU、内存利用率)

多线程的缺点
开启线程需要占用一定的内存空间(默认情况下,主线程占用1M,子线程占用512KB),如果开启大量的线程,会占用大量的内存空间,降低程序的性能
线程越多,CPU在调度线程上的开销就越大
程序设计更加复杂:比如线程之间的通信、多线程的数据共享

3、多线程在iOS开发中的应用

主线程:

一个iOS程序运行后,默认会开启1条线程,称为“主线程”或“UI线程”

主线程的主要作用:

显示\刷新UI界面,处理UI事件(比如点击事件、滚动事件、拖拽事件等)

主线程的使用注意:

别将比较耗时的操作放到主线程中。耗时操作会卡住主线程,严重影响UI的流畅度,给用户一种“卡”的坏体验。

4、iOS中三种多线程技术(NSThread、NSOperation/NSOperationQueue、GCD)

1.NSThread
  1. 使用nsthread对象建立一个线程非常方便
  2. 但是!要使用nsthread管理多个线程非常困难,不推荐使用
  3. 技巧!使用[NSThread currentThread]跟踪任务所在线程,适用于这三种技术
2.NSOperation/NSOperationQueue

NSOperation和NSOperationQueue相关

  1. 是使用gcd实现的一套objective-c的api
  2. 是面向对象的线程技术
  3. 提供了一些在gcd中不容易实现的特性,如:限制最大并发数量、操作之间的依赖关系
1
2
3
4
5
6
7
8
9
10
> NSOperation`是系统提供的抽象的基类,我们使用的时候需要使用继承于它的子类。系统为我们提供了两种继承于`NSOperation`的子类,分别是`NSInvocationOperation`和`NSBlockOperation。
>
> 当将操作添加到主操作队列时,所有操作会按照添加到队列中的先后顺序串行依次执行。(主队列是GCD自带的一种特殊串行队列。)
> NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
> [mainQueue addOperation:op1];
>
> 当将任务添加到自定义队列的时候,会开启子线程,操作会并发执行。
> NSOperationQueue *customQueue = [[NSOperationQueue alloc]init];
> [customQueue addOperation:op1];
>
3.GCD —— grand central dispatch
  1. 是基于c语言的底层api
  2. 用block定义任务,使用起来非常灵活便捷
  3. 提供了更多的控制能力以及操作队列中所不能使用的底层函数

NSOperationQueue与GCD的使用原则和场景

NSOperationQueue与GCD的使用原则和场景

三、线程等待(线程同步)、线程依赖、任务顺序问题

< 返回目录

多个任务中,某个线程的执行依赖其他线程的执行完毕,或者某个线程的执行需等待其他线程执行完毕。

常见场景:
某个页面加载时通过网络请求获得相应的数据,再做某些操作。有时候加载的内容需要通过好几个请求的数据组合而成,比如有两个请求A和B。

多线程同步需求分析图

1、通常的做法/不好的做法:把并发队列变成串行

常见的有:为了省事,会将B请求放在A请求成功的回调中发起,将C请求放在B请求成功的回调中发起,在C的成功回调中将数据组合起来,这样做有明显的问题:

1
2
①、请求如果多了,需要写许多嵌套的请求
②、请求被变成了同步的方式了,这是最大的问题,在网络差的情况下,如果有n个请求,意味着用户要等待n倍于并发请求的时间才能看到内容

2、合理的做法(使用多线程异步执行)

1)、先说说简单的多线程同步问题(异步线程里没有再开启异步线程)

首先我们先来看简单的多线程同步问题(异步线程里没有再开启异步线程),这种时候,我们可以使用的方法有

使用GCD线程组dispatch_group的dispatch_group_notify即可解决问题。其中notify的作用就是在group中的其他操作全部完成后,再操作自己的内容。
② 使用NSOperationQueue中operation的addDependency
③使用dispatch_barrier_async方法。

①、使用GCD线程组dispatch_group的dispatch_group_notify即可解决问题

使用dispatch_group方法的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
dispatch_group_t group = dispatch_group_create();

dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//请求1
NSLog(@"Request_1");
});

dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//请求2
NSLog(@"Request_2");
});

dispatch_group_notify(group, dispatch_get_main_queue(), ^{
//界面刷新
NSLog(@"任务均完成,刷新界面");
});
②使用使用NSOperationQueue中operation的addDependency,则是
1
2
3
4
5
6
7
//4.设置依赖
[operation3 addDependency:operation1]; //任务二依赖任务一
[operation3 addDependency:operation2]; //任务三依赖任务二

//5.创建队列并加入任务
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperations:@[operation3, operation2, operation1] waitUntilFinished:NO];
③dispatch_barrier_async

2)、真正的线程同步问题(异步线程里再开启异步线程)

对于上面的例子,当将上面三个操作改成真实的网络操作后,这个简单的做法突然变得无效了,这是为什么呢?

其实这个道理很简单,因为我们开启的网络请求,是一个异步线程,所谓的异步线程,就是告诉系统你不要管我是否完成了,你尽管执行其他操作,开一个线程让我到外面操作去执行就行了,对我的处理你已经完成了,也就是说线程只负责将请求发出去,就认为自己的任务算完成了。所以,当三个请求都发送出去后,不会管网络操作是否完成,就会执行notify中的内容,但由于请求结果本身需要一定的时间,所以导致了界面都刷新了,而请求结果才返回。

即上面的问题,总结为如果dispatch_group_async里执行的是异步代码dispatch_group_notify会直接触发而不会等待异步任务完成。

所以,对于这种异步线程里开异步线程的线程同步问题,该怎么处理呢?

为了应对这种异步线程里开异步线程的线程同步问题,其实我们需要多处理的只是监控异步线程里的所有操作(包括异步线程里的异步线程)都结束后,才算这个异步线程结束

这里我们的解决方法常见的有:

方法A:直接使用dispatch_group_enter和dispatch_group_leave,即只需要在任务开始前enter和结束后leave即可达到线程同步的效果。

dispatch_group_enter(group):下面的任务由group组管理,group组的任务数+1
dispatch_group_leave(group):相应的任务执行完成,group组的任务数-1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
- (void)testGroupSync_userEnterLeave {
dispatch_group_t group = dispatch_group_create();

dispatch_group_enter(group);
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//请求1
dispatch_async(dispatch_get_global_queue(0, 0), ^{
sleep(5);
NSLog(@"任务一完成");
dispatch_group_leave(group);
});
});

dispatch_group_enter(group);
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//请求2
dispatch_async(dispatch_get_global_queue(0, 0), ^{
sleep(8);
NSLog(@"任务二完成");
dispatch_group_leave(group);
});
});


dispatch_group_notify(group, dispatch_get_main_queue(), ^{
//界面刷新
NSLog(@"任务均完成,刷新界面");
});
}

方法B:使用信号量,控制异步线程的结束,来达到多线程同步的效果。

在GCD中有三个函数是semaphore的操作,分别是:

1
2
3
  dispatch_semaphore_create   创建一个semaphore
  dispatch_semaphore_signal   发送一个信号(信号量+1)
  dispatch_semaphore_wait    等待信号(wait执行完后,信号量-1)

实际使用,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
- (void)testGroupSync_semaphore_signal_wait {
dispatch_group_t group = dispatch_group_create();

// 创建一个控制线程同步的信号量,初始值为0(红灯)
dispatch_semaphore_t syncSemaphore = dispatch_semaphore_create(0);
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//先再任务1的线程里中再开启一个异步线程执行请求1,同时堵塞住此时的任务1所在的线程,等到已开始的异步请求1结束之后,原本阻塞住的任务1线程才会恢复畅通,才代表任务1结束了。
//请求1
dispatch_async(dispatch_get_global_queue(0, 0), ^{
sleep(5);
NSLog(@"任务一完成");
// 使信号的信号量+1,这里的信号量本来为0,+1信号量为1(绿灯)
dispatch_semaphore_signal(syncSemaphore);
});

// 开启信号等待,设置等待时间为永久,直到信号的信号量大于等于1(等绿灯)
dispatch_semaphore_wait(syncSemaphore, DISPATCH_TIME_FOREVER);
});

dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//请求2
dispatch_async(dispatch_get_global_queue(0, 0), ^{
sleep(8);
NSLog(@"任务二完成");
// 使信号的信号量+1,这里的信号量本来为0,+1信号量为1(绿灯)
dispatch_semaphore_signal(syncSemaphore);
});

// 开启信号等待,设置等待时间为永久,直到信号的信号量大于等于1(等绿灯)
dispatch_semaphore_wait(syncSemaphore, DISPATCH_TIME_FOREVER);
});


dispatch_group_notify(group, dispatch_get_main_queue(), ^{
//界面刷新
NSLog(@"任务均完成,刷新界面");
});
}

附:实际上,这段代码是一个常用的不控制并发数,只控制线程阻塞,实现线程同步的例子。在这里它是将等待信号dispatch_semaphore_wait放在线程执行后。往下看,待会会介绍控制并发数的例子。

上面例子中,先再任务1的线程里中再开启一个异步线程执行请求1,同时堵塞住此时的任务1所在的线程,等到已开始的异步请求1结束之后,恢复畅通,才代表任务1结束了。

3)、其他控制任务顺序的例子

附1:多个请求依次执行

例子:三个任务分别为下载图片,打水印和上传图片,三个任务需异步执行但需要顺序性。

对于这个问题通常会通过线程依赖进行解决。

  • 1、如果是GCD的话,设置线程依赖比较繁琐,所以这里就不讨论了。
  • 2、如果是NSOperation的话,我们直接通过addDependency来设置一个操作队列NSOperationQueue中的线程依赖就可以了。

代码如下(此例子不讨论线程里开线程,如果需要的话,请将信号量的使用添加上去即可解决):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 //1.任务一:下载图片
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
[self request_A];
}];

//2.任务二:打水印
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
[self request_B];
}];

//3.任务三:上传图片
NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
[self request_C];
}];

//4.设置依赖
[operation2 addDependency:operation1]; //任务二依赖任务一
[operation3 addDependency:operation2]; //任务三依赖任务二

//5.创建队列并加入任务
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperations:@[operation3, operation2, operation1] waitUntilFinished:NO];

四、多线程并发数控制

当我们在处理一系列线程的时候,当数量达到一定量,我们需要处理并发数控制。

  • 1、如果是GCD的话,怎么快速的控制并发呢?答案就是dispatch_semaphore。这个比较复杂,但我们这边还是谈一下
  • 2、如果是NSOperation的话,我们直接使用NSOperationQueue来控制并发,这个就不谈了。

GCD使用信号量dispatch_semaphore控制并发

说道信号量,这里顺便谈下信号量的概念:

信号量就是一个资源计数器,它是一个整形值并且具有一个初始计数值,并且支持两个操作:信号通知和等待。当一个信号量被信号通知,其计数会被增加。当一个线程在一个信号量上等待时dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);,线程会被阻塞(如果有必要的话),直至计数器大于零,然后线程会减少这个计数。

上面的例子中,信号量初始值为0,其先执行到dispatch_semaphore_wait,此时由于信号量为0,所以造成了阻塞,而使得线程1没能结束它的工作。而到线程1里的异步线程执行完后,给信号量发送了一个通知,使得信号量的值加上了1,此时刚才线程1里的dispatch_semaphore_wait发现信号量大于等于1了,它就不再阻塞,而是继续执行下去,从而使得了线程1这时候真正结束了它所应该处理的工作。wait执行完后,信号量又减1了。

也就是通过这种线程阻塞/等待的方法,我们实现了线程的同步。

当然信号量的用途,除了可以用来实现线程同步外,还可以用来实现控制GCD的并发数

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- (void)testBingfa {
// 创建队列组
dispatch_group_t group = dispatch_group_create();
// 创建信号量,并且设置值为10
dispatch_semaphore_t semaphore = dispatch_semaphore_create(10);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (int i = 0; i < 100; i++)
{ // 由于是异步执行的,所以每次循环Block里面的dispatch_semaphore_signal根本还没有执行就会执行dispatch_semaphore_wait,从而semaphore-1.当循环10此后,semaphore等于0,则会阻塞线程,直到执行了Block的dispatch_semaphore_signal 才会继续执行
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_group_async(group, queue, ^{
NSLog(@"%i",i);
sleep(2);
// 每次发送信号则semaphore会+1,
dispatch_semaphore_signal(semaphore);
});
}
}

比较这段代码与上面的代码,控制并发一般都是将等待信号dispatch_semaphore_wait放在线程执行前。而我们常用的只控制线程阻塞,实现线程同步的,都是将等待信号dispatch_semaphore_wait放在线程执行后。所以,如果一个多线程,它需要同时控制线程同步和线程并发数的话,那它就需要创建两个信号量来分别控制。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
- (void)testGroupSyncAndBingfa_semaphore_signal_wait {
dispatch_group_t group = dispatch_group_create();

// 创建一个控制线程并发的信号量,初始值为最大并发数2(红灯)
dispatch_semaphore_t bingfaSemaphore = dispatch_semaphore_create(2);

// 创建一个控制线程同步的信号量,初始值为0(红灯)
dispatch_semaphore_t syncSemaphore = dispatch_semaphore_create(0);

dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_semaphore_wait(bingfaSemaphore, DISPATCH_TIME_FOREVER); //并发信号

//请求1
dispatch_async(dispatch_get_global_queue(0, 0), ^{
sleep(5);
NSLog(@"任务一完成");
dispatch_semaphore_signal(syncSemaphore); //同步信号
});
dispatch_semaphore_wait(syncSemaphore, DISPATCH_TIME_FOREVER); //同步信号
});

dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_semaphore_wait(bingfaSemaphore, DISPATCH_TIME_FOREVER); //并发信号

//请求2
dispatch_async(dispatch_get_global_queue(0, 0), ^{
sleep(8);
NSLog(@"任务二完成");
dispatch_semaphore_signal(syncSemaphore); //同步信号
});
dispatch_semaphore_wait(syncSemaphore, DISPATCH_TIME_FOREVER); //同步信号
});

dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_semaphore_wait(bingfaSemaphore, DISPATCH_TIME_FOREVER); //并发信号

//请求3
dispatch_async(dispatch_get_global_queue(0, 0), ^{
sleep(6);
NSLog(@"任务三完成");
dispatch_semaphore_signal(syncSemaphore); //同步信号
});
dispatch_semaphore_wait(syncSemaphore, DISPATCH_TIME_FOREVER); //同步信号
});


dispatch_group_notify(group, dispatch_get_main_queue(), ^{
//界面刷新
NSLog(@"任务均完成,刷新界面");
});
}

通过所附加的两个例子,我们明显的看出NSOperation在处理线程依赖以及并发数的问题上,明显更高级。所以,如果有类似的问题,我们优先使用NSOperation来处理。

常见笔试/面试题

< 返回目录

1、在使用SQLite过程中,如果多条线程同时操作同一数据库会造成什么问题,怎么解决?

答:(1)容易造成系统崩溃
(2)解决方案:开启串行模式,使用一个类(单例方式)操作数据库。

END

< 返回目录

必备知识架构

知识架构

iOS知识库

Android知识库

目录

  • 十一、谈谈设计模式
  • 十二、如何优化过于臃肿的Controller
  • 十三、谈谈性能优化(功耗)
  • 十四、UITableView的优化、重用
  • 十五、布局 layoutsubview、drawrect等
  • 十六、有逼格的代码
  • 十七、单元测试
  • 十八、APP审核

  • 常见笔试/面试题

  • END

十一、谈谈设计模式

< 返回目录

十二、如何优化过于臃肿的Controller

< 返回目录
如何优化过于臃肿的Controller

十三、谈谈性能优化(功耗)

< 返回目录

UITableView的优化、重用

< 返回目录

布局 layoutsubview、drawrect等

< 返回目录

有逼格的代码

typedef NSString * NSRunLoopMode NS_EXTENSIBLE_STRING_ENUM;
提升自己逼格的编程之美之代码规范
iOS开发细节 | 通知怎么写?
实现NS_ENUM的自定义反射

单元测试

< 返回目录

APP审核

< 返回目录

如果一个页面被苹果拒回。那怎么通过审核。(参考金融类APP提交苹果审核,怎么避开5.2.1)

答:

1.第一种是有后台控制壳什么时候出现。移动端传一个版本号给后台,后台根据版本号判断App否在审核,在审核就显示壳,不在审核就显示原生界面。

2.直接由移动端来切换界面。此时App需要登录才能看到主界面,对给苹果审核人员的测试账号做一个判断,如果是测试账号,就显示壳,非测试账号显示原生界面。

其中:

第一种方式用户进来就可以看到主界面,更有利于吸引自然流量,但是如果苹果后期复查,发现了用户使用的App跟审核的不一样,会被下架。

第二种方式不利于吸引自然流量,但是被下架的风险很小,因为苹果的审核团队在美国,不可能自己去注册账号,复查也没关系,除非有人举报你的App。

常见笔试/面试题

< 返回目录

1、如何使用一个for循环输出九九乘法表

NSJSONSerialization
1
2
NSData *data = [operation.responseString dataUsingEncoding:NSUTF8StringEncoding];
NSMutableDictionary *responseObject_dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers | NSJSONReadingMutableLeaves error:nil];

//NSJSONReadingMutableContainers的作用: http://blog.csdn.net/chenyong05314/article/details/45691041

1
2
3
NSJSONReadingMutableContainers:返回可变容器,NSMutableDictionary或NSMutableArray。
NSJSONReadingMutableLeaves:返回的JSON对象中字符串的值为NSMutableString
NSJSONReadingAllowFragments:允许JSON字符串最外层既不是NSArray也不是NSDictionary,但必须是有效的JSON Fragment。例如使用这个选项可以解析 @“123” 这样的字符串。

iOS中常见Crash总结

END

< 返回目录

面试

自动打包

浏览器缓存、分段、

拉前端代码?+正常的环境的切换+通知

没网?数据?

h5请求,app拦截,自动更新

h5调用插件

多渠道打包

Cordova、

安全

支付:

架构 MVP

代码层面 hashMap 16大小、本地化存储 mmkv 门面模式

性能优化 线上oom、bugly、图片过大

Viewmodel 数据持久

不同客户不同包

网络框架 重试、日志

权限管理

离线缓存?

日历视图 七八层嵌套-> 1层

通知、插件、路由

插入视图

物联网

安卓自启动问题

本地化/国际化-

框架-getX

webView-flutter 白屏

扫码

设计模式?策略模式?单例?通知?几个原则。

  • 谈谈对项目做过的优化(历史存在什么问题,你的解决方式。)?
  • 谈谈你做过的框架(侧重非UI部分)
  • 谈谈埋点?

搜索逻辑?冒泡排序?

封装

看过什么书,什么三方库?

  • [x] 图片缓存?

  • [x] 性能优化(webView 优化)?

    • 内存优化、泄漏,检测?
    • 启动优化
    • 安装包大小优化
  • 应用在后台长时间执行(service 保活)
  • 怎么区分不同平台的安装包?
  • 同一应用多端,项目上怎么开发(司机端、乘客端)。
  • [ ] 路由设计 scheme://path?argument

  • [ ]

app中核心的非数据组件()

图片处理、网络库、路由

线程同步

掌握 RxJava + Retrofit + OkHttp 的⽹络底层框架,并结合 MVP、MVC、MVVM 三种架构模式编写出⽹络底 层框架,已应⽤于项⽬中,底层稳定性强

了解LiveData,Viewmodel,DataBinding等新框架,且结合RxJava 使⽤MVVM架构应⽤在项⽬中

理解内存泄露的原理,编写代码过程中能避免常⻅内存泄露。使⽤Memory Profiler 和 Memory Analyzer等 ⼯具检测内存泄露问题

了解App启动速度优化,内存,以及APK 瘦身等优化

理解 Android 适配原理,能够做到适配各类常⽤机型

理解Android触摸事件传递机制,⾃定义View和动画机制 理解 Handle 消息处理机制

理解多个设计模式的使⽤。如单例设计模式,观察者模式,建造者模式,装饰者设计模式等 独⽴编写多个lib库,如图库,列表适配库,⼴告库,分享库(QQ,微信,微博,Facebook等第三⽅),均采⽤ 组件化开发⽅式,可快速移植其他项⽬中

Flutter

状态管理 setState\Provider

网络拦截器、

图片缓存

请求

新电脑(Mac)初始安装

[TOC]

一、系统设置

  • [x] mac三指拖动设置

    1
    系统设置 --> 辅助功能 --> 鼠标与触控板 --> 触控板选项 --> 三指拖移
  • [x] mac显示隐藏文件

    1
    defaults write com.apple.finder AppleShowAllFiles -boolean true;killall Finder

二、搜狗输入法、QQ、微信、Wps

三、琐事记录&计划

1、开始记录各种琐事:个人博客Git

2、找到对应的文件:Alfred

3、编辑:Typora、SublimeText、截图xnip、翻译Bob、粘贴Paste

4、列计划:omniplan、Xmind

5、其他:Bartender

四、代码相关

1、Sourcetree、gitlab、github项目、ssh

  • [x] Sourcetree

  • [x] 生成ssh

    1
    2
    3
    4
    5
    6
    7
    # 查看是已有
    cd ~/.ssh

    # 没有则执行生成
    ssh-keygen

    # 生成后,拷贝id_rsa.pub中的秘钥到git的ssh配置中
  • [x] gitlab

  • [x] github

    mac中用sourcetree下载clone代码,结果出错:warning: templates not found in /usr/local/git/share/git-core/templates

    image-20201103134013411

    解决办法:

    1
    2
    sudo mkdir -p /usr/local/git/share/git-core/templates
    sudo chmod -R 755 /usr/local/git/share/git-core/templates

    image-20201103135013020

2、Cocoapods、Spec

  • [x] Cocoapods官网

    1、安装Cocoapods

    1
    sudo gem install cocoapods

    2、拷贝cocoapods的Spec

    1
    2
    3
    4
    pod repo # 找到pod库的路径
    cd 到上述路径
    拷贝cocoapods的Spec,并重命名该仓库名字
    pod repo update master # 将指定的仓库更新

3、go2sheell

五、iOS编码工具

1、Xcode

  • Xcode

2、CodeSnippets

1、进入 BlackMagic Git工程中的 CodeSnippets 并下载

2、CodeSnippets所在位置

①自己定义的代码块是在以下目录下:
~/Library/Developer/Xcode/UserData/CodeSnippets/

3、iSwift破解版

4、其他 cocoapods APP

六、Android

1、Android Studio

七、WebStrom

1、WebStrom APP

2、WebStorm细节配置

2.2、WebStorm配置直接运行RN项目

​ 具体操作请查看:ReactNative开发环境搭建与运行

八、抓包 Charles

  • Charles 下载

    进入百度网盘,搜索Charles,目前实用4.5.5版本

    Charles

  • Charles.md

九、brew、yarn、npm

  • [ ] brew

    1
    /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
  • [ ] yarn

    1
    brew install yarn
  • [ ] npm

  • [ ] wrap

十、个人娱乐类

十一、其他

1、APP网站macbl

2、APP安装问题