花了 N多天的时间,总算达到了预期的效果(并没有,依旧有很多问题,加了很多特殊代码的排除规则,但也算基本能用了),记录一下,希望能帮到有类似需求的iOSer吧。
SwiftLint: github.com/realm/Swift...
1,先使用命令行安装 SwiftLint工具,命令如下:
brew install swiftlint
2,在项目内接入 SwiftLint,可使用 Cocoapods,我使用的 SPM接入;
3,在项目根目录下(与.xcodeproj文件同层级)创建 .swiftlint.yml文件;
4,将下述规则代码粘贴进去,因为我这边的项目是 SwiftUI,所以控件都是用的 SwiftUI相关的。如果使用的是 UIKit,则需要替换一下;
SwiftLint
only_rules:
- custom_rules
excluded:
- "**/Tests/**"
- "**/UITests/**"
- "**/Pods/**"
- "**/DerivedData/**"
custom_rules:
check_hardcoded_strings:
name: "Hardcoded String"
regex: '(?<!LocalizedStringKey\()(Text\(\s*"(?!.*[\\$]\(.*?\))([^"\\]|\\.)+"\s*\)|(Label|TextField|TextEditor|Alert|Picker|Menu|contextMenu|toolbar|navigationTitle|alert|confirmationDialog|prompt|navigationBarTitle|tabItem|Section|Toggle|ProgressView|Link|Gauge|DatePicker|Stepper|ColorPicker|SecureField|GroupBox|DisclosureGroup|OutlineGroup|LabeledContent)\([^)]*"(?!\s*$)(?!.*(systemImage|imageNamed|systemName|NSLocalizedString\s*\(|localizedString|String\.localized|DateFormatter\.\w+\.string\())[^"\n]+"[^)]*\))'
message: "Avoid hard-coded strings and use localized strings instead."
severity: error
exclude:
# SF Symbols icons
- '\.(systemImage|symbolName)\s*:\s*"[a-z]+(\.[a-z]+)+"' # Match all SF Symbols formats
- 'Label\([^,]+,\s*systemImage\s*:\s*"[^"]+"\)' # Enhanced Label detection
- 'Image\(systemName:\s*"[^"]+"\)' # Cover all Image initializations
# Image sources
- 'image(Name[d]?|Resource|Path)\s*[:=]\s*"[^"]+"'
- '\.image\(\s*"[^"]+"\)'
# Basic exclusions
- 'Text\(\s*"\s*"\s*\)' # Match empty strings and whitespace-only
- 'Text\("[0-9]+(\.[0-9]+)?"\)' # Numbers
- '([+]\s*Text\(\s*"\s*"\s*\))|(Text\(\s*"\s*"\s*\)\s*[+])' # Handle concatenation scenarios
- '(?s)(HStack|VStack|ZStack)\s*\{.*?Text\(\s*"\s*"\s*\).*?\}' # Nested structure detection
# Dynamic content exclusions
- 'Text\(\s*[a-zA-Z_]\w*\s*\)' # Text(variable)
- 'Text\(".*?[\\$]\(.*?\).*?"\)' # Any interpolation ($ or backslash)
- 'Text\(\s*".*?\\.*?"\s*\)' # Contains escape characters
# Special control handling
- "\\bButton\\("
- "\\bnavigationBarItems\\("
- "TextField\\(\\s*\"\"\\s*,.*\\)"
- "NavigationLink\\(\\s*\"\"\\s*,.*\\)"
- "\\.accessibilityLabel\\(Text\\(.*\\)\\)"
- "Group\\s*\\{.*?Text\\(.*?\\).*?\\}"
# Other exclusions
- "(?s)/\\*.*?\\*/"
- "//.*?(\\n|$)"
- "case\\s+\""
- "@selector\\("
- "(#if DEBUG)(.|[\\r\\n])*?(#endif)"
- "(?s)preview\\s*\\{.*?\\}"
- "assert\\(.*\\)"
- "fatalError\\(.*\\)"
- "UserDefaults\\.standard\\.string\\(forKey:.*\\)"
- "Notification\\.Name\\(rawValue:.*\\)"
- "NSLocalizedString\\([^)]*\\)"
5,在项目 Target - Build Phase内新增一个 New Run Script Phase,用来在编译时运行脚本代码;
6,在这个脚本内贴入下述代码,这里要注意 SwiftLint在 M芯片和 Intel芯片的 Mac上的安装路径是不一致的:
bash
# Type a script or drag a script file from your workspace to insert its path.
SWIFTLINT_PATHS=(
"/opt/homebrew/bin/swiftlint" # the path fot M-series chip
"/usr/local/bin/swiftlint" # the path for Intel chip
)
CONFIG="${SRCROOT}/.swiftlint.yml"
SOURCES="${SRCROOT}"
# Trying to find out an available path
SWIFTLINT=""
for path in "${SWIFTLINT_PATHS[@]}"; do
if [ -f "$path" ]; then
SWIFTLINT="$path"
break
fi
done
echo "=== CHECK SWIFTLINT ENV ==="
echo "SwiftLint path: $SWIFTLINT"
if [ -n "$SWIFTLINT" ]; then
echo "SwiftLint version: $($SWIFTLINT version)"
"$SWIFTLINT" lint \
--config "$CONFIG" \
"$SOURCES" \
--strict
exit $?
else
echo "error: SwiftLint not found. Please install it using: brew install swiftlint"
exit 1
fi
7,将这个脚本拖拽到 Compile Sources之前,在编译之前就运行;
8,Command + B,如果代码内有硬编码字符串,应该就会提示报错了。此外如果要修改 .swiftlint.yml文件内的规则,修改规则后务必要先 Clean Build Folder,然后再 Command + B,不然有可能会不生效。