工作记录

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

iOS进阶_多Target

利用多Target开发相似app

一、问题背景

开发一个与之前几乎一样的app。只是app名字等基本信息变更。

错误做法 正确做法
项目 再创建了新的项目 使用同一项目
原因 极容易出现后来新开发的功能两个app都要支持 保证可共用到以后新开发的功能

下面我们开始介绍如何利用多Target开发相似app。

二、操作步骤

1、生成新的Target(这里推荐采用Duplicate方式,而不是File->New->Target)

1.1、Duplicate方法略。
1.2、Duplicate后,需要修改的东西
必选需修改项 操作方法 得到
Info.plist ①复制一份。
②并重新为Target选择Info.plist
③跟新Info.plist中的名字、签名等
App1Info.plist、App2Info.plist
Scheme Manager Scheme -> 双击重命名 新的App2Scheme
证书&描述文件 更具新的BundleId,添加证书&描述文件 真机编译通过

特别注意:add Info.plist等文件的时候,一定要注意选择对应的Target。不多多勾选☑️,也不要少勾选。

1.3、其他APP定制项更改
可选修改项 操作方法 得到
icon 修改InfoPlist 新APP的Icon
名字 修改InfoPlist 新APP的名字

2、Target区分

需求背景:有些共用的文件在不同的Target下是有细微不同的,那么我们在具体实现的时候就需要作出区分。

2.1、Objective-C、C、C++的LLVM预处理宏的添加

Objective-C、C、C++的LLVM预处理宏在Preprocessor Macros处定义。如图创建工程时已经默认创建好了在Debug时定义DEBUG=1 宏标记。

2.2、Swift

因为Swift 中没有宏定义的概念,因此我们不能使用 #ifdef 的方法来检查某个符号是否经过宏定义。

在项目的 Build Settings 中,找到 Swift Compiler - Custom Flags,并在其中的 Other Swift Flags

为APP1加上 -D APPTARGET1 就可以了;为APP2加上 -D APPTARGET2 就可以了;

其他参考文章:https://blog.csdn.net/kaiyuanheshang/article/details/78862382

解决办法:这里解决的方法是针对不同的Target在Preprocessor Macros中定义宏,如添加TargetTYPE

  • 在Preprocessor Macros中添加TARGETTYPE

PreprocessorMacros添加后

Target代码区分需用到的知识:

含义 示例
#if 既关心宏是否定义,又关心宏的逻辑的真假
#ifdef
#ifndef
仅仅关心宏是否被定义,不关心宏的逻辑真假

代码区分如下:

1
2
3
4
5
#if TARGETTYPE == 0
[AMapServices sharedServices].apiKey = @"6d79992bc988b60f68e059edeef82538";
#elif TARGETTYPE == 1
[AMapServices sharedServices].apiKey = @"aef6d9dabe4cdd1da9e923e52b5d40ca";
#endif

至此,你直接编译,发现”好像”完成了。实际上如果你的项目没有使用POD的,确实是到此就完成了 。

分割图1

下面我们额外补充,当你的项目有使用POD的时候,你还需要处理的东西。

3、Pod修改

在上述中,你可能发现好像我使用了POD的但是依然正确编译通过啊。

是的,是通过了,但是这是假象。或者准确的说,当你下次使用POD相关命令,如pod install的时候,你会发现之前的项目编译不通过了。

所以,你需要修改PodFile,并重新pod install。PodFile的修改方法如下:

1
2
3
4
5
6
7
8
9
target 'APP1' do
pod 'AFNetworking'
pod 'APP1SDK'
end

target 'APP2' do
pod 'AFNetworking'
pod 'APP2SDK'
end
  • 修改方式1:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# There are no targets called "APPCommon" in any Xcode projects
abstract_target 'APPCommon' do
pod 'AFNetworking'

# Has its own copy of APPCommon + APP2SDK
target 'APP1' do
pod 'APP1SDK'
end

# Has its own copy of APPCommon + APP2SDK
target 'APP2' do
pod 'APP2SDK'
end
end
  • 修改方式2:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 共用的第三方库
def AppCommon_Pods
pod 'AFNetworking'
end

# APP1所需的第三方库
target 'APP1' do
AppCommon_Pods
pod 'APP1SDK'
end

# APP2所需的第三方库
target 'APP2' do
AppCommon_Pods
pod 'APP2SDK'
end

最后修改完后,重新pod install后即可。

分割图1

4、脚本打包时候,因为多Target后旧的libPods-xxx(Framework)忘删除引起的问题

多Target后旧的libPods-xxx引起的问题

多Target后旧的libPods-xxx引起的问题

多Target后旧的libPods-xxx的问题解决否的判断

多Target后旧的libPods-xxx的问题解决否的判断

三、Swift中的条件编译

在C 系语言中,我们可以通过预处理宏定义一些参数,使用#if或者#ifdef编译条件分支来控制哪些代码需要编译,而哪些代码不需要。但是在swift中没有宏定义的概念,虽然不能使用 #ifdef 的方法来检查某个符号是否经过宏定义,但是可以支持“#if/#else/#endif”语句。

四、其他

只用一个target,配合一个脚本,可以进行茫茫多target的管理了

第3节:Jenkins使用技巧常用

一、正确实现并测试一个Jenkins脚本的步骤

原则:将脚本中的命令分布测试通过后再一起合成。

1、将一行行命令单独在终端中操作,验证是否通过;

2、整理到*.sh/.py*中,通过终端验证;

3、放到 Jenkins 的shell脚本中,构建验证;

3.1、现在本地验证后,再托管到服务器上;

在本地通过*cd 脚本绝对路径sh 脚本.sh*,构建验证;

3.2、本地验证后,使用 git/SVN 管理源码

二、源码托管

问:Jenkins中的项目一般都是托管在 Git/SVN 上,如果你想要在本地尝试呢?如何操作?

答:源码管理选择None。然后直接在Jenkins中的脚本里cd到执行路径,再操作即可。

DBSQL

Mac终端查看sqlite3数据库、表数据等(含sqlite可视化工具下载)

地址:https://xclient.info/s/navicat-premium.html#versions

navicat for mysql 只适用于 mysql ,navicat Premium 是全系列的。

Navicat Premium是一套数据库管理工具,结合了其它Navicat成员的功能,支持单一程序同时连接到MySQL、MariaDB、SQL Server、SQLite、Oracle和PostgreSQL数据库。Navicat Premium可满足现今数据库管理系统的使用功能,包括存储过程、事件、触发器、函数、视图等。
Navicat for MySQL是一套管理和开发MySQL或MariaDB的理想解决方案,支持单一程序,可同时连接到MySQL和MariaDB。这个功能齐备的前端软件为数据库管理、开发和维护提供了直观而强大的图形界面,给MySQL或MariaDB新手以及专业人士提供了一组全面的工具。

Markdown基础语法

参考文章:

锚点

详情查看:附一: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

开发工具的安全性保障

项目安全

一、开发工具

附:《开发工具.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