项目目录结构规范实践

[toc]

项目目录结构规范实践

步骤

1、项目目录结构分类与创建

2、

一、项目目录结构分类与创建

1、utils
2、models
3、commons

1、独立类(utils\models\common)的文件归类、迁移

1.1、库创建(0.5h)

1.2、文件归类与迁移(4h)

1、util

2、models

用户

序号 类型
1 用户
2 内容
3

1.3、内部的依赖修复与优化

内部引用优化为使用相对路径或新的绝对路径。

1
import './a.dart';

1.4、外部的使用优化

优化为

Step1:内部 export 各种文件

1
2
export './src/a.dart';
export './src/b.dart';

Step2:外部 import 基础类库的总文件

1
2
3
import 'package:app_utils/app_utils.dart';
import 'package:app_models/app_models.dart';
import 'package:app_common/app_common.dart';

2、通用组件类(commons)文件归类、迁移

1、内含适配组件 adapt

每个视图都需要依赖

2、基础用户头像、商品视图

依赖:基础的像素适配

入参:关键性参数及自定义的点击回调

附:升级版通用功能组件类common_ui(如用户头像、商品视图等),见下文。

3、基础路由(route)

4、升级版通用功能组件类common_ui(如用户头像、商品视图等)

以用户头像举例:

①需要支持传入baseUserModel的时候,显示头像信息

②需要支持传入baseUserModel的时候,点击跳转到对应用户详情页

所以需要依赖的有:

序号 需求 需要依赖 其他
1 需要支持传入baseUserModel的时候,显示头像信息 models
2 需要支持传入baseUserModel的时候,点击跳转到对应用户详情页 route

商品视图:

基础类空安全升级

依赖关系可视化

[toc]

依赖关系可视化

参考文档:

一、cocoapods依赖关系可视化

cocoapods管理的三方库之间有时候存在依赖关系,Podfile.lock藏满了各个版本库的版本号信息和彼此的依赖关系。

1、网页可视化导出:cocoapods-graph

终端安装插件:

1
pip install cocoapods-graph

使用方式:

进入到工程的根目录,执行:

1
2
3
cd ~/Project/CQComponent/UIKit-Overlay-iOS/TSOverlayDemo

cocoapods-graph -f Podfile.lock --html

生成 Podfile.lock.html 文件,

cocoapods-graph-01

其内容展示如下:

cocoapods-graph-02

2、图片可视化导出:cocoapods-dependencies

终端安装插件:

1
2
gem install cocoapods-dependencies
brew install graphviz

使用方式:

进入到工程的根目录,执行:

1
pod dependencies [PODSPEC] [--graphviz] [--image]
  • pod 是 CocoaPods 的命令行工具。
  • dependencies 是 CocoaPods 中的一个命令,用于显示特定 pod 或项目中所有 pod 的依赖关系。
  • [PODSPEC] 是一个可选参数,用于指定特定 pod 的名称。如果你提供了 pod 的名称,它将显示该 pod 的依赖关系。如果你没有提供 pod 的名称,它将显示项目中所有 pod 的依赖关系。
  • --graphviz 是一个可选标志,它会生成一个 Graphviz DOT 文件(一般为Podfile.gv),表示 pod 的依赖关系图。这个文件可以用于可视化依赖关系。
  • --image 是一个可选标志,它会从 Graphviz DOT 文件生成一个图像文件(一般为Podfile.png )。这样你就可以以图像格式查看依赖关系图。

示例1:不提供 [PODSPEC] 将显示项目中所有 pod 的依赖关系。

1
2
3
4
5
6
cd ~/Project/CQComponent/UIKit-Overlay-iOS/TSOverlayDemo

pod install

# 不提供 [PODSPEC] 将显示项目中所有 pod 的依赖关系。
pod dependencies --graphviz --image

生成 Podfile.gvPodfile.png文件如下:

cocoapods-dependencies-01-html

其中 Podfile.gv 可用 OmniGraffle应用程序 打开

gv的打开方式

打开方式说明如下:

序号 打开方式 打开说明 示例
1 Hieracchical 层次结构
2 Force-Directed 强制导向
3 Circular 圆形的
4 Radial 径向的

其各自详细效果图,详见 依赖关系可视化-TSOverlayDemo.graffle

示例2:提供 [PODSPEC] 将显示该 pod 的依赖关系

命令:pod dependencies AFNetworking --graphviz --image

这个命令将显示 AFNetworking 这个 pod 的依赖关系,并生成一个 Graphviz DOT 文件和相应的图像文件,用于可视化查看 AFNetworking 的依赖关系。你可以在生成的图像文件中查看依赖关系图。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 1、安装
gem install reversepoddependency

# 2、查找所安装库里的命令路径
gem which reversepoddependency
# gem which:这是一个用于定位 Ruby gem 安装路径的命令。当你执行 gem which GEM_NAME 时,它会返回指定 gem 的安装路径。
# which:这是一个用于查找可执行文件的命令。
# 得到的结果如下:
# /usr/local/lib/ruby/gems/3.2.0/gems/reversepoddependency-0.1.0/lib/reversepoddependency.rb
# 所以该包的 specbackwarddependency 应在如下目录:
# /usr/local/lib/ruby/gems/3.2.0/gems/reversepoddependency-0.1.0/
# 经查找 specbackwarddependency 的其实际地址为如下:
# /usr/local/lib/ruby/gems/3.2.0/gems/reversepoddependency-0.1.0/exe/specbackwarddependency

# 3、使用所安装库里的命令
/usr/local/lib/ruby/gems/3.2.0/gems/reversepoddependency-0.1.0/exe/specbackwarddependency ~/.cocoapods/repos/trunk AFNetworking

在运行 gem install reversepoddependency 命令后,安装的 reversepoddependency gem 应该会被存储在你使用的 Ruby 安装目录下的 Gems 文件夹中。

问题:执行 /usr/local/lib/ruby/gems/3.2.0/gems/reversepoddependency-0.1.0/exe/specbackwarddependency ~/.cocoapods/repos/trunk AFNetworking 时候出现如下错误:

specbackwarddependency_01

我们通过进入指定文件/usr/local/lib/ruby/gems/3.2.0/gems/cocoapods-core-1.12.1/lib/cocoapods-core/source.rb 查看其210行,并添加以下代码,即可过滤掉该库:

1
2
3
4
if name == "TUICalling" || name == "TUIChat" || name == "VK-ios-sdk" 
name = "AFNetworking"
version = "3.2.1"
end

specbackwarddependency_02

不然你得通过以下命令找到该所在库,然后再一个个删掉,这种方式会造成后续使用问题。所以我们选择修改判断代码

1
2
3
4
cd ~/.cocoapods/repos/trunk/Specs

# 查找指定库
find ~/.cocoapods/repos/trunk/Specs -name 'TUICalling'

添加代码后,重新执行

1
/usr/local/lib/ruby/gems/3.2.0/gems/reversepoddependency-0.1.0/exe/specbackwarddependency ~/.cocoapods/repos/trunk AFNetworking

得到的结果如下:

specbackwarddependency_03

End

网络扩展

[toc]

网络扩展

一、背景

TPFVPN

NetworkExtension2-Client开发

NetworkExtension3-Tunnel开发

NetworkExtension4-Server开发

NetworkExtension5-App和Extension通信

https://github.com/cgcym1234/YYVPN

移动/PC客户端流量拦截与转发

深信服移动终端EasyApp SDK介绍

其他github搜索结果:https://github.com/search?q=vpn+language%3AObjective-C+&type=repositories&s=stars&o=desc

其他文章:App extension实战 - NetworkExtension 讲解连接并捕获packet

End

网络ApiMock

[toc]

网络Api mock

一、背景

为了避免后端因为其他任务,来不及开发接口,特意建立mock环境,以此来保证后续出现类似情况,app也能够正常的开发,并能够在后端开发结束时候,快速完成整体的联调,从而在某个环节断档的情况下,也能够保证整体的进度。

二、功能介绍

  • 远程模拟
  • 本地模拟

三、远程模拟

1、远程界面样式

目前该环境,已对现有所有app接口实现mock。

image-20220119193932769

2、使用简介

2.1、修改地址

如果你已在api mock后台创建了模拟的接口,则只需要在项目中进行如下修改即可,其会自动将所请求的地址进行模拟。

1
2
3
4
static String getVirtualList = "/account/wallet/virtualAsset/page"

//模拟时候,在字符串尾部加上`.toSimulateApi()`即可
static String getVirtualList = "/account/wallet/virtualAsset/page".toSimulateApi();

2.2、修改mock数据

因为从Swagger同步过来的接口,其返回值不是完整的response结构。

完整的response={“code”:0, “msg”: “成功”, data:xxx};

同步的response=data

所以为避免每个接口都得重复的去添加response外层来调整结构,我们通过在本地网络上进行兼容,从而实现了即使你没对同步的接口进行操作,也能够直接调用请求,得到完整的数据结构。

四、本地模拟

1、使用简介

以模拟/account/wallet/wishStar/page接口为例

1.1、添加本地json

在项目中asset下的的data文件夹里添加该以请求路径命名的json文件。

image-20220322134145737

1.2、修改地址

将请求地址的尾部加上.toLocalApi(),即可自动将所请求的地址进行本地数据模拟。

1
2
3
4
static String wishStar = "/account/wallet/wishStar/page"; //愿望星流水明细

//模拟时候,在字符串尾部加上`.toLocalApi()`即可
static String wishStar = "/account/wallet/wishStar/page".toLocalApi(); //愿望星流水明细

####

_random.nextDouble() 获取的是0-1之间不为负数的小数

四舍五入

1
2
var foo = 6.28;
print(foo.round()); // 6

End

app发热问题

[toc]

app发热问题

其他参考文章:

CPU或GPU负荷过高是导致手机过度发热的主要原因之一,因此优化应用程序的CPU或GPU负荷是解决这个问题的关键。以下是一些常见的优化方法:

减少图形处理:如果您的应用程序涉及大量的图形处理,例如3D动画、特效等,可以尝试降低图形处理的质量或数量,以减轻GPU的负担。

优化算法和数据结构:通过优化算法和数据结构,可以减少CPU和GPU的计算量,从而降低负荷。例如,使用更高效的排序算法、数据缓存和内存管理等技术,可以提高应用程序的性能并减少计算量。

使用线程管理:使用线程管理技术可以将应用程序的不同部分分配到不同的线程中,从而减少CPU和GPU的负荷。例如,在主线程中处理用户界面,而在后台线程中处理数据下载和计算等任务。

延迟加载:延迟加载技术可以将应用程序的资源和数据分批加载,而不是一次性全部加载。这样可以减少CPU和GPU的负荷,同时也可以提高应用程序的响应速度和用户体验。

缓存数据:缓存数据可以减少应用程序对网络和磁盘的访问,从而降低CPU和GPU的负荷。例如,将数据缓存在内存中,而不是每次都从网络或磁盘中读取。

使用硬件加速:一些高端手机和平板电脑提供了硬件加速功能,例如GPU加速、硬件解码等。如果您的应用程序需要进行大量的图形或视频处理,可以考虑使用硬件加速来降低CPU和GPU的负荷。

离开web游戏页面停止计时器、停止渲染

调查:

直播的时候也热,正常性能消耗高
网络耗流量

原生交互?指引擎初始化?

CPU
渲染 GPU 图片批量处理,而不是单单
图片处理 图片大小。

接口:http - sockt
定时器个数、
循环精度、

iOS、Android webView的缓存大小

app内存问题

[toc]

app内存问题

一、如何排查内存问题

参考文章:

2内存-③内存泄漏定位.md

二、优化前后数据对比

时刻 目前情况 取消图片缓存扩容设置 去掉TTF文件初始化
打开APP时 img img img
滑动瀑布流 img img img
优化效果说明 优化后,在滑动瀑布流的时候,内存从原来的稳定1.24G,降低到稳定的896M 优化后,打开APP时,内存明显再降低了80M左右

问1:滑动过程中的突刺是什么操作产生?

问2:滑动过程内存增加用户操作是?增加后,内存增加到峰值就没增加的原因?如果估算峰值/峰值是该数值有计算方法?

问3:去掉ttf后,内存降低的数值怎么计算?是1:1的方式?

三、下载的内存分析和优化

以下载以下文件为例,

网络资源:https://media.xihuanwu.com/applet/wishhouse/reward/svga/rocket.svga (13MB)

序号 步骤 Dio 5.2.1
(Flutter)
HTTP 0.13.6
(Flutter)
OkHttp3 4.10.0
(Android)
0 未下载时 同左 同左
1.1 rocket.svga–13MB
下载过程峰值
1.2 rocket.svga–13MB
下载结束后置放
1.3 rocket.svga–13MB
下载结束后切换后台
1.4 rocket.svga–13MB
下载结束后切换后台回前台
2.1 rocket.svga–13MB
下载过程峰值
2.2 rocket.svga–13MB
下载结束后
3.1 rocket.svga–13MB
下载过程峰值
3.2 rocket.svga–13MB
下载结束后
4.1 rocket.svga–13MB
下载过程峰值
4.2 rocket.svga–13MB
下载结束后
5.1 rocket.svga–13MB
下载过程峰值
5.2 rocket.svga–13MB
下载结束后
884M
小结 在5次下载后,内存占用达到884MB,尝试将应用切换至后台、置放、手动GC,内存均无变化。①每次下载内存增加?②下载的内存并没有办法得到释放? 原来的触发下载改为此项后,内存无影响变化

结论:

​ 通过以上数据可以看出,Flutter实现在每次下载时,内存都发生了显著的上升,而原生实现表现平稳,在执行以上操作后,Flutter实现的内存占用达到了 884MB,而原生为 284MB,相比Flutter实现 少了600MB的内存占用。

建议将现有下载转为原生实现,从而降低资源下载时的内存使用。

ARC中方法创建的内存释放

1
2
3
4
5
6
7
8
- (void)exampleMethod {
// 创建一个局部对象,并且有一个强引用
NSObject *object = [[NSObject alloc] init];

// 做一些操作...

// 当对象离开作用域,强引用计数减1,如果为0,则对象被释放
}

@autoreleasepool中的内存释放

1
2
3
4
5
6
7
8
9
10
11
12
13
14
- (void)exampleWithAutoreleasePool {
// 进入一个自动释放池块
@autoreleasepool {
// 创建一个autorelease对象,它会被放入自动释放池中
NSObject *autoreleaseObject = [[NSObject alloc] init];

// 做一些操作...

// 当这个@autoreleasepool块结束时,autoreleaseObject会被释放
}

// 在自动释放池块外,尝试访问autoreleaseObject会导致崩溃,因为它已经被释放了
// NSObject *accessAfterRelease = autoreleaseObject; // 这将导致崩溃
}

第2节:Swift扩展(Extensions)

[TOC]

入门二

  • 一、Swift扩展(Extensions)

一、Swift扩展(Extensions)

Swift基础部门:http://www.swift51.com/swift4.0/chapter2/01_The_Basics.html

详见:http://www.swift51.com/swift4.0/chapter2/21_Extensions.html中的2.21扩展

在swift中extension(扩展)与Objective-C的category(分类/扩展/类别)有点类似,但是extension比起category来说更加强大和灵活,它不仅可以扩展某种类型或结构体的方法,同时它还可以与protocol等结合使用,编写出更加灵活和强大的代码。

二、

Swift3.0语法变化

swift 枚举的取值

Swift中协议的可选方法的实现判断

二、第三方库

OC第三方库需要在桥街文件中引入,swift第三方库需要import model方式引入!桥街文件不能引入swift第三方库

  • Network:

Alamofire:著名的AFNetworking网络基础库Swift版 - Alamofire/Alamofire · GitHub

SwiftyJSON:最为开发者认可的JSON解析类 - SwiftyJSON/SwiftyJSON · GitHub

  • Storage:

SQLite.swift:简单、轻量,使用上最SQL的SQLite封装库 - stephencelis/SQLite.swift · GitHub

SugarRecord:基于CoreData与REALM的好用封装 - SugarRecord/SugarRecord · GitHub

  • UI:

SweetAlert:带动画效果弹窗封装类 - codestergit/SweetAlert-iOS · GitHub

RAMAnimatedTabBarController:灵动的动画标签栏类库 - Ramotion/animated-tab-bar · GitHub

PNChart-Swift:带动画效果的图表控件库 - kevinzhow/PNChart-Swift · GitHub

LTMorphingLabel:各种文字动画效果 - lexrus/LTMorphingLabel · GitHub

Cartography:用代码解决麻烦的AutoLayout - robb/Cartography · GitHub

other:

pod ‘SVProgressHUD’

pod ‘MJRefresh’

pod ‘SnapKit’

Swift常用第三方库

2017最受欢迎的30个Swift 库,你关注到了吗?

Swift常用第三方库

基础知识

iOS 宏定义-获取状态栏、导航栏、tabBar高度

https://www.jianshu.com/p/801bdea428f8

image-20201121001108987

1
2
3
4
5
6
7
let screenHeight = UIScreen.main.bounds.size.height
let statusBarHeight = UIApplication.shared.statusBarFrame.size.height
let navigationBarHeight = self.navigationController?.navigationBar.frame.size.height ?? 0
let tabbarHeight = self.tabBarController?.tabBar.frame.height ?? 0
let screenWidth = UIScreen.main.bounds.size.width
let iphoneX = screenWidth >= 375.0 && screenHeight >= 812.0
let bottomGuideHeight: CGFloat = iphoneX ? 34 : 0