Markdown基础语法

[TOC]

参考文章:

锚点

详情查看:附一:StateEasyPage.js 与 StateNormalPage.js

折叠

1、语法代码:

基础语法:

1
2
3
4
<details>
<summary>测试的简要标题</summary>
测试的详细内容
</details>

加工语法:

1
2
3
4
5
6
7
8
<details>
<summary><mark><font color=darkred>点击查看详细内容</font></mark></summary>
<p> - 测试 测试测试</p>
<pre><code>
for i in a:
print(i)
</code></pre>
</details>

2、上述语法代码效果展示

  • 代码块1的效果


  • 测试的简要标题
    测试的详细内容
  • 代码块2的效果


  • 点击查看详细内容

    - 测试 测试测试



    for i in a:
    print(i)

3、自己常用

附一:StateEasyPage.js 与 StateNormalPage.js

开发工具的安全性保障

[toc]

项目安全

一、开发工具

附:《开发工具.md

开发工具安全性处理

1、(基础)入口隐蔽

2、(进阶)设置密码:build号(2011021000 即20年 11.02 10:00),并允许后台强制修改密码

3、(保障)升级时候,缓存的显示开发工具按钮失效:缓存的key,增加版本号

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
// 悬浮按钮 DevToolManager
String _app_drag_floating_button_key = "_app_drag_floating_button_should_show_${version}" // 当前版本悬浮按钮显示态
bool showFloatingDevButton = await SharedPreferences.getInstance().getBool(_app_drag_floating_button_key);


// 开发工具入口按钮 DevEntranceView
buildUI() {
bool _findEnterUI = false; // 页面全局变量,是否发现了入口

bool needAuth = !productEnv;
if (!needAuth) {
return 直接显示入口,且入口为"定制开发工具按钮",点击可直接进入开发工具页面
}

if (_findEnterUI) {
return "验证码输入框+进入页面的按钮"
}

// 提供一个隐藏区域,供用户长按来显示入口
return GestureDetector(onLongPress:() {
_findEnterUI = true;
});
}

getPd() async {
GlobalOtherConfig? otherConfigModel = GlobalConfig.otherConfig();
if (otherConfigModel != null && otherConfigModel.toolPasd != null && otherConfigModel.toolPasd!.isNotEmpty) {
_password = otherConfigModel.toolPasd;
} else {
PackageInfo packageInfo = await PackageInfo.fromPlatform();
_password = packageInfo.buildNumber;
}
}

End

混编事项说明

[toc]

混编事项说明

一、事项简述

混编

二、混编工程搭建

1、项目本身重构,实现原生混编前提—原生包Flutter

Flutter项目降级成模块,作为原生部分。

  • 抽离原生部分,Flutter项目降级成模块:原生项目外移,与Flutter项目同层。
  • 修改原生模块依赖配置文件Podfile,引入降级后的Flutter模块。

2、引擎处理

目的:混合栈引擎共享

方案一:使用flutter_boost

  • flutter_boost 接入

3、验证接入效果

3.1、验证跳转

三、混编下缓存数据共享

1、Flutter下的SharedPreferences

2、iOS下的UserDefaults

3、Android下的sharedPreferences

四、混编下的路由跳转

1、Flutter下的 fluro

2、iOS下的 CTMediator

3、Android下的 ARouter

1、原生路由实现

2、Flutter路由和原生路由的交互跳转

五、混编下的打包

1、混编下的打包环境变量的修改

六、生命周期修改

原因: Flutter 的 WidgetsBindingObserver RouteAware 失效,必须使用混编下(如FlutterBoost)的生命周期,很多业务需要重新修改确认。

七、混编下的图片资源共享

核心:各平台图片库的图片存储和获取位置自定义

1、Flutter下的 extended_image

2、iOS下的 SDWebImage

3、Android下的 glide

八、组件

1、网络数据共享

1、Flutter上的 dio

2、iOS上 Swift 的 AlamofireOC 的 AFNetworking

3、Android上的 OkHttp

Android主流网络请求开源库的对比(Android-Async-Http、Volley、OkHttp、Retrofit)

网络的重试、缓存

2、图片库

见上文《图片资源共享》部分

3、其他三方库

火山、buglgy、地图等 — 不用重新做

4、UI基础组件

5、开发工具

5.1、日志系统

自定义的监控系统

九、桥接—-Flutter方法

image-20241111154605819

End

工作记录

[toc]

工作记录

1、办公设备及环境搭建与配置

1、按照 《新电脑初始安装》,完成办公设备及环境搭建与配置

2、项目熟悉

如何快速的熟悉一个iOS开发项目?

以实际运行项目,

  1. 阅读项目文档
    • 查看项目README文件,了解项目的基本信息和构建指南。
    • 查找任何现有的开发文档、设计文档或技术规范。
  2. 设置开发环境
    • 确保你的开发机器上安装了所有必要的工具,如Xcode、Git等。
    • 克隆代码仓库到本地,并尝试构建和运行项目。
  3. 理解项目结构
    • 浏览项目的目录结构,了解各个模块和组件的组织方式。
    • 查看项目中的.xcodeproj.xcworkspace文件,了解项目配置和依赖。
  4. 分析代码
    • 从主应用程序入口点(通常是AppDelegateSceneDelegate)开始,跟踪程序启动流程。
    • 查看主要的视图控制器(ViewController)和视图模型(ViewModel),理解它们的作用和交互方式。
    • 阅读关键类和协议的定义,了解它们如何协同工作。
  5. 运行和测试
    • 在模拟器或真机上运行项目,亲自体验应用的功能。
    • 执行现有的单元测试和UI测试,了解项目的测试覆盖情况。

3、熟悉工作流程

  1. 代码审查
    • 如果项目中有代码审查(Code Review)流程,阅读最近的提交和变更,了解代码的演进历史。
    • 通过代码审查,你可以学习到项目中的最佳实践和编码风格。
  2. 使用版本控制系统
    • 熟悉Git(或其他版本控制系统)的使用,了解如何提交更改、查看历史记录和分支管理。
  3. 与团队沟通
    • 与项目团队成员交流,了解他们的工作和项目中的关键点。
    • 询问项目中遇到的问题和解决方案,以及任何未文档化的实践。
  4. 探索项目的CI/CD流程
    • 了解项目的持续集成和持续部署流程,包括任何自动化测试和构建脚本。
  5. 实践和迭代
    • 在理解了项目的基础上,尝试添加一些简单的功能或修复一些小问题。
    • 通过实践来加深对项目的理解,并逐步承担更多的责任。
  6. 保持好奇心和耐心
    • 对于复杂的项目,不要期望一下子就能完全掌握。
    • 保持好奇心,不断提问和探索,随着时间的推移,你会逐渐熟悉项目。

【BugFix】修复 Pod 中缺失 LayerEffectNode 等文件导致的工程编译失败的问题

iOS appstore无沙盒账号登录选项

解决方案: 手机运行内购程序会出现登录沙盒账号页面。进行登录沙盒账号后,手机系统appstore就会出现沙盒账号登录选项了。

01.01-01.31

  • 应用内图片组动画大小未适配

  • 壁纸cell宽度计算未向下取整

End

账号管理

[toc]

账号管理

前言:主要账号

序号 分类 使用的功能 账号 登录方式 所有人 联系方式 是否独有
1 苹果开发者账号 iOS开发、发布 账号、密码
2 微信开放平台) 微信登录、分享、支付
3 极光一键登录) 一键登录验证(验证码在腾讯云)
4 百度地图) 定位功能
5 Bugly 崩溃、卡顿

苹果开发者证书

p12 证书文件 及 mobileprovision 描述文件的管理:见 《iOS证书

一、苹果开发者账号

苹果设备注册管理.md

1、苹果开发者设备

因苹果设备每年只能添加100台,且即使删除后也是当做一台设备。所以请真正有需要的用户才提交申请。

如需申请,请填写表:

序号 用户类型 姓名 udid 机型
1 开发者 Qian iPhone12 Pro
2 测试人员
3 产品人员
4 内测用户

附、udid获取方式

方式1、请自行使用浏览器进入蒲公英的一键获取udid工具

方式2、直接扫码获取

image-20230508153431432

二、Bugly

官网:https://bugly.qq.com/

姓名 Bugly 其他

Id获取方式如图:

image-20230508134738713

End

其他数据结构规范

[toc]

数据结构规范–消息

一、推送消息规范

推送模拟参考::《iOS进阶_推送模拟》

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
"code": 0,
"message": "success",
"result": {
"msgType": 1,
"msgDes": "金豆消息(对msgType的描述)",
"msgData": {
"msgId": "1234567890",
"msgTitle": "金豆消息标题",
"msgContent": "金豆消息内容",
"msgImage": "http://www.baidu.com/xxx.jpg"
},
"msgOnTap": {
"action_type": "route",
"action_name": "发布内容",
"action_value": "appScheme://xxx"
}
}
}

msgOnTap:代表点击该按钮需要进行的操作。

点击规范请查看:《路由规范(含点击属性规范).md)》

二、聊天消息规范

建议与推送消息结构完全一致,至少与推送消息中的result一致。

End

其他数据结构规范

[toc]

数据结构规范–卡片

一、内容卡片规范

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
[
{
"cardType": "content",
"contentCard": {

},
"userCard": {

},
"bannerCards": [

]
},
{
"cardType": "user",
"contentCard": {

},
"userCard": {

},
"bannerCards": [

]
},
{
"cardType": "banner",
"contentCard": {

},
"userCard": {

},
"bannerCards": [

]
}
]

2、需求1:长按卡片,弹出反馈列表。

分析:因为同一个卡片在不同业务页面,不一定都可以进行反馈,所以需要提前知道每个卡片在不同业务页面是否可以进行反馈,甚至是知道可以进行哪些反馈选项操作。

方案1:提前知道每个卡片在不同业务页面是否可以进行反馈。

后台数据返回

1
2
3
4
"canNegativeCardTypes": [
"mallHomePage#cardType_content",
"mallHomePage#cardType_user"
]

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
void longPressCard() {
var cardType = "content";
var position = "mallHomePage";
var flag = "$position#cardType_$cardType"
bool canNegative = canNegativeCardTypes.contains(flag);
if (!canNegative) {
return; // 不用相应
}

List<NegativeModel> negativeModels = await request(Url, {flag: flag});
showNegativeList(negativeModels);
}

方案2:提前知道每个卡片在不同业务页面可以进行哪些反馈选项操作。

后台数据返回

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
"negativeFeedbackConfig": {
"mallHomePage": {
"cardType_content": [
{
"image": "xxx.png",
"text": "不喜欢该内容",
"negativeId": 1
},
{
"image": "xxx.png",
"text": "不喜欢该作者",
"negativeId": 2
},
{
"image": "xxx.png",
"text": "举报",
"negativeId": 3
}
],
"cardType_user": [
{
"image": "xxx.png",
"text": "不喜欢该作者",
"negativeId": 2
},
{
"image": "xxx.png",
"text": "举报",
"negativeId": 3
}
],
}
}

代码实现

1
2
3
4
5
6
void longPressCard() {
var cardType = "content";
var position = "mallHomePage";
List<NegativeModel> negativeModels = negativeFeedbackConfig[$position][cardType_$cardType];
showNegativeList(negativeModels);
}

End

项目CodeReview

[toc]

项目CodeReview

一、

1、非空、空值是否合理

2、类型定义是否合理 (字符串/枚举值)

3、方法是否统一(如数字字符串的小数位数保留、弹窗)

4、变量的位置定义是否合理,是否需要传递。局部变量,全局变量。

5、接口是否简化,接口参数是否过多(如跳转到聊天页)

6、必要注释是否缺失

7、代码实现顺序是否合理

参考文章

End

UI组件选择历程

[toc]

FlutterGetX框架选择历程

为什么

前言

1.getX的功能不只是只有状态管理功能。
2.只是为了状态管理的话,项目中新功能可使用。使用不影响其他人。且目前项目中的依赖已包含getX。
3.如果是旧功能,在赶项目的阶段如果没法把握能保量保质的完成开发,不建议使用。当然还是希望大家使用,但任务的完成质量是第一位,如果只是为了使用而影响了项目进度,我认为不是特别可取,除非涉及严重问题不得不。所以没有规定不能使用,但结果是要完成好开发,而不是简单的“好了”,然后存在有很多细节没完善的地方。

对于一个功能,我认为所谓的好了,起码是
①主流程没问题,
②特殊流程已处理,
③异常已容错,
④界面效果与ui完全一致,不差任何一两个像素及颜色偏差,
⑤使用上至少不存在用户感知到的卡顿,
⑥自己发现的问题已跟进处理,而不是挂着等测试或产品提,
⑦别人发现的也一样处理,而不是不重要,
⑧甚至不应该出现用户感知是可点击的,结果点了了没任何效果的问题,哪个加个toast也比没有强
⑨流程上的有些偏可以下沉到底层的,如按钮的重复点击问题处理,图片的加载缓存404等处理,是否在自己的模块上处理完成,或者说告知之前这块没处理过,后面安排处理,
⑩debug模式是否正常,而不是像项目一开始时候的debug都基本无法debug,都在跑release。
等等…

对内的代码结构是否合理,

所以在能保证质量完成开发或者除了不影响使用的解决不了的情况下很希望大家也多看看多学学多了解和使用一些优秀的框架。但框架是为开发服务的,不能说想使用了什么框架结果完成不了,或做得有点大概。
4.另外对于getX的状态管理使用,也不是一使用了就得全部替换,甚至说新功能就一定得按getX来实现。拿个关于页面,一个简单页面用getX与现有的,反而使用getX可认为是完全没必要,因为页面可认为是不需要“可变”状态,只是需要很独立的数据显示而已。类似于做原生,也有很多优秀的框架甚至架构,但mvc的模式肯定在你的项目里有存在,而且在那种场景下,它的优点反而更明显。可以理解为越简单的东西越没有必要使用非常强大的框架,没必要用大炮打小鸟。

优秀新框架的初使用,我认为在前期是允许使用,而不是规定都得使用。好比有人很熟悉,但其他人不熟悉可能做起来,他就没法完成他原本安排的任务,形象而夸大的说,可以想象成让你换个语言开发,排期不变,保证开发完成和质量,而且还不是说他那块的就一定得使用新框架才能。

所以鼓励使用优秀的技术,但别忘了保证完成自己的开发。当然使用新技术时候,如果时间差不多,也可同产品商量适当一两天,在其接受延期的情况下才能延期,不然要使用的话,哪怕加再多班也得完成。而对于一些类似完全重构的任务,自然会同产品协商专门安排一期处理。不管是原生开发还是跨平台,我觉得这些理念和思维应该都差不多。

End