引言:为什么你的代码在呼救(以及 MARK: 如何让它平静下来)
\n\n想象一下:你打开一个 500 行的 Swift 文件。眼睛在屏幕上扫视,你正在寻找方法 tableView(_:cellForRowAt:),但却淹没在 func 和 var 的海洋中。熟悉吗?在 2025 年,当项目变得越来越复杂,开发速度至关重要时,这种情况是通往 bug 和浪费时间的最直接途径。
在 Stack Overflow 上,问题 "#pragma mark in Swift?" 获得了数千次浏览。这并非偶然。从 Objective-C 转过来的开发者在寻找熟悉的工具,而新手则在寻找整理代码的方法。答案简单而优雅:Swift 中没有 #pragma mark,但有一个更强大的替代品——// MARK:。
在这篇文章中,我们不仅会告诉你如何使用 // MARK: 在 Swift。我们还将展示 2025 年的最佳实践,这些实践将使你的代码成为一件艺术品,无论是一年后的你,还是你的同事,都能轻松理解。准备好 Xcode——会很有趣。
\n\n什么是 // MARK: 在 Swift 以及为什么需要它?
\n\n如果你曾经使用过 Objective-C,你会记得 #pragma mark。这是一个预处理器指令,帮助你在 Xcode 的导航面板中对方法进行分组。Swift 中废弃了它,但通过特殊的注释保留了其功能。
// MARK: 是一个注释,Xcode 将其解释为章节分隔符。它会在导航栏(Jump Bar)中添加一个粗体标题和一条分隔线。看起来像这样:
\n\n// MARK: - Lifecycle\n\noverride func viewDidLoad() {\n super.viewDidLoad()\n}\n\n// MARK: - Table View Data Source\n\nfunc tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {\n return items.count\n}\n\n\n请注意 MARK: 后面的连字符(// MARK: -)。它会添加一条水平分隔线。没有连字符则只会显示粗体文本。根据你想要在视觉上分隔块的程度,使用这两种变体。
SEO 关键词: 在 Swift 中使用 // MARK:,Swift 代码组织,Xcode 导航。
\n\n2025 年使用 // MARK: 的最佳实践
\n\n简单地在任何地方插入 // MARK: 并不是一个好主意。这会产生噪音。以下是顶级 iOS 开发者使用的经过验证的技巧。
1. 按协议和职责进行分组
\n\n最常见的场景是在一个类中实现多个协议。不要让同事猜测 UITableViewDelegate 在哪里结束,UITableViewDataSource 在哪里开始。
final class ProfileViewController: UIViewController {\n\n // MARK: - Properties\n\n private let viewModel: ProfileViewModel\n private let tableView = UITableView()\n\n // MARK: - Lifecycle\n\n override func viewDidLoad() {\n super.viewDidLoad()\n setupUI()\n }\n\n // MARK: - UITableViewDataSource\n\n override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {\n return viewModel.sections.count\n }\n\n override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {\n // ...\n }\n\n // MARK: - UITableViewDelegate\n\n func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {\n viewModel.didSelectRow(at: indexPath)\n }\n\n // MARK: - Private Methods\n\n private func setupUI() {\n // ...\n }\n}\n\n\n这是黄金标准。每个块负责一个逻辑单元。
\n\n2. 使用 // MARK: - 对类内的逻辑部分进行划分
\n\n即使你没有实现协议,也要将长类分成几个部分:Public Methods、Private Methods、Helpers、Actions。