3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

MintでSwiftLint導入方法〜M1 Mac・Intel Mac対応【RunScript作成】〜

Last updated at Posted at 2024-01-26

はじめに

Mintを使用してSwiftLintを導入しようとしたら、上手くいかず、つまずいてしまったので、導入方法と解決方法を記事にしました!特にRunScript記述が難しかったです。

SwiftLintとは?

Swift用の静的解析ツールです。
静的解析とは、コードを実行しなくても、コード規約に違反している箇所を指摘する検証のことです。そのため、SwiftLintを導入することで、チーム内で1つのコード規約に則って開発することができます。

事前準備

Mintとは?

Swiftコマンドラインツール(SwiftLint)のインストールと実行を管理するツールです。

Mintをインストール

ターミナルのホームディレクトリで下記のコード実行し、Mintをインストールする!

ターミナル
brew install mint

Mintのバージョン確認

下記のコマンドを実行し、Mintのバージョンが確認できたら、正常にインストールできてます!

ターミナル
mint version

//Version: 0.17.5

MintでSwift導入

プロジェクトフォルダに移動

ターミナル
cd {プロジェクトフォルダ名}

Mintfile作成

ターミナル
touch Mintfile

Mintfileを開く

ターミナル
open Mintfile

Mintfile内にSwiftLintのバージョンを記述

Mintfile
realm/SwiftLint@0.52.4

SwiftLintをインストール

Mintfileに記述されたバージョンのパッケージを一度にインストールする

ターミナル
mint bootstrap

ビルド時に静的解析を行うようにRun Script作成

TARGETS → Build Phasesタブ → 左上にある[+]をクリック → New Run Script Phase
Run script: Based on dependency analysisのチェックを外す!
400246aa335f43c2c3d7bb64362e8756.png

下記のRun Scriptを記述すると、ビルド時に自動で修正してから静的解析されるようになります。M1 MacとIntel Macに対応することができます!

SDKROOT=$(xcrun --sdk macosx --show-sdk-path)
export MINT_PATH=./.mint/lib
export MINT_LINK_PATH=./.mint/bin

# M1 Mac
if [ "$(uname -m)" = "arm64" ]; then
  export HOMEBREW_HOME=/opt/homebrew
# Intel Mac
else
  export HOMEBREW_HOME=/usr/local
fi
if [ -d "${HOMEBREW_HOME}" ]; then
  export PATH="${HOMEBREW_HOME}/bin:$PATH"
fi

if which mint >/dev/null; then
  mint run realm/SwiftLint swiftlint --fix --format
  mint run realm/SwiftLint swiftlint
else
  echo "warning: Mint not installed, please run \`brew install mint\` ."
fi

.swiftlint.yml を作成し、ルールの詳細設定

.swiftlint.ymlを作成

ターミナル
touch .swiftlint.yml

.swiftlint.ymlを開く

ターミナル
open .swiftlint.yml

.swiftlint.ymlを編集する

.swiftlint.yml
disabled_rules:
  #- block_based_kvo
  #- class_delegate_protocol
  #- closing_brace
  #- closure_parameter_position
  #- colon
  #- comma
  #- comma_inheritance
  #- comment_spacing
  #- compiler_protocol_init
  #- computed_accessors_order
  #- control_statement
  #- custom_rules
  #- cyclomatic_complexity
  #- deployment_target
  #- discouraged_direct_init
  #- duplicate_enum_cases
  #- duplicate_imports
  #- duplicated_key_in_dictionary_literal
  #- dynamic_inline
  #- empty_enum_arguments
  #- empty_parameters
  #- empty_parentheses_with_trailing_closure
  #- file_length
  #- for_where
  #- force_cast
  #- force_try
  #- function_body_length
  #- function_parameter_count
  #- generic_type_name
  #- identifier_name
  #- implicit_getter
  #- inclusive_language
  #- inert_defer
  #- is_disjoint
  #- large_tuple
  #- leading_whitespace
  #- legacy_cggeometry_functions
  #- legacy_constant
  #- legacy_constructor
  #- legacy_hashing
  #- legacy_nsgeometry_functions
  #- legacy_random
  #- line_length
  #- mark
  #- multiple_closures_with_trailing_closure
  #- nesting
  #- no_fallthrough_only
  #- no_space_in_method_call
  #- notification_center_detachment
  #- ns_number_init_as_function_reference
  #- nsobject_prefer_isequal
  #- opening_brace
  #- operator_whitespace
  #- orphaned_doc_comment
  #- private_over_fileprivate
  #- private_unit_test
  #- protocol_property_accessors_order
  #- reduce_boolean
  #- redundant_discardable_let
  #- redundant_objc_attribute
  #- redundant_optional_initialization
  #- redundant_set_access_control
  #- redundant_string_enum_value
  #- redundant_void_return
  #- return_arrow_whitespace
  #- self_in_property_initialization
  #- shorthand_operator
  #- statement_position
  #- superfluous_disable_command
  #- switch_case_alignment
  #- syntactic_sugar
  - todo # TODOコメントで警告を増やしたくないため
  - trailing_comma # 末尾にカンマを付けたいことがあるため
  #- trailing_newline
  #- trailing_semicolon
  #- trailing_whitespace
  #- type_body_length
  #- type_name
  #- unavailable_condition
  #- unneeded_break_in_switch
  #- unused_capture_list
  #- unused_closure_parameter
  #- unused_control_flow_label
  #- unused_enumerated
  #- unused_optional_binding
  #- unused_setter_value
  #- valid_ibinspectable
  #- vertical_parameter_alignment
  #- vertical_whitespace
  #- void_return
  #- void_function_in_ternary
  #- xctfail_message

opt_in_rules:
  - accessibility_label_for_image
  - accessibility_trait_for_button
  #- anonymous_argument_in_multiline_closure
  - array_init
  - attributes
  - balanced_xctest_lifecycle
  #- closure_body_length # SwiftUIのViewで長くなることがあるため
  - closure_end_indentation
  - closure_spacing
  - collection_alignment
  - comma_inheritance
  - conditional_returns_on_newline
  - contains_over_filter_count
  - contains_over_filter_is_empty
  - contains_over_first_not_nil
  - contains_over_range_nil_comparison
  - convenience_type
  - discarded_notification_center_observer
  - discouraged_assert
  - discouraged_object_literal
  - discouraged_optional_boolean
  - discouraged_optional_collection
  - empty_collection_literal
  - empty_count
  - empty_string
  - empty_xctest_method
  - enum_case_associated_values_count
  - expiring_todo
  #- explicit_acl # できる限りACLを省略したいため
  #- explicit_enum_raw_value # ローバリューを省略することもあるため
  - explicit_init
  #- explicit_top_level_acl # できる限りACLを省略したいため
  #- explicit_type_interface # できる限り型推論したいため
  #- extension_access_modifier # このルールの意味を理解していないため
  - fallthrough
  - fatal_error_message
  #- file_header # このルールの意味を理解していないため
  - file_name
  - file_name_no_space
  #- file_types_order # 好きな順番に並べたいため
  - first_where
  - flatmap_over_map_reduce
  #- force_unwrapping # 強制アンラップしたいことがあるため
  - function_default_parameter_at_end
  - ibinspectable_in_extension
  - identical_operands
  - implicit_return
  #- implicitly_unwrapped_optional # VIPERで変数を `!` で定義したいため
  #- indentation_width # `guard` のインデントに対応していなく、メソッドの引数でも引っかかって厳しいため
  - joined_default_parameter
  - last_where
  - legacy_multiple
  #- let_var_whitespace # 空白行を設けたくないこともあるため
  - literal_expression_end_indentation
  - local_doc_comment
  - lower_acl_than_parent
  #- missing_docs # マルチモジュールのpublicなAPIすべてにドキュメンテーションコメントを書きたくないため
  - modifier_order
  #- multiline_arguments # 引数は同じ行に2つ入れたいこともあるため
  #- multiline_arguments_brackets # 括弧で行を増やしたくないため
  #- multiline_function_chains # 関数の呼び出しは同じ行に2つ入れたいこともあるため
  #- multiline_literal_brackets # 括弧で行を増やしたくないため
  #- multiline_parameters # 引数は同じ行に2つ入れたいこともあるため
  #- multiline_parameters_brackets # 括弧で行を増やしたくないため
  - nimble_operator
  #- no_extension_access_modifier # エクステンションにACLを設定したいことがあるため
  #- no_grouping_extension # エクステンションでグルーピングしたいことがあるため
  #- no_magic_numbers # マジックナンバーを使いたいときもあるため
  #- non_private_xctest_member # TODO: 未リリースのため
  - nslocalizedstring_key
  - nslocalizedstring_require_bundle
  #- number_separator # 数字を `_` で区切りたくないため
  #- object_literal # リテラルで生成したくないこともあるため
  - operator_usage_whitespace
  - optional_enum_case_matching
  - overridden_super_call
  - override_in_extension
  - pattern_matching_keywords
  #- prefer_nimble # Nimbleを使っていないため
  - prefer_self_in_static_references
  - prefer_self_type_over_type_of_self
  - prefer_zero_over_explicit_init
  #- prefixed_toplevel_constant # 定数のプリフィックスに `k` を付けたくないため
  - private_action
  - private_outlet
  - private_subject
  #- prohibited_interface_builder # IBを使ってビューを生成したいため
  - prohibited_super_call
  - quick_discouraged_call
  - quick_discouraged_focused_test
  - quick_discouraged_pending_test
  - raw_value_for_camel_cased_codable_enum
  - reduce_into
  - redundant_nil_coalescing
  - redundant_type_annotation
  #- required_deinit # できる限りデイニシャライザを省略したいため
  - required_enum_case
  - return_value_from_void_function
  - self_binding
  - shorthand_optional_binding
  - single_test_class
  - sorted_first_last
  #- sorted_imports # インポート文をアルファベット順以外に並び替えたいこともあるため
  - static_operator
  - strict_fileprivate
  #- strong_iboutlet # `@IBOutlet` を `weak` で定義したいため
  #- switch_case_on_newline # Swift 5.9からのswitch式に対応していないため
  - test_case_accessibility
  - toggle_bool
  #- trailing_closure # SwiftUIのViewでラベルを省略したくないことがあるため
  #- type_contents_order # 好きな順番に並べたいため
  - unavailable_function
  - unneeded_parentheses_in_closure_argument
  - unowned_variable_capture
  - untyped_error_in_catch
  # - vertical_parameter_alignment_on_call # なぜか指摘されることがあるため
  #- vertical_whitespace_between_cases # Switch文のケース間に空白行を設けたくないため
  #- vertical_whitespace_closing_braces # 中括弧を閉じる前に空白行を設けたいことがあるため
  #- vertical_whitespace_opening_braces # 中括弧を開く前に空白行を設けたいことがあるため
  - xct_specific_matcher
  - yoda_condition

analyzer_rules:
  - capture_variable
  #- explicit_self # 関数は `self.` を付けずに呼び出したいため
  - typesafe_array_init
  - unused_declaration
  - unused_import

excluded:
  - LokiPackage/Sources/.build

line_length:
  warning: 300
  error: 500

identifier_name:
  min_length:
    warning: 1 # `r` `g` `b` などを使いたいため

下記のウホーイさんの記事の.swiftlint.ymlを使わせてもらっています!

つまずいたエラーと解決方法

下記のようなエラーが発生し、つまずいてしまった。

Sandbox: mint(4301) deny(1) file-read-data /Users/...

c30386c810d340541790b3021fde22d3 (2).png

解決策
TARGETS → Build Settingsタブ → User Script SandboxingをNOに変更する!
Xcode14のデフォルトはNoであったが、Xcode15のデフォルトはYesであるので、NOに変更する必要がある!これがXcode15でSwiftLintが上記のようなエラーになる原因です。

e6dd2617cd60a1315300f87483663a4e.png

参考文献

ウホーイさんから教えていただいたことを記事にしました。

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?