游乐游手机版
首页/AI热点日报/热点详情

TRAE:从谨慎检查到一键接受,我的主力IDE

类型:热点整理2026-07-18
TRAE作为AI编程助手,通过打开工程文件夹建立索引,辅助完成新功能模块开发。利用类图快速搭建框架、从Figma生成视图代码、自动生成配置代码,显著提升开发效率,实现从逐条谨慎检查到一键接受AI代码的转变。

TRAE 不仅是一款代码编辑器,更是你开发路上的 AI 智能助手。本教程将带你从打开项目文件夹开始,逐步掌握利用 TRAE 高效完成新功能模块开发、分析已有模块以及代码重构的核心技巧,让你从逐条谨慎检查变更,进化到一键轻松接受 AI 代码。

一、用 TRAE 打开工程文件

大家在使用 TRAE 开发客户端功能时,通常会把哪个文件夹交给 TRAE 呢?

当开发业务需求时,可以用 TRAE 直接打开工程中源码所在的文件夹,这样几乎所有需要的文件都能在 TRAE 中索引到,同时也能避免整个工程下其他文件的干扰。

如果明确需要针对某个文件夹下的代码进行分析或修改,有时也会直接用 TRAE 打开该特定文件夹,以便它能快速建立代码索引,精确地分析上下文。

重要提示: TRAE 的历史会话记录是以文件夹维度存储的,一旦文件夹被删除,之前在该文件夹中产生的所有历史会话也将全部丢失!

如何导出历史会话记录? 可以用魔法打败魔法,直接让 AI 将会话内容整理到文件中。使用以下提示词即可:

将上面的对话历史内容全部整理到该文件中,包括给出的代码片段,不要遗漏内容,优化输出的markdown格式,让问题和回答一目了然



二、实现一个新功能模块

对于一个新功能模块,个人认为非常适合用 TRAE 来完成绝大部分代码。对于新增类的实现和完善,几乎都可以由 AI 完成。最近的业务中正好有一个这样的例子:全新的功能,与现有业务代码耦合度较低。实践下来,大约有 90% 的代码是用 AI 生成的,使用的 LLM 主要是 Gemini-2.5-Pro-Preview(0506)(最新版本中已经是 Gemini-2.5-Pro)和 DeepSeek-V3-0324。

Case 1: 用类图先搭建起功能模块的基础框架

我一般习惯在技术方案中就把实现一个功能模块所需的类都设计好,然后再开始写代码。有了这份类图的指导,就可以使用 TRAE 快速地把关键类的基础框架搭建起来。

XXX模块的最初类设计图

如果方法和属性定义得比较清晰,可以直接将该类图截图给 Gemini 作为上下文,节省写提示词的时间,然后在对话时使用 @Builder 直接生成类的文件。每轮对话最好只处理一个文件,然后针对这个类的实现提出具体的要求,例如:

import Foundation

classXXXStateManager {

// MARK: - Singleton
static let sharedInstance = XXXStateManager()
private init() {}

// MARK: - Properties
private var _value: Float = 0.0
private let lock = NSLock()

    var value: Float {
        get {
            lock.lock()
            defer { lock.unlock() }
return _value
        }
set {
            lock.lock()
            _value = newValue
            lock.unlock()
// 通知外部积分已变更,会携带此时的value和state值
        }
    }

// MARK: - Methods

/// 获取百分比
    func getXXXValue() -> Float {
// TODO: Implementation
return value
    }

/// 根据百分比返回当前状态枚举值
    func getXXXState() /*-> XXXState*/ {
// TODO: Implementation & Define XXXState enum
    }

/// 请求接口,更新积分
    func requestUpdateXXXValue() {
// TODO: Implementation
    }

/// 请求接口,获取最新积分
    func syncXXXValue() {
// TODO: Implementation
    }

/// 开启后,重置积分
    func resetXXXToValue(_ newValue: Float) {
// TODO: Implementation
        self.value = newValue
    }
}

// TODO: Define XXXState enum if needed, for example:
// enum XXXState {
//    case stateA
//    case stateB
//    // ... other states
// }

之后在实现每个类的过程中,就是不断拆解问题,让 AI 去完成。注意: 一个问题解决后最好再开一个新的会话解决下一个问题,避免 LLM 对上下文理解的干扰。 记得当新增代码量达到一定程度时,要检查是否有编译错误。

左右滑动查看更多精彩内容


Case 2: 用 Figma 中的 UIKit 代码生成视图代码

以前这种画 UI 既枯燥又磨人的活,终于可以在几分钟内搞定了~

我在这里的做法是,在 Figma 中选中图层,将对应的 UIKit 代码直接复制到 TRAE 中,让 AI 生成 Swift 代码。先实现视图本身的样式,再往里添加子视图元素,生成的代码基本不需要做太大改动。

import UIKit
import SnapKit

classReadyCardView: UIView {

private let iconView = UIView()
private let titleLabel = UILabel()
private let subTitleLabel = UILabel()

override init(frame: CGRect) {
        super.init(frame: frame)
        setupView()
        setupSubviews()
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupView()
        setupSubviews()
    }

private func setupView() {
// 设置视图基本属性
        self.clipsToBounds = false
        self.layer.cornerRadius = 16

// 添加阴影效果
        let shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: 16)
        layer.shadowPath = shadowPath.cgPath
        layer.shadowColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.25).cgColor
        layer.shadowOpacity = 1
        layer.shadowRadius = 16
        layer.shadowOffset = CGSize(width: 0, height: 8)

// 添加渐变背景
        let gradientLayer = CAGradientLayer()
        gradientLayer.colors = [
            UIColor(red: 0, green: 0, blue: 0, alpha: 1).cgColor,
            UIColor(red: 0, green: 0, blue: 0, alpha: 1).cgColor,
            UIColor(red: 0, green: 0.267, blue: 0.209, alpha: 1).cgColor
        ]
        gradientLayer.locations = [0, 0.6, 1]
        gradientLayer.startPoint = CGPoint(x: 0, y: 0.5)
        gradientLayer.endPoint = CGPoint(x: 1, y: 0.5)
        gradientLayer.frame = bounds
        gradientLayer.cornerRadius = 16
        layer.insertSublayer(gradientLayer, at: 0)

// 添加边框
        layer.borderWidth = 1.5
        layer.borderColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.15).cgColor
    }

private func setupSubviews() {
// 添加iconView
        addSubview(iconView)
        iconView.snp.makeConstraints { make in
            make.width.height.equalTo(120)
            make.top.equalToSuperview().offset(64)
            make.centerX.equalToSuperview()
        }

// 添加titleLabel
        addSubview(titleLabel)
        titleLabel.textColor = UIColor(red: 1, green: 1, blue: 1, alpha: 1)
        titleLabel.font = UIFont(name: "PingFangSC-Medium", size: 20)
        titleLabel.textAlignment = .center
        titleLabel.text = "已就绪"
        titleLabel.snp.makeConstraints { make in
            make.width.equalTo(210)
            make.height.equalTo(28)
            make.top.equalTo(iconView.snp.bottom).offset(8)
            make.centerX.equalToSuperview()
        }

// 添加subTitleLabel
        addSubview(subTitleLabel)
        subTitleLabel.textColor = UIColor(red: 0.604, green: 0.604, blue: 0.604, alpha: 1)
        subTitleLabel.font = UIFont(name: "PingFangSC-Regular", size: 15)
        subTitleLabel.text = ""
        subTitleLabel.snp.makeConstraints { make in
            make.width.equalTo(270)
            make.height.equalTo(21)
            make.top.equalTo(titleLabel.snp.bottom)
            make.centerX.equalToSuperview()
        }
    }

override func layoutSubviews() {
        super.layoutSubviews()
// 更新渐变层frame
if let gradientLayer = layer.sublayers?.first as? CAGradientLayer {
            gradientLayer.frame = bounds
        }
    }
}

小提示: 这种方式简单直接,零成本上手使用。更进一步,我们也可以通过 Figma 官方提供的 MCP 工具来实现 UI 代码的生成,具体操作会在进阶篇中介绍。


Case 3: 生成读取 Settings 配置的代码

读取 Settings 配置的代码也比较模板化,如果手动去敲,在配置项很多的时候也需要花费不少时间。现在描述清楚要求后,静待 TRAE 来生成代码就行了。下面左侧是生成的代码效果,几乎不需要改什么,可以直接用。之后可以继续让 TRAE 用这份 Configuration 替换掉写死在代码中的值。

import Foundation
import AWEAppSettings // 请确保已正确导入 AWEAppSettings

/// XXX铃功能相关配置
classXXXConfiguration {
// MARK: - Settings Keys
/// 灵动岛文案配置的根键
privatestatic let kXXXTextConfigRootKey = "XXX_text_config"
/// 作品播放x毫秒后的互动才能算积分(单位毫秒)的键
privatestatic let kXXXPlayDurationMinKey = "XXX_play_duration_min"
/// XXX横幅自动展示x秒后消失(单位秒)的键
privatestatic let kXXXBannerShowDurationKey = "XXX_banner_show_duration"
/// 点击发现tab后,x秒内不重复请求接口(单位秒)的键
privatestatic let kXXXClickTabRequestIntervalKey = "XXX_click_tab_request_interval"
/// 前x次点击小铃铛(uid/did维度都可)会展开横幅(x=3)的键
privatestatic let kXXXClickMatchBellExpandBannerCountKey = "XXX_click_match_bell_expand_banner_count"
// MARK: - Sub Keys for XXX_text_config
privatestatic let kTextConfigEntranceKey = "entrance"
privatestatic let kTextConfigCollectKey = "collect"
privatestatic let kTextConfigCollectTitleKey = "title"// 嵌套在 collect 下
privatestatic let kTextConfigCollectSubTitleKey = "sub_title"// 嵌套在 collect 下
privatestatic let kTextConfigFullKey = "full"
privatestatic let kTextConfigFullTitleKey = "title"// 嵌套在 full 下
privatestatic let kTextConfigFullSubTitleKey = "sub_title"// 嵌套在 full 下
privatestatic let kTextConfigFullBtnTextKey = "btn_text"// 嵌套在 full 下
// MARK: - Default Values for XXX_text_config
privatestatic let defaultTextConfigEntrance = ""
privatestatic let defaultTextConfigCollectTitle = "\"
privatestatic let defaultTextConfigCollectSubTitle = ""
privatestatic let defaultTextConfigFullTitle = "\"
privatestatic let defaultTextConfigFullSubTitle = ""
privatestatic let defaultTextConfigFullBtnText = ""
privatestatic let defaultCollectDictionary: [String: String] = [
        kTextConfigCollectTitleKey: defaultTextConfigCollectTitle,
        kTextConfigCollectSubTitleKey: defaultTextConfigCollectSubTitle
    ]
privatestatic let defaultFullDictionary: [String: String] = [
        kTextConfigFullTitleKey: defaultTextConfigFullTitle,
        kTextConfigFullSubTitleKey: defaultTextConfigFullSubTitle,
        kTextConfigFullBtnTextKey: defaultTextConfigFullBtnText
    ]
// MARK: - General Settings Getters
/// 获取作品播放x毫秒后的互动才能算积分(单位毫秒)
/// 默认值: 3000
static func playDurationMin() -> Int {
return AWEAppSettings.awemeSettings().integer(forKeyPath: kXXXPlayDurationMinKey, defaultValue: 3000)
    }
/// 获取XXX横幅自动展示x秒后消失(单位秒)
/// 默认值: 10
static func bannerShowDuration() -> Int {
return AWEAppSettings.awemeSettings().integer(forKeyPath: kXXXBannerShowDurationKey, defaultValue: 10)
    }
/// 获取点击发现tab后,x秒内不重复请求接口(单位秒)
/// 默认值: 30
static func clickTabRequestInterval() -> Int {
return AWEAppSettings.awemeSettings().integer(forKeyPath: kXXXClickTabRequestIntervalKey, defaultValue: 30)
    }
/// 获取前x次点击小铃铛(uid/did维度都可)会展开横幅(x=3)
/// 默认值: 3
static func clickMatchBellExpandBannerCount() -> Int {
return AWEAppSettings.awemeSettings().integer(forKeyPath: kXXXClickMatchBellExpandBannerCountKey, defaultValue: 3)
    }
// MARK: - Text Config Getters
/// 通用方法:获取 XXX_text_config 下指定子键的字符串值
/// - Parameters:
///   - subKey: XXX_text_config 内的子键 (例如 "entrance" 或 "collect.title")
///   - defaultValue: 如果未找到配置,则返回的默认值
/// - Returns: 配置的字符串值或默认值
privatestatic func getTextConfigStringValue(forKey subKey: String, defaultValue: String) -> String {
        let keyPath = "(kXXXTextConfigRootKey).(subKey)"
return AWEAppSettings.awemeSettings().string(forKeyPath: keyPath, defaultValue: defaultValue) ?? defaultValue
    }

/// 通用方法:获取 XXX_text_config 下指定子键的字典值
/// - Parameters:
///   - subKey: XXX_text_config 内的子键 (例如 "collect" 或 "full")
///   - defaultValue: 如果未找到配置,则返回的默认值
/// - Returns: 配置的字典值或默认值
privatestatic func getTextConfigDictionaryValue(forKey subKey: String, defaultValue: [String: Any]) -> [String: Any] {
        let keyPath = "(kXXXTextConfigRootKey).(subKey)"
return AWEAppSettings.awemeSettings().dictionary(forKeyPath: keyPath, defaultValue: defaultValue) ?? defaultValue
    }
/// 获取灵动岛文案配置 - 入口文案
/// 例如:"entrance":""
/// 默认值: ""
static func textConfigEntrance() -> String {
return getTextConfigStringValue(forKey: kTextConfigEntranceKey, defaultValue: defaultTextConfigEntrance)
    }
// MARK: - Collect Text Config

/// 获取灵动岛文案配置 - "collect" 对象字典
/// 默认值: `["title": "", "sub_title": ""]`
static func textConfigCollectDictionary() -> [String: String] {
        let dict = getTextConfigDictionaryValue(forKey: kTextConfigCollectKey, defaultValue: defaultCollectDictionary)
return dict as? [String: String] ?? defaultCollectDictionary
    }
/// 获取灵动岛文案配置 - 充能中标题
/// 例如:"collect.title":"XXX铃充能中"
/// 默认值: "XXX铃充能中"
static func textConfigCollectTitle() -> String {
        let keyPath = "(kTextConfigCollectKey).(kTextConfigCollectTitleKey)"
return getTextConfigStringValue(forKey: keyPath, defaultValue: defaultTextConfigCollectTitle)
    }
/// 获取灵动岛文案配置 - 充能中副标题
/// 例如:"collect.sub_title":""
/// 默认值: ""
static func textConfigCollectSubTitle() -> String {
        let keyPath = "(kTextConfigCollectKey).(kTextConfigCollectSubTitleKey)"
return getTextConfigStringValue(forKey: keyPath, defaultValue: defaultTextConfigCollectSubTitle)
    }
// MARK: - Full Text Config (寻找已就绪)

/// 获取灵动岛文案配置 - "full" 对象字典
/// 默认值: `["title": "寻找已就绪", "sub_title": "点击开启,找到与你有默契的人", "btn_text": "开启寻找"]`
static func textConfigFullDictionary() -> [String: String] {
        let dict = getTextConfigDictionaryValue(forKey: kTextConfigFullKey, defaultValue: defaultFullDictionary)
return dict as? [String: String] ?? defaultFullDictionary
    }
/// 获取灵动岛文案配置 - 寻找已就绪标题
/// 例如:"full.title":""
/// 默认值: ""
static func textConfigFullTitle() -> String {
        let keyPath = "(kTextConfigFullKey).(kTextConfigFullTitleKey)"
return getTextConfigStringValue(forKey: keyPath, defaultValue: defaultTextConfigFullTitle)
    }
/// 获取灵动岛文案配置 - 寻找已就绪副标题
/// 例如:"full.sub_title":""
/// 默认值: ""
static func textConfigFullSubTitle() -> String {
        let keyPath = "(kTextConfigFullKey).(kTextConfigFullSubTitleKey)"
return getTextConfigStringValue(forKey: keyPath, defaultValue: defaultTextConfigFullSubTitle)
    }
/// 获取灵动岛文案配置 - 寻找已就绪按钮文案
/// 例如:"full.btn_text":""
/// 默认值: ""
static func textConfigFullBtnText() -> String {
        let keyPath = "(kTextConfigFullKey).(kTextConfigFullBtnTextKey)"
return getTextConfigStringValue(forKey: keyPath, defaultValue: defaultTextConfigFullBtnText)
    }
}

Case 4: 随时对代码进行优化

在实现功能的过程中,可以借助 TRAE 随时对代码进行优化。比如这次开发中,异步读写 storage 在两处都有同样的处理,我让 AI 直接封装了一个 AsyncStorageUtil 类。再比如,我就是看某段代码写得很啰嗦,感觉可以优化,但没有思路,也可以直接让 AI 给出优化建议。


Case 5: 将 OC 代码翻译成 Swift

把大段的 OC 代码手动翻译成 Swift 还是会费一番功夫的,现在 AI 可以秒完成,在我们写 Swift 时一定要利用上这个能力。


Case 6: 使用 TRAE 的 cue 功能直接写代码

除了在对话框中与 AI 沟通来完成任务,很多时候我也会直接在 TRAE 中写代码。按 Tab 键即可接受预测的内容,按 ESC 键取消当前的预测。体验下来,接受的概率还是比较高的,这种方式也推荐大家去试用。


三、分析已有的功能模块

Case1: Copy 代码时补齐头文件

在开发中我们会遇到一种情况:去已有代码里 Copy 一段逻辑到自己的代码里,有时这段代码需要额外引入很多头文件。纯靠记忆精准敲出这些头文件是有点难为我胖虎了,去原来的代码一点点找又比较费时,尤其是那个文件引入了一屏幕都放不下的头文件时。

此时就可以让 AI 先去干一番活啦,比如我要把下面的代码复制到一个新文件中去:


Case2: 分析长函数的执行过程

当我们遇到不能一眼看出某个方法在做什么的时候,可以让 LLM 详细解释这个方法,并生成流程图。比如下面这段代码,我们让 Gemini 来分析解释一下,并让它生成可以在 Mermaid 或 draw.io 中展示的流程图:

- (void)fetchRecommendCardOfFamiliarFeedWithSuccessCompletion:(void(^)(BOOL))completion {
    if (![self enableInsertFamiliarFeedCard]) {
        AWEBLOCK_INVOKE(completion,NO);
        return;
    }
    dispatch_group_t group = dispatch_group_create();
    BOOL fetchDataSuccess = NO;
    if ([self.familiarFeedRecommendStrategy enableInsertFamiliarFeedObdCardAB] &&
        self.familiarFeedObdDataSource.models.count == 0) {
        fetchDataSuccess = YES;
        dispatch_group_enter(group);
        [self fetchFamiliarRecommendUserDataWithType:AWERecommendTypeFeedObdCard isAutoTrigger:NO completion:^{
            dispatch_group_lea ve(group);
        }];
    }
    if ([self.familiarFeedRecommendStrategy enableInsertFamiliarFeedMateCardAB] &&
        self.familiarFeedMateDataSource.models.count == 0) {
        fetchDataSuccess = YES;
        dispatch_group_enter(group);
        [self fetchFamiliarRecommendUserDataWithType:AWERecommendTypeFeedMateCard isAutoTrigger:NO completion:^{
            dispatch_group_lea ve(group);
        }];
    }
    if ([self.familiarFeedRecommendStrategy enableInsertFamiliarFeedListCardAB] &&
        self.familiarFeedMultiMateDataSource.models.count == 0) {
        fetchDataSuccess = YES;
        dispatch_group_enter(group);
        [self fetchFamiliarRecommendUserDataWithType:AWERecommendTypeFeedMateMultiCard isAutoTrigger:NO completion:^{
            dispatch_group_lea ve(group);
        }];
    }
    if (fetchDataSuccess) {
        dispatch_group_notify(group, dispatch_get_main_queue(), ^{
            AWEBLOCK_INVOKE(completion, YES);
        });
    } else {
        AWEBLOCK_INVOKE(completion, NO);
    }
}

小提示: 可以从 TRAE 的插件市场中安装一个 Mermaid Preview 插件,然后创建一个 mermaid.md,把代码贴过去就可以预览效果了,会根据当前的 IDE 给对应的配色。

```mermaid // 文件中加上该表示
// 直接将 mermaid 源码粘贴在这里

左右滑动查看更多精彩内容


Case3: 分析一个完整的功能模块

在做技术调研时,也经常会遇到需要去了解一个完整功能模块实现过程的情况。如果这个模块的代码比较内聚,并且都集中放在一个文件夹内,那就可以把整个文件夹丢给 AI 去分析,并让它生成流程图和时序图,但也要考虑到 LLM 一次可以接收的上下文长度。比如之前调研主框架的异形卡实现过程:

这样了解一番后,对这个模块是怎么工作的就有了一个大致了解,提升了我们调研的效率。


Case4: 辅助完成代码重构

在做代码重构时,也可以让 TRAE 来辅助完成,比如一些文件重名替换、抽离定义常量等等。前段时间把一个气泡视图重构成了可以给其他场景使用的通用组件,也是用 TRAE 完成了大部分工作。基本上自己想好了重构方案后,就是指挥 AI 来一步步干活了。

我这里直接新开一个 TRAE 窗口,只打开要修改的文件夹,然后就可以引用 #Workspace 了,也避免了其他代码上下文对 LLM 分析的干扰。

注意: AI 修改后需要再审查核对一下,整体上比纯人工来写提效了很多,在我这次重构中至少节约了 1 pd。

来源:https://www.53ai.com/news/LargeLanguageModel/2025071094806.html

相关热点

继续查看同栏目近期热点。

延伸阅读

补充最近整理过的热点入口。