Git Permission

一、git分支添加访问权限

image-20220303102746825

二、Gitlab仓库管理 设置保护分支

设置保护分支

把认为哪个个分支不想让别人动,就把这个分支设置为保护分支,并且只有授权的用户才可以向这个分支推送代码

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

[toc]

目录

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

< 返回目录

Bugly

一、iOS 崩溃

1、崩溃信息

【全部】崩溃信息截图如下:

image-20230526150407119

2、分析

image-20230526163957707

问题id 问题描述 发生次数
#1038 SIGSEGV 腾讯播放器问题 236
其他 其他问题 7

腾讯播放器占比超95%,已修复,待上线。

二、Android 崩溃

1、崩溃信息

image-20230526150921436

2、分析

image-20230526164207063

模拟器相关 43+/72 > 60%

即至少能再降低60%崩溃率。

三、iOS Flutter错误

1、错误信息

image-20230526151515956

1、分析

image-20230526165153853

与游戏webView相关的异常错误达 7000+/8000 > 87.5%。

原因:app调用游戏webView提供的js,h5那边返回了不支持的类型。

影响:只是异常错误,实际无业务影响。

即处理后能降低 87.5%,预计为 5.08% = 12.5% * 40.66%

四、Android Flutter 错误

1、错误信息

image-20230526165814931

2、分析

image-20230526170106312

已处理 524+ / 1200 ≈ 43.7%

五、小结

描述 新百分比 旧百分比 旧主要问题 旧非主要问题
时间 05-31 -> 10.31 2023-05-26 2023-05-26 2023-05-26
iOS崩溃 0.419%->5.09‱ 2.70 % 2.565%:95%腾讯播放器 0.135%
Android崩溃 0.478%->3.60‱ 1.51% 0.910%:60%+模拟器 0.6%
iOS错误 40.66% 34.58%:> 87.5% webView游戏 5.08%
Android错误 4.93% 10.59% 4.530%:类型或退出异常,已处理43.7% 6.06%

End

游戏通讯协议的选择TCP?UDP?HTTP?WebSocket?

二、协议选择

通过以上对协议特性分析,我想大家心里已经有低儿了。根据小编的工作经验以及对游戏理解,有以下建议:

1、对于弱联网类游戏,必须消除类的,卡牌类的,可以直接HTTP协议,考虑安全的话直接HTTPS,或者对内容体做对称加密;

2、对于实时性,交互性要求较高,且team有过相关经验,可以优先选择websocket,其次TCP协议;

3、对于实时性要求极高,且可达性要求一般可以选择UDP协议;

4、局域网对战类,×××类,直接来UDP协议吧(公网对战,P2P的UDP还得“打洞”处理,后面分享会讲到)

其他无关

#8030 SIGTRAP(TRAP_BRKPT)

image-20230524132453348

主要原因:Webview渲染线程导致APP崩溃

发生次数:4

#8002 SIGTRAP #4002 SIGABRT #6040 SIGABRT #4028 SIGABRT #2038 SIGABRT

分析原因:用户使用的是Android模拟器,具体版本为Android模拟器Android 7.1.2,level 25,CPU架构为x86、x86_64,设备ROOT占比100%

发生次数:84+5+8

#5008 SIGABRT

分析原因:在分析崩溃日志时,发现每次发生此项崩溃是在用户从后台返回前台时

发生次数:11 (只在 redmi note 8 pro机型有上报此项错误)

#3032 SIGABRT

分析原因:SIG是信号名的通用前缀。ABRT是abort program的缩写。当操作系统发现不安全的情况时,它能够对这种情况进行更多的控制,必要的话,它能要求进程进行清理工作。在调试造成此信号的底层错误时,并没有什么妙招。 如 cocos2d 或 UIKit 等框架通常会在特定的前提条件没有满足或一些糟糕的情况出现时调用 C 函数 abort (由它来发送此信号)。

发生次数:7

#10 java.lang.NullPointerException

Attempt to invoke virtual method ‘io.flutter.plugin.common.PluginRegistry$RequestPermissionsResultListener com.lyokone.location.FlutterLocationService.getServiceRequestPermissionsResultListener()’ on a null object reference

分析原因:百度定位库在调用了空对象的方法,引发空指针问题。

发生次数:5

#3034 SIGSEGV(SEGV_MAPERR)

#03 pc 0000000000129d48 /vendor/lib64/egl/libRBGLESv2_adreno.so (rb_perform_resolve+616) [arm64-v8a::d49019399b6d1ce7075020c1e441c844]

分析原因:这是一个与SIGSEGV (Segmentation Fault)错误相关的错误消息。它指示在运行时出现了一个段错误,也称为内存访问错误。在您提供的错误消息中,指出错误发生在libRBGLESv2_adreno.so库的rb_perform_resolve函数中。libRBGLESv2_adreno.so是Qualcomm Adreno GPU驱动程序中的库文件。Adreno是Qualcomm开发的一系列图形处理器(GPU),广泛用于移动设备和嵌入式系统中。该库提供了OpenGL ES 2.0(Embedded Systems)的实现,允许应用程序在使用Adreno GPU的设备上进行图形渲染和加速。

在bugly日志上显示出现上述错误线程为Chrome_InProcGp线程,Chrome_InProcGp 线程是Webview其中一个处理渲染和绘图任务的线程。它负责管理和执行网页内容的呈现、布局和绘制操作,包括处理 HTML、CSS 和 JavaScript,解析页面内容并生成可视化的渲染结果。

发生次数:8 影响设备:2

#4102 SIGSEGV(SEGV_MAPERR)

分析原因:发生崩溃线程为Chrome_InProcGpuThreadChrome_InProcGpuThread 是 Chrome 浏览器中的一个线程,它是与 GPU 相关的线程之一。在 Chrome 的多进程架构中,GPU 线程用于处理图形渲染和加速,以提供流畅的图形显示和动画效果。

发生次数:5 影响设备:1 系统版本:Android 6.0.1,level 23

问题编号 发送次数 影响设备 备注
#12004 23 14 已修复
#9075 7 1 模拟器
#8088 6 1 模拟器
#2038 4 2 模拟器
#3034 3 1 模拟器
#2110 2 1
#5008 2 1
#8020 2 2
#10057 1 1
#10 1 1
其他 21 - 其他发送次数为1,影响设备为1的问题
汇总 72
模拟器 288->20 27.7%
已修复 23 31.9%
其他 29 40.2%

iOS bugly 崩溃

img

img

img

img

这个问题已于 4.20 提交工单,工单多次反馈已修复问题,多次升级sdk均未解决问题。

5.9重新提交工单,并投诉。自行在愿望屋app1.2.0版本hook仓储,对此方法添加容错处理,未生效。

img

工单记录

img

img

img

image-20230524132704989

上架-app链接

如何获取安卓应用下载地址

小米:

1
https://account.xiaomi.com/fe/service/login/password?_group=DEFAULT&_locale=zh_CN&sid=mideveloper&qs=%253Fcallback%253Dhttps%25253A%25252F%25252Fdev.mi.com%25252Fsts%25253Fsign%25253DKQKR691zSy1QUnqOYiKUx55Ei%2525252Fc%2525253D%252526followup%25253Dhttps%2525253A%2525252F%2525252Fdev.mi.com%2525252Fcallback%2525253FcallbackUrl%2525253Dhttps%252525253A%252525252F%252525252Fdev.mi.com%252525252Fplatform%2526sid%253Dmideveloper%2526_locale%253Dzh_CN%2526_group%253DDEFAULT&callback=https%3A%2F%2Fdev.mi.com%2Fsts%3Fsign%3DKQKR691zSy1QUnqOYiKUx55Ei%252Fc%253D%26followup%3Dhttps%253A%252F%252Fdev.mi.com%252Fcallback%253FcallbackUrl%253Dhttps%25253A%25252F%25252Fdev.mi.com%25252Fplatform&_sign=mPPUj2hILAeuPLjxfMpO%2FQwt1Gw%3D&serviceParam=%7B%22checkSafePhone%22%3Afalse%2C%22checkSafeAddress%22%3Afalse%2C%22lsrp_score%22%3A0.0%7D&showActiveX=false&theme=&needTheme=false&bizDeviceType=

上架-发版频率

和他们沟通了下,以后发布定在每周一。另外和测试那边说的如果在周四结束功能需求还没在测试环境验证通过,未避免在生产上回归出现问题,导致周一的发版太紧凑,会当那个需求要放在下下个版本。这样大家节奏会松点。

所以。强调,自己重要的问题,一定得及时和测试沟通,让他们提前测好。不要临时出问题,赶得来不及,上又上不了。
强调,自己重要的问题,一定得及时和测试沟通,让他们提前测好。不要临时出问题,赶得来不及,上又上不了。

[toc]

上架-提审前的自检

参考文档:

前言

1、常见问题类型

  • 隐私、权限的使用或声明
  • 登录
  • 版本检查
  • 黑名单
  • 无关h5网页
  • 内购

2、常见问题举例

背景/场景 被拒原因 解决
1.1 Android用户点击同意协议 同意用户协议前,提前获取了应用的设备信息、初始化了其他sdk 所有三方信息及sdk的初始化都放在同意协议之后
1.2 提供同城附近功能 提前使用位置 在调用的时候,才去申请位置权限
1.3 剪切板 未声明 已声明,误判,申述
1.4 获取安装列表 数美、同盾风控SDK调用 移除获取
2 使用微信、一键登录等三方登录 有三方,则一定要有苹果登录 审核期间隐藏三方登录入口
3 添加了蒲公英的版本检查 内部出现了,跳转到pgyer.com的功能 移除pgyer相关内容
4 app中的用户可创建内容,并进行朋友圈式传播 A mechanism for users to block abusive users 提供①拉黑用户;②内容举报功能,并告知其入口位置
5.1 app中需要嵌入一个h5 游戏,用来给app拉新。 提示游戏与app无太大关系。 审核期间隐藏各种入口,重提一个包
5.2 为推广,app推广图里,加入了游戏视图,而游戏本身被拒 app里隐藏了游戏, 告知其确实误操作上传了一张截图,其中的内容还没有上线。
5.3 app隐藏了游戏,游戏的获利,却出现在了流水功能中。 需告知①怎么获取,②怎么使用 告知是脏数据
6.1 app提供会员功能,会员需要充值 充值不是使用in-app purchase 为该账号重置,告知其已调整为免费使用

开发流程-提审前自检

3、审核失败的报告示例

一、隐私协议

修改建议:请确保应用内包含的所有SDK均已在应用内的隐私政策/在AppGallery Connect上提交的隐私政策内逐一罗列明示,

说明SDK收集使用的个人信息以及使用目的。请排查应用内包含的所有SDK,井在隐私政策内进行规范化的说明,以保证隐私检
測准确性。

1、微信SDK

Android接入指南 中的 《微信Open SDK个人信息处理规则》 提到如下内容:

1.1.4 前述关于收集、使用个人信息的内容适用于iOS及Android系统。

1.1.5 特别说明,在Android系统中我们会验证用户设备上安装微信APP的状态,用于确认该设备是否能够实现Open SDK的相关能力,如设备上未安装微信APP,用户将无法使用微信Open SDK能力所实现的相关功能。

所以,微信SDK也要补充获取应用的权限。

2、风控SDK

问题1:

经检测发现,您的应用中集成了”com.ishumei(数美;数美反作弊)”等SDK,但未在应用内的隐私政策/在AppGallery Connect
上提交的隐私政策内容中进行明示,不符合华为应用市场审核标准。

解决:补充隐私协议

问题2:

1.您的应用首次运行时,在展示使用权限对应的柏关产品或服务之前,提前向用户弹奇申请开后【已安装应用列表】权限,不符台华为应用市场南核标准。
测试步骤:首次打开APP,进行功能换作前,应用弹奇丰请开启【己安装应用列表】权限。
修改建议:应用如需丰请权限,应在用户使用对应业务功能时丰请,不得提前弹窗丰清权限,旦权限丰请行为需与实际使用目的一致。

解决:升级或配置来移除获取安装列表的功能

3、支付SDK

经检测发现,您的应用中集成了“com.alipay(支付宝;mPaaS;阿里乘车码;阿里芝麻信用实名认证;芝麻认证), com.sensorsdata.analytics(SensorsAnalytics;神策)”等SDK,但未在应用内的隐私政策/在AppGallery Connect上提交的隐私政策内容中进行明示,不符合华为应用市场审核标准。

解决:申述:

已跟技术排查应用内包含的所有SDK,核实愿望屋应用中并未集成com.alipay SDK。可能相关的两个地方:
1、支付宝支付,是用H5的方式调用支付宝客户端进行支付,并未获取用户任何权限和用户隐私。
2、阿里云金融级实人认证SDK,均已在应用内的隐私政策/在AppGallery Connect上提交的隐私政策内逐一罗列明示,并说明SDK收集使用的个人信息以及使用目的。
符合《审核指南》第7.2相关审核要求:
7.2 应用的隐私政策链接指向的隐私政策应当包含应用程序(包括委托的第三方或嵌入的第三方代码、插件)收集和使用个人信息的目的、方式和范围。
麻烦审核人员进行复合上线。 如有问题,随时沟通。谢谢~

4、剪切板权限

经检测发现,您的应用存在收集用户的个人信息或权限的行为(获取剪切板个人信息),但未在应用内的隐私政策/在AppGallery Connect上提交的隐私政策网址中进行说明。
修改建议:请在应用内的隐私政策/在AppGallery Connect上提交的隐私政策网址中,对应用所收集个人信息的目的、方式、范国进行说明。

解决:

5、AndroidID

容易出现的地方:网络库中的header添加deviceId

二、登录、审核账号

您的应用提供的测试帐号和密码无法正常登录应用,应用内实际只有微信登录方式(提示密码错误),不符合华为应用市场审
核标准,
修改建议:请提交应用时,在”应用审核信息”选项中提供有效的测试帐号和密码。
请参考《审核指南》 第1.21相关审核要求:https:/developer.huawei.com/consumerlcn/doc/50104

原因:风控限制(一台设备只能登录三个账号)、白名单未真的白,还存在某些限制

解决:白名单真的白。

三、版本检查

1、pgyer.com

2.1、Specifically, your app uses the itms-services URL scheme to connect to pgyer.com, which may allow for installations or updating of the app.

Guideline 2.5.2 - Performance - Software Requirements

During review, your app installed or launched executable code, which is not permitted on the App Store. Specifically, your app uses the itms-services URL scheme to connect to pgyer.com, which may allow for installations or updating of the app.

The next submission of this app may require a longer review time, and this app will not be eligible for an expedited review until this issue is resolved.

Next Steps

- Remove any reference to itms-services URL schemes from your app.
- Review the Software Requirements section of the App Store Review Guidelines.
- Ensure your app is compliant with all sections of the App Store Review Guidelines and the Terms & Conditions of the Apple Developer Program.
- Once your app is fully compliant, resubmit your app for review.

Submitting apps designed to mislead or harm customers or evade the review process may result in the termination of your Apple Developer Program account. Review the Terms & Conditions of the Apple Developer Program to learn more about our policies regarding termination.

2.2、Guideline 2.5.2 - Performance - Software Requirements

During review, your app installed or launched executable code, which is not permitted on the App Store. Specifically, your app uses the itms-services URL scheme to connect to pgyer.com, which may allow for installations or updating of the app.

The next submission of this app may require a longer review time.

Next Steps

- Remove any reference to itms-services URL schemes from your app.

- Review the Software Requirements section of the App Store Review Guidelines.

- Ensure your app is compliant with all sections of the App Store Review Guidelines and the Terms & Conditions of the Apple Developer Program.

- Once your app is fully compliant, resubmit your app for review.

Submitting apps designed to mislead or harm customers or evade the review process may result in the termination of your Apple Developer Program account. Review the Terms & Conditions of the Apple Developer Program to learn more about our policies regarding termination.

四、UGC黑名单

3、Guideline 1.2 - Safety - User Generated Content

Guideline 1.2 - Safety - User Generated Content

We found in our review that your app includes user-generated content but does not have all the required precautions. Apps with user-generated content must take specific steps to moderate content and prevent abusive behavior.

Next Steps

To resolve this issue, please revise your app to implement the following precautions:

- A mechanism for users to block abusive users

五、h5 game

Guideline 4.7 - Design - HTML5 Games, Bots, etc.

We noticed that your app offers HTML5-based games, but the games appear to be an incidental feature that do not deeply enhance or enrich the user’s experience.

Next Steps

To resolve this issue, please remove any HTML5-based games from your app that are not directly related to your app’s core functionality.

Please see attached screenshots for details.

背景:

app中需要嵌入一个h5 游戏,用来给app拉新。

被拒原因:

提示游戏与app无太大关系。

六、内购(会员)

3、in-app purchase

Guideline 3.1.1 - Business - Payments - In-App Purchase

We noticed that your app includes or accesses paid digital content, services, or functionality by means other than in-app purchase, which is not appropriate for the App Store. Specifically:

- The VIP can be purchased in the app using payment mechanisms other than in-app purchase.

回复:

尊敬的审核人员您好: 根据上一次反馈的审核意见,我们已经做出了整改 1、涉嫌App内购的会员付费业务,我们目前调整为上线免费赠送,不提供购买入口 2、涉嫌跳转其他App的问题我们也已经做出了修正,目前不需要其他App也可正常完整的使用愿望屋App 以上,请审核人员审核,致谢

End

ChatGPT 串接到 Discord

[TOC]

ChatGPT 串接到 Discord - 团队协作好助理

  1. 进入 replit
  2. 直接用 Github 帐号登入并授权

3、获取API secret 并设置

获取 Secret

https://platform.openai.com/settings/organization/api-keys

image-20241101213456012

更新 Secret

image-20241101215108741

二、运行到

点击 RUN 按钮运行后,发现缺失部分Python包。

1、运行过程中的问题修复

解决如下:🛠️ 如何在replit中安装其他Python包?

1
2
3
4
pip install python-dotenv
pip install discord
pip install openai
pip install flask

image-20241101210749231

2、运行成功

执行完后再点击运行,得到

image-20241101211520003

⚠️ 若一小时内没有任何请求,则程式会中断,因此需要下步骤

三、定时发送请求,来保活

CronJob 定时发送请求

  1. 注册/登入 cron-job.org

出现 AttributeError: module 'openai' has no attribute 'ChatCompletion' 这个错误的原因是因为您尝试使用的 openai.ChatCompletion.create 方法在 openai 模块中不存在。这是因为 OpenAI 的 Python SDK 中正确的属性名称是 openai.Completion,而不是 openai.ChatCompletion

您应该使用 openai.Completion.create 方法来替代 openai.ChatCompletion.create

image-20241101224416466

ChatGPT 注册及基础使用

[TOC]

ChatGPT 注册及基础使用

一、ChatGPT的注册与使用

1、ChatGPT的注册

1、网址:https://chat.openai.com/

image-20230312192000315

如出现

image-20230315002540003

请将使用全局代理,并将节点从新加坡换成美国,显示正常。

image-20230312203356915

继续

image-20230312193957401

需要手机号码

image-20230312194026961

2、国外手机号验证码的获取

详见:科学上网_SMS

We’ve detected suspicious behavior from phone numbers similar to yours. Please try again later or contact us through our help center at help.openai.com.

注册成功的结果:

image-20230312201155525

进入后显示:

image-20230312203247171

3、ChatGPT的使用

①需先添加api-keys

Incorrect API key provided: undefined. You can find your API key at https://platform.openai.com/account/api-keys.

image-20230312202200091

进入指定页面”Create new secret key”

image-20230312202641668

创建后,显示如下:

image-20230312202720126

Default organization不用修改。

image-20230312203152634

②添加完后,即可正常请求了

之后我们再次输入,则能正常请求了:

image-20230312204207388

第2节:沙盒数据分析

[toc]

iOS-沙盒数据分析

由前一节沙盒数据查看,我们已经得到了沙盒数据了。接下来就是数据分析了。

一、沙盒目录认识

1.Documents:

  用户生成的文件、其他数据及其他程序不能重新创建的文件,iTunes备份和恢复的时候会包括此目录。

2.Library/Caches:

  可以重新下载或者重新生成的数据,数据库缓存文件和可下载内容应该保存到这个文件夹,iTunes不会备份此目录,此目录下文件不会在应用退出删除。

3.tmp:

  只是临时使用的数据,iTunes不会备份和恢复此目录,此目录下文件可能会在应用退出后删除。

二、沙盒WebKit缓存

参考文章:WKWebView 缓存策略

End