记录使用 SwiftLint检测代码内的硬编码字符串

花了 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,不然有可能会不生效。

相关推荐
专业开发者3 小时前
调试 iOS 蓝牙应用的新方法
物联网·macos·ios·cocoa
1024小神5 小时前
Swift配置WKwebview加载网站或静态资源后,开启调试在电脑上debug
swift
Hilaku6 小时前
那个把代码写得亲妈都不认的同事,最后被劝退了🤷‍♂️
前端·javascript·代码规范
tangbin5830857 小时前
iOS Swift 可选值(Optional)详解
前端·ios
卷心菜加农炮20 小时前
基于Python的FastAPI后端开发框架如何使用PyInstaller 进行打包与部署
ios
gyx_这个杀手不太冷静21 小时前
上线前不做 Code Review?你可能正在给团队埋雷!
前端·代码规范·团队管理
北极象1 天前
千问大模型接入示例
ios·iphone·qwen
ipad协议开发1 天前
企业微信 iPad 协议应用机器人开发
ios·企业微信·ipad
kkoral1 天前
基于MS-Swift 为 Qwen3-0.6B-Base 模型搭建可直接调用的 API 服务
python·conda·fastapi·swift
QuantumLeap丶2 天前
《Flutter全栈开发实战指南:从零到高级》- 26 -持续集成与部署
android·flutter·ios