代码格式化规范
本文档概述了 SideStore 项目中 Swift 和 Objective-C 代码的格式化标准。一致的格式化能让代码库更易于阅读和维护。
通用原则
- 一致性:遵循项目中已有的代码风格
- 可读性:代码应易于阅读和理解
- 简洁性:优先采用简单清晰的方案,而非取巧的做法
- Apple 惯例:尽可能遵循 Apple 官方的 Swift 和 Objective-C 惯例
Swift 格式化
命名规范
变量与函数
- 变量、函数和方法使用 camelCase
- 使用能清晰表明用途的描述性名称
// ✅ Good
let downloadProgress: Float
func validateUserCredentials() -> Bool
var isAppInstalling: Bool
// ❌ Bad
let dp: Float
func validate() -> Bool
var installing: Bool
类、结构体、枚举与协议
- 类型使用 PascalCase
- 使用基于名词的描述性名称
// ✅ Good
class AppInstaller
struct InstallationProgress
enum AppState
protocol AppManaging
// ❌ Bad
class installer
struct progress
enum state
protocol managing
常量
- 常量使用 camelCase
- 可考虑对全局常量使用 SCREAMING_SNAKE_CASE
// ✅ Good
let maxRetryAttempts = 3
private let defaultTimeout: TimeInterval = 30.0
// Global constants
let MAX_CONCURRENT_DOWNLOADS = 5
// ❌ Bad
let MaxRetryAttempts = 3
let max_retry_attempts = 3
缩进与间距
缩进
- 使用 4 个空格进行缩进(不要使用制表符)
- 续行应与起始分隔符对齐
// ✅ Good
func installApp(withIdentifier identifier: String,
sourceURL: URL,
completion: @escaping (Result<Void, Error>) -> Void) {
// Implementation
}
// ❌ Bad
func installApp(withIdentifier identifier: String,
sourceURL: URL,
completion: @escaping (Result<Void, Error>) -> Void) {
// Implementation
}
行长
- 尽可能将每行控制在 120 个字符以内
- 在逻辑合理的位置断行
// ✅ Good
let longVariableName = SomeClass.createInstanceWithVeryLongMethodName(
parameter1: value1,
parameter2: value2
)
// ❌ Bad
let longVariableName = SomeClass.createInstanceWithVeryLongMethodName(parameter1: value1, parameter2: value2, parameter3: value3)
间距
- 运算符两侧使用单个空格
- 行尾不留多余空白
- 在函数之间以及主要代码段之间使用一个空行分隔
// ✅ Good
let result = value1 + value2
if condition && anotherCondition {
// Code
}
func firstFunction() {
// Implementation
}
func secondFunction() {
// Implementation
}
// ❌ Bad
let result=value1+value2
if condition&&anotherCondition{
// Code
}
func firstFunction(){
// Implementation
}
func secondFunction(){
// Implementation
}
花括号与控制流
花括号风格
- 左花括号与语句放在同一行
- 右花括号单独成行,并与起始语句对齐
// ✅ Good
if condition {
doSomething()
} else {
doSomethingElse()
}
class MyClass {
func myMethod() {
// Implementation
}
}
// ❌ Bad
if condition
{
doSomething()
}
else
{
doSomethingElse()
}
Guard 语句
- 使用 guard 语句进行提前返回
- 保持 guard 条件简单易读
// ✅ Good
guard let url = URL(string: urlString) else {
completion(.failure(ValidationError.invalidURL))
return
}
guard !apps.isEmpty else {
return
}
// ❌ Bad
if let url = URL(string: urlString) {
// Long nested code block
} else {
completion(.failure(ValidationError.invalidURL))
return
}
类型标注与类型推断
何时使用类型标注
- 当类型不明确时使用类型标注
- 当 Swift 能明确推断出类型时,省略类型标注
// ✅ Good
let name = "SideStore" // Type is obvious
let timeout: TimeInterval = 30 // Type clarifies intent
var apps: [App] = [] // Empty array needs type annotation
// ❌ Bad
let name: String = "SideStore" // Redundant type annotation
let timeout = 30 // Unclear if Int or TimeInterval
函数声明
参数标签
- 使用描述性的参数标签
- 当省略第一个参数标签读起来更自然时,可以省略
// ✅ Good
func install(_ app: App, to device: Device)
func download(from url: URL, completion: @escaping (Data?) -> Void)
// ❌ Bad
func install(app: App, device: Device)
func download(url: URL, completion: @escaping (Data?) -> Void)
返回类型
- 尽可能将返回类型放在同一行
- 当签名过长时将返回类型换行
// ✅ Good
func processData() -> Result<ProcessedData, ProcessingError>
func complexFunction(withManyParameters param1: String,
param2: Int,
param3: Bool)
-> Result<ComplexReturnType, ComplexErrorType> {
// Implementation
}
Objective-C 格式化
命名规范
方法
- 使用带有清晰参数标签的描述性方法名
- 以小写字母开头
- 使用 camelCase
// ✅ Good
- (void)installAppWithIdentifier:(NSString *)identifier
sourceURL:(NSURL *)sourceURL
completion:(void (^)(NSError *error))completion;
// ❌ Bad
- (void)install:(NSString *)id url:(NSURL *)url completion:(void (^)(NSError *))completion;
变量与属性
- 使用 camelCase
- Use descriptive names
- 实例变量以下划线为前缀
// ✅ Good
@interface AppManager : NSObject
@property (nonatomic, strong) NSArray<App *> *installedApps;
@property (nonatomic, assign) BOOL isInstalling;
@end
@implementation AppManager {
NSURLSession *_networkSession;
dispatch_queue_t _processingQueue;
}
类与协议
- Use PascalCase
- 可考虑为公开类使用前缀(例如用 SS 表示 SideStore)
// ✅ Good
@interface SSAppInstaller : NSObject
@protocol SSAppManaging <NSObject>
// ❌ Bad
@interface appInstaller : NSObject
@protocol appManaging <NSObject>
间距与格式化
方法声明
- 参数应垂直对齐
- 使用一致的间距
// ✅ Good
- (instancetype)initWithIdentifier:(NSString *)identifier
title:(NSString *)title
version:(NSString *)version;
// ❌ Bad
- (instancetype)initWithIdentifier:(NSString *)identifier title:(NSString *)title version:(NSString *)version;
花括号
- 左花括号放在同一行
- 右花括号单独成行
// ✅ Good
if (condition) {
[self doSomething];
} else {
[self doSomethingElse];
}
// ❌ Bad
if (condition)
{
[self doSomething];
}
else
{
[self doSomethingElse];
}
注释与文档
Swift 文档
- 使用
///编写文档注释 - 为公开 API 包含参数和返回值的说明
/// Downloads and installs an app from the specified URL
/// - Parameters:
/// - identifier: The unique identifier for the app
/// - sourceURL: The URL to download the app from
/// - completion: Called when installation completes or fails
/// - Returns: A cancellable operation
func installApp(withIdentifier identifier: String,
sourceURL: URL,
completion: @escaping (Result<Void, Error>) -> Void) -> Operation {
// Implementation
}
Objective-C 文档
- 使用
/** */编写文档注释 - 遵循 HeaderDoc 或 Doxygen 约定
/**
* Downloads and installs an app from the specified URL
* @param identifier The unique identifier for the app
* @param sourceURL The URL to download the app from
* @param completion Block called when installation completes or fails
*/
- (void)installAppWithIdentifier:(NSString *)identifier
sourceURL:(NSURL *)sourceURL
completion:(void (^)(NSError *error))completion;
行内注释
- 使用
//编写单行注释 - 保持注释简洁且有针对性
- 解释为什么,而非是什么
// ✅ Good
// Retry failed downloads up to 3 times to handle temporary network issues
let maxRetryAttempts = 3
// ❌ Bad
// Set maxRetryAttempts to 3
let maxRetryAttempts = 3
错误处理
Swift 错误处理
- 使用 Swift 原生的
throws和Result类型进行错误处理 - 创建有意义的错误类型
enum InstallationError: Error {
case invalidURL
case networkFailure(Error)
case insufficientStorage
case deviceNotSupported
}
func installApp() throws -> App {
guard let url = URL(string: urlString) else {
throw InstallationError.invalidURL
}
// Implementation
}
Objective-C 错误处理
- 使用
NSError **参数模式 - 在设置前,始终检查错误参数是否为非 nil
- (BOOL)installAppWithError:(NSError **)error {
if (someCondition) {
if (error) {
*error = [NSError errorWithDomain:SSErrorDomain
code:SSErrorCodeInvalidInput
userInfo:nil];
}
return NO;
}
return YES;
}
最佳实践
内存管理
- 在 Swift 和 Objective-C 中正确使用 ARC
- 注意循环引用;恰当使用
weak和unowned引用
// ✅ Good
class AppInstaller {
weak var delegate: AppInstallerDelegate?
private lazy var networkManager: NetworkManager = {
let manager = NetworkManager()
manager.delegate = self // Self is strong reference, but manager doesn't retain self
return manager
}()
}
线程
- 始终在主队列上更新 UI
- 为后台任务使用合适的队列
// ✅ Good
DispatchQueue.global(qos: .userInitiated).async {
let result = self.processData()
DispatchQueue.main.async {
self.updateUI(with: result)
}
}
可选值处理
- 使用安全的解包技术
- 优先使用 guard 语句进行提前返回
// ✅ Good
guard let data = response.data,
let apps = try? JSONDecoder().decode([App].self, from: data) else {
completion(.failure(ParsingError.invalidResponse))
return
}
工具与自动化
SwiftLint
可考虑使用 SwiftLint 自动强制执行其中的许多格式化规则:
# .swiftlint.yml
line_length: 120
function_body_length: 60
file_length: 400
type_body_length: 300
disabled_rules:
- trailing_whitespace
opt_in_rules:
- empty_count
- force_unwrapping
请记住:这些规范旨在提升代码的可读性和可维护性。如有疑问,应优先保证清晰性,并与现有代码库保持一致。