前语

代码风格或许是一个有争议的论题,而且在开发人员之间引发一些剧烈的评论。运用东西强制执行一套代码风格规则关于避免一些争辩,以及保证在整个项目中坚持代码风格的共同性非常有帮忙。SwiftLint 可以很简略的整合进 Xcode 项目中,以便在编译时将代码风格冲突标记为警告或许差错。


运用 Xcode 集成 SwiftLint

你可以在 Github上 获得SwiftLint。它可以运用多种方法设备,比如,直接下载 SwiftLint.pkg 包,或许运用HomeBrew指令行。

brew install swiftlint

设备 SwiftLint 后,可以经过在主 app target 的Build Phase(构筑阶段)下添加一个Run Phase(工作阶段)的工作脚本,来集成进 Xcode 项目。点击+号按钮,挑选”New Run Script Phase”,添加下面的脚本。在 silicon Macs (搭载M1芯片)上需求添加export语句,因为HomeBrew二进制文件默许设备在/opt/homebrew/bin目录之下。

译者注:并不一定在此目录下,详细可以点击这儿。

export PATH="$PATH:/opt/homebrew/bin"
if which swiftlint > /dev/null; then
  swiftlint
else
  echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint"
fi

用 SwiftLint 坚持 Swift 风格共同

在 Xcode 添加工作脚本以集成 SwiftLint


SwiftLint 的规则冲突

好消息是,新建的 Xcode 项目没有违背 SwiftLint 的默许规则。一旦你知道了 SwiftLint,最好从一初步就当即将其添加到每个项目中。在刚才新建的 iOS App 的Text view后边添加一个空格。现在,编译代码时会生成警告。

struct ContentView: View {
    var body: some View {
        VStack {
            Text("Hello, world!") 
            Text("second line")
            Spacer()
        }
    }
}

这段代码违背了trailing_whitespace规则,它默许是打开的。

+------------------------------------------+--------+-------------+------------------------+-------------+----------+---------------+
| identifier                               | opt-in | correctable | enabled in your config | kind        | analyzer | configuration |
+------------------------------------------+--------+-------------+------------------------+-------------+----------+---------------+
| trailing_whitespace                      | no     | yes         | yes                    | style       | no       | warning, i... |

用 SwiftLint 坚持 Swift 风格共同

Swift 正在警告在一行之后有一个额外的空格


SwiftLint 的规则

SwiftLint 包含了200多条规则,而且 Swift 社区仍在不间断的贡献更多的规则。查看 SwiftLint 规则的一种方法是在终端中工作swiftlint rules指令(此种方法需求设备swiftlint)。这将会闪现规则以及规则的一系列属性,比如是否可选,是否可纠正。

以下是 SwiftLint 0.46.5的默许规则:

swiftlint rules
+------------------------------------------+--------+-------------+------------------------+-------------+----------+---------------+
| identifier                               | opt-in | correctable | enabled in your config | kind        | analyzer | configuration |
+------------------------------------------+--------+-------------+------------------------+-------------+----------+---------------+
| anonymous_argument_in_multiline_closure  | yes    | no          | no                     | idiomatic   | no       | warning       |
| anyobject_protocol                       | yes    | yes         | no                     | lint        | no       | warning       |
| array_init                               | yes    | no          | no                     | lint        | no       | warning       |
| attributes                               | yes    | no          | no                     | style       | no       | warning, a... |
| balanced_xctest_lifecycle                | yes    | no          | no                     | lint        | no       | warning       |
| block_based_kvo                          | no     | no          | yes                    | idiomatic   | no       | warning       |
| capture_variable                         | yes    | no          | no                     | lint        | yes      | warning       |
| class_delegate_protocol                  | no     | no          | yes                    | lint        | no       | warning       |
| closing_brace                            | no     | yes         | yes                    | style       | no       | warning       |
| closure_body_length                      | yes    | no          | no                     | metrics     | no       | warning: 2... |
| closure_end_indentation                  | yes    | yes         | no                     | style       | no       | warning       |
| closure_parameter_position               | no     | no          | yes                    | style       | no       | warning       |
| closure_spacing                          | yes    | yes         | no                     | style       | no       | warning       |
| collection_alignment                     | yes    | no          | no                     | style       | no       | warning, a... |
| colon                                    | no     | yes         | yes                    | style       | no       | warning, f... |
| comma                                    | no     | yes         | yes                    | style       | no       | warning       |
| comment_spacing                          | no     | yes         | yes                    | lint        | no       | warning       |
| compiler_protocol_init                   | no     | no          | yes                    | lint        | no       | warning       |
| computed_accessors_order                 | no     | no          | yes                    | style       | no       | warning, o... |
| conditional_returns_on_newline           | yes    | no          | no                     | style       | no       | warning, i... |
| contains_over_filter_count               | yes    | no          | no                     | performance | no       | warning       |
| contains_over_filter_is_empty            | yes    | no          | no                     | performance | no       | warning       |
| contains_over_first_not_nil              | yes    | no          | no                     | performance | no       | warning       |
| contains_over_range_nil_comparison       | yes    | no          | no                     | performance | no       | warning       |
| control_statement                        | no     | yes         | yes                    | style       | no       | warning       |
| convenience_type                         | yes    | no          | no                     | idiomatic   | no       | warning       |
| custom_rules                             | no     | no          | no                     | style       | no       | user-defin... |
| cyclomatic_complexity                    | no     | no          | yes                    | metrics     | no       | warning: 1... |
| deployment_target                        | no     | no          | yes                    | lint        | no       | warning, i... |
| discarded_notification_center_observer   | yes    | no          | no                     | lint        | no       | warning       |
| discouraged_assert                       | yes    | no          | no                     | idiomatic   | no       | warning       |
| discouraged_direct_init                  | no     | no          | yes                    | lint        | no       | warning, t... |
| discouraged_none_name                    | yes    | no          | no                     | idiomatic   | no       | warning       |
| discouraged_object_literal               | yes    | no          | no                     | idiomatic   | no       | warning, i... |
| discouraged_optional_boolean             | yes    | no          | no                     | idiomatic   | no       | warning       |
| discouraged_optional_collection          | yes    | no          | no                     | idiomatic   | no       | warning       |
| duplicate_enum_cases                     | no     | no          | yes                    | lint        | no       | error         |
| duplicate_imports                        | no     | no          | yes                    | idiomatic   | no       | warning       |
| duplicated_key_in_dictionary_literal     | no     | no          | yes                    | lint        | no       | warning       |
| dynamic_inline                           | no     | no          | yes                    | lint        | no       | error         |
| empty_collection_literal                 | yes    | no          | no                     | performance | no       | warning       |
| empty_count                              | yes    | no          | no                     | performance | no       | error, onl... |
| empty_enum_arguments                     | no     | yes         | yes                    | style       | no       | warning       |
| empty_parameters                         | no     | yes         | yes                    | style       | no       | warning       |
| empty_parentheses_with_trailing_closure  | no     | yes         | yes                    | style       | no       | warning       |
| empty_string                             | yes    | no          | no                     | performance | no       | warning       |
| empty_xctest_method                      | yes    | no          | no                     | lint        | no       | warning       |
| enum_case_associated_values_count        | yes    | no          | no                     | metrics     | no       | warning: 5... |
| expiring_todo                            | yes    | no          | no                     | lint        | no       | (approachi... |
| explicit_acl                             | yes    | no          | no                     | idiomatic   | no       | warning       |
| explicit_enum_raw_value                  | yes    | no          | no                     | idiomatic   | no       | warning       |
| explicit_init                            | yes    | yes         | no                     | idiomatic   | no       | warning       |
| explicit_self                            | yes    | yes         | no                     | style       | yes      | warning       |
| explicit_top_level_acl                   | yes    | no          | no                     | idiomatic   | no       | warning       |
| explicit_type_interface                  | yes    | no          | no                     | idiomatic   | no       | warning, e... |
| extension_access_modifier                | yes    | no          | no                     | idiomatic   | no       | warning       |
| fallthrough                              | yes    | no          | no                     | idiomatic   | no       | warning       |
| fatal_error_message                      | yes    | no          | no                     | idiomatic   | no       | warning       |
| file_header                              | yes    | no          | no                     | style       | no       | warning, r... |
| file_length                              | no     | no          | yes                    | metrics     | no       | warning: 4... |
| file_name                                | yes    | no          | no                     | idiomatic   | no       | (severity)... |
| file_name_no_space                       | yes    | no          | no                     | idiomatic   | no       | (severity)... |
| file_types_order                         | yes    | no          | no                     | style       | no       | warning, o... |
| first_where                              | yes    | no          | no                     | performance | no       | warning       |
| flatmap_over_map_reduce                  | yes    | no          | no                     | performance | no       | warning       |
| for_where                                | no     | no          | yes                    | idiomatic   | no       | warning       |
| force_cast                               | no     | no          | yes                    | idiomatic   | no       | error         |
| force_try                                | no     | no          | yes                    | idiomatic   | no       | error         |
| force_unwrapping                         | yes    | no          | no                     | idiomatic   | no       | warning       |
| function_body_length                     | no     | no          | yes                    | metrics     | no       | warning: 4... |
| function_default_parameter_at_end        | yes    | no          | no                     | idiomatic   | no       | warning       |
| function_parameter_count                 | no     | no          | yes                    | metrics     | no       | warning: 5... |
| generic_type_name                        | no     | no          | yes                    | idiomatic   | no       | (min_lengt... |
| ibinspectable_in_extension               | yes    | no          | no                     | lint        | no       | warning       |
| identical_operands                       | yes    | no          | no                     | lint        | no       | warning       |
| identifier_name                          | no     | no          | yes                    | style       | no       | (min_lengt... |
| implicit_getter                          | no     | no          | yes                    | style       | no       | warning       |
| implicit_return                          | yes    | yes         | no                     | style       | no       | warning, i... |
| implicitly_unwrapped_optional            | yes    | no          | no                     | idiomatic   | no       | warning, m... |
| inclusive_language                       | no     | no          | yes                    | style       | no       | warning, a... |
| indentation_width                        | yes    | no          | no                     | style       | no       | severity: ... |
| inert_defer                              | no     | no          | yes                    | lint        | no       | warning       |
| is_disjoint                              | no     | no          | yes                    | idiomatic   | no       | warning       |
| joined_default_parameter                 | yes    | yes         | no                     | idiomatic   | no       | warning       |
| large_tuple                              | no     | no          | yes                    | metrics     | no       | warning: 2... |
| last_where                               | yes    | no          | no                     | performance | no       | warning       |
| leading_whitespace                       | no     | yes         | yes                    | style       | no       | warning       |
| legacy_cggeometry_functions              | no     | yes         | yes                    | idiomatic   | no       | warning       |
| legacy_constant                          | no     | yes         | yes                    | idiomatic   | no       | warning       |
| legacy_constructor                       | no     | yes         | yes                    | idiomatic   | no       | warning       |
| legacy_hashing                           | no     | no          | yes                    | idiomatic   | no       | warning       |
| legacy_multiple                          | yes    | no          | no                     | idiomatic   | no       | warning       |
| legacy_nsgeometry_functions              | no     | yes         | yes                    | idiomatic   | no       | warning       |
| legacy_objc_type                         | yes    | no          | no                     | idiomatic   | no       | warning       |
| legacy_random                            | yes    | no          | no                     | idiomatic   | no       | warning       |
| let_var_whitespace                       | yes    | no          | no                     | style       | no       | warning       |
| line_length                              | no     | no          | yes                    | metrics     | no       | warning: 1... |
| literal_expression_end_indentation       | yes    | yes         | no                     | style       | no       | warning       |
| lower_acl_than_parent                    | yes    | no          | no                     | lint        | no       | warning       |
| mark                                     | no     | yes         | yes                    | lint        | no       | warning       |
| missing_docs                             | yes    | no          | no                     | lint        | no       | warning: o... |
| modifier_order                           | yes    | yes         | no                     | style       | no       | warning, p... |
| multiline_arguments                      | yes    | no          | no                     | style       | no       | warning, f... |
| multiline_arguments_brackets             | yes    | no          | no                     | style       | no       | warning       |
| multiline_function_chains                | yes    | no          | no                     | style       | no       | warning       |
| multiline_literal_brackets               | yes    | no          | no                     | style       | no       | warning       |
| multiline_parameters                     | yes    | no          | no                     | style       | no       | warning, a... |
| multiline_parameters_brackets            | yes    | no          | no                     | style       | no       | warning       |
| multiple_closures_with_trailing_closure  | no     | no          | yes                    | style       | no       | warning       |
| nesting                                  | no     | no          | yes                    | metrics     | no       | (type_leve... |
| nimble_operator                          | yes    | yes         | no                     | idiomatic   | no       | warning       |
| no_extension_access_modifier             | yes    | no          | no                     | idiomatic   | no       | error         |
| no_fallthrough_only                      | no     | no          | yes                    | idiomatic   | no       | warning       |
| no_grouping_extension                    | yes    | no          | no                     | idiomatic   | no       | warning       |
| no_space_in_method_call                  | no     | yes         | yes                    | style       | no       | warning       |
| notification_center_detachment           | no     | no          | yes                    | lint        | no       | warning       |
| nslocalizedstring_key                    | yes    | no          | no                     | lint        | no       | warning       |
| nslocalizedstring_require_bundle         | yes    | no          | no                     | lint        | no       | warning       |
| nsobject_prefer_isequal                  | no     | no          | yes                    | lint        | no       | warning       |
| number_separator                         | yes    | yes         | no                     | style       | no       | warning, m... |
| object_literal                           | yes    | no          | no                     | idiomatic   | no       | warning, i... |
| opening_brace                            | no     | yes         | yes                    | style       | no       | warning, a... |
| operator_usage_whitespace                | yes    | yes         | no                     | style       | no       | warning, l... |
| operator_whitespace                      | no     | no          | yes                    | style       | no       | warning       |
| optional_enum_case_matching              | yes    | yes         | no                     | style       | no       | warning       |
| orphaned_doc_comment                     | no     | no          | yes                    | lint        | no       | warning       |
| overridden_super_call                    | yes    | no          | no                     | lint        | no       | warning, e... |
| override_in_extension                    | yes    | no          | no                     | lint        | no       | warning       |
| pattern_matching_keywords                | yes    | no          | no                     | idiomatic   | no       | warning       |
| prefer_nimble                            | yes    | no          | no                     | idiomatic   | no       | warning       |
| prefer_self_in_static_references         | yes    | yes         | no                     | style       | no       | N/A           |
| prefer_self_type_over_type_of_self       | yes    | yes         | no                     | style       | no       | warning       |
| prefer_zero_over_explicit_init           | yes    | yes         | no                     | idiomatic   | no       | warning       |
| prefixed_toplevel_constant               | yes    | no          | no                     | style       | no       | warning, o... |
| private_action                           | yes    | no          | no                     | lint        | no       | warning       |
| private_outlet                           | yes    | no          | no                     | lint        | no       | warning, a... |
| private_over_fileprivate                 | no     | yes         | yes                    | idiomatic   | no       | warning, v... |
| private_subject                          | yes    | no          | no                     | lint        | no       | warning       |
| private_unit_test                        | no     | no          | yes                    | lint        | no       | warning: X... |
| prohibited_interface_builder             | yes    | no          | no                     | lint        | no       | warning       |
| prohibited_super_call                    | yes    | no          | no                     | lint        | no       | warning, e... |
| protocol_property_accessors_order        | no     | yes         | yes                    | style       | no       | warning       |
| quick_discouraged_call                   | yes    | no          | no                     | lint        | no       | warning       |
| quick_discouraged_focused_test           | yes    | no          | no                     | lint        | no       | warning       |
| quick_discouraged_pending_test           | yes    | no          | no                     | lint        | no       | warning       |
| raw_value_for_camel_cased_codable_enum   | yes    | no          | no                     | lint        | no       | warning       |
| reduce_boolean                           | no     | no          | yes                    | performance | no       | warning       |
| reduce_into                              | yes    | no          | no                     | performance | no       | warning       |
| redundant_discardable_let                | no     | yes         | yes                    | style       | no       | warning       |
| redundant_nil_coalescing                 | yes    | yes         | no                     | idiomatic   | no       | warning       |
| redundant_objc_attribute                 | no     | yes         | yes                    | idiomatic   | no       | warning       |
| redundant_optional_initialization        | no     | yes         | yes                    | idiomatic   | no       | warning       |
| redundant_set_access_control             | no     | no          | yes                    | idiomatic   | no       | warning       |
| redundant_string_enum_value              | no     | no          | yes                    | idiomatic   | no       | warning       |
| redundant_type_annotation                | yes    | yes         | no                     | idiomatic   | no       | warning       |
| redundant_void_return                    | no     | yes         | yes                    | idiomatic   | no       | warning       |
| required_deinit                          | yes    | no          | no                     | lint        | no       | warning       |
| required_enum_case                       | yes    | no          | no                     | lint        | no       | No protoco... |
| return_arrow_whitespace                  | no     | yes         | yes                    | style       | no       | warning       |
| self_in_property_initialization          | no     | no          | yes                    | lint        | no       | warning       |
| shorthand_operator                       | no     | no          | yes                    | style       | no       | error         |
| single_test_class                        | yes    | no          | no                     | style       | no       | warning       |
| sorted_first_last                        | yes    | no          | no                     | performance | no       | warning       |
| sorted_imports                           | yes    | yes         | no                     | style       | no       | warning       |
| statement_position                       | no     | yes         | yes                    | style       | no       | (statement... |
| static_operator                          | yes    | no          | no                     | idiomatic   | no       | warning       |
| strict_fileprivate                       | yes    | no          | no                     | idiomatic   | no       | warning       |
| strong_iboutlet                          | yes    | yes         | no                     | lint        | no       | warning       |
| superfluous_disable_command              | no     | no          | yes                    | lint        | no       | warning       |
| switch_case_alignment                    | no     | no          | yes                    | style       | no       | warning, i... |
| switch_case_on_newline                   | yes    | no          | no                     | style       | no       | warning       |
| syntactic_sugar                          | no     | yes         | yes                    | idiomatic   | no       | warning       |
| test_case_accessibility                  | yes    | yes         | no                     | lint        | no       | warning, a... |
| todo                                     | no     | no          | yes                    | lint        | no       | warning       |
| toggle_bool                              | yes    | yes         | no                     | idiomatic   | no       | warning       |
| trailing_closure                         | yes    | no          | no                     | style       | no       | warning, o... |
| trailing_comma                           | no     | yes         | yes                    | style       | no       | warning, m... |
| trailing_newline                         | no     | yes         | yes                    | style       | no       | warning       |
| trailing_semicolon                       | no     | yes         | yes                    | idiomatic   | no       | warning       |
| trailing_whitespace                      | no     | yes         | yes                    | style       | no       | warning, i... |
| type_body_length                         | no     | no          | yes                    | metrics     | no       | warning: 2... |
| type_contents_order                      | yes    | no          | no                     | style       | no       | warning, o... |
| type_name                                | no     | no          | yes                    | idiomatic   | no       | (min_lengt... |
| unavailable_function                     | yes    | no          | no                     | idiomatic   | no       | warning       |
| unneeded_break_in_switch                 | no     | no          | yes                    | idiomatic   | no       | warning       |
| unneeded_parentheses_in_closure_argument | yes    | yes         | no                     | style       | no       | warning       |
| unowned_variable_capture                 | yes    | no          | no                     | lint        | no       | warning       |
| untyped_error_in_catch                   | yes    | yes         | no                     | idiomatic   | no       | warning       |
| unused_capture_list                      | no     | no          | yes                    | lint        | no       | warning       |
| unused_closure_parameter                 | no     | yes         | yes                    | lint        | no       | warning       |
| unused_control_flow_label                | no     | yes         | yes                    | lint        | no       | warning       |
| unused_declaration                       | yes    | no          | no                     | lint        | yes      | severity: ... |
| unused_enumerated                        | no     | no          | yes                    | idiomatic   | no       | warning       |
| unused_import                            | yes    | yes         | no                     | lint        | yes      | severity: ... |
| unused_optional_binding                  | no     | no          | yes                    | style       | no       | warning, i... |
| unused_setter_value                      | no     | no          | yes                    | lint        | no       | warning       |
| valid_ibinspectable                      | no     | no          | yes                    | lint        | no       | warning       |
| vertical_parameter_alignment             | no     | no          | yes                    | style       | no       | warning       |
| vertical_parameter_alignment_on_call     | yes    | no          | no                     | style       | no       | warning       |
| vertical_whitespace                      | no     | yes         | yes                    | style       | no       | warning, m... |
| vertical_whitespace_between_cases        | yes    | yes         | no                     | style       | no       | warning       |
| vertical_whitespace_closing_braces       | yes    | yes         | no                     | style       | no       | N/A           |
| vertical_whitespace_opening_braces       | yes    | yes         | no                     | style       | no       | N/A           |
| void_return                              | no     | yes         | yes                    | style       | no       | warning       |
| weak_delegate                            | yes    | yes         | no                     | lint        | no       | warning       |
| xct_specific_matcher                     | yes    | no          | no                     | idiomatic   | no       | warning       |
| xctfail_message                          | no     | no          | yes                    | idiomatic   | no       | warning       |
| yoda_condition                           | yes    | no          | no                     | lint        | no       | warning       |
+------------------------------------------+--------+-------------+------------------------+-------------+----------+---------------+

在终端工作 SwiftLint

SwiftLint 可以配备为一个库房预提交的钩子,用以保证提交代码的风格共同。它也可以在终端中作为指令工作,只需在项目目录中工作swiftlint即可。工作swiftlint --help查看更多选项。

swiftlint --help
OVERVIEW: A tool to enforce Swift style and conventions.
USAGE: swiftlint <subcommand>
OPTIONS:
  --version               Show the version.
  -h, --help              Show help information.
SUBCOMMANDS:
  analyze                 Run analysis rules
  docs                    Open SwiftLint documentation website in the default web browser
  generate-docs           Generates markdown documentation for all rules
  lint (default)          Print lint warnings and errors
  rules                   Display the list of rules and their identifiers
  version                 Display the current version of SwiftLint
  See 'swiftlint help <subcommand>' for detailed help.

在(之前新建的项目)HelloSwiftLintApp(目录下)在终端工作swiftlint相同会闪现违背了trailing_whitespace规则。

swiftlint
Linting Swift files in current working directory
Linting 'HelloSwiftLintApp.swift' (1/2)
Linting 'ContentView.swift' (2/2)
...HelloSwiftLint/ContentView.swift:13:1: warning: Trailing Whitespace Violation: Lines should not have trailing whitespace. (trailing_whitespace)
Done linting! Found 1 violation, 0 serious in 2 files.

自动修正 SwiftLint 冲突

从上面的规则列表可以看出,有一些规则是可以自动修正的。这是直接针对间距规则的,就像上面介绍的额外空格一样。只要可以进行 SwiftLint 剖析,就可以进行 SwiftLint 自动修正。

在终端工作swiftlint --fix就会自动修正那些可以被自动修正的 SwiftLint 冲突。

swiftlint --fix
Correcting Swift files in current working directory
Correcting 'HelloSwiftLintApp.swift' (1/2)
Correcting 'ContentView.swift' (2/2)
.../HelloSwiftLint/ContentView.swift:13:1 Corrected Trailing Whitespace
Done inspecting 2 files for auto-correction!

或许,可以将自动修正整合到 Xcode 的Build Phase。修正”Run Script Phase“下的 SwiftLint 脚本。现在,在 Xcode 中编译代码时,添加跟随空格会自动删去。

export PATH="$PATH:/opt/homebrew/bin"
if which swiftlint > /dev/null; then
  swiftlint --fix && swiftlint
else
  echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint"
fi

用 SwiftLint 坚持 Swift 风格共同


手动修正 SwiftLint 规则冲突

并非全部的规则冲突都可以自动修正。关于 SwiftLint 剖析生成的警告以及差错,有许多种处理方法。假设只要一到两个冲突,最好的方法是修正它们,然后持续。

处理 SwiftLint 冲突的一些选项:

1. 修正代码以契合 SwiftLint 规则
2. 在代码中添加特例,以疏忽特定的规则冲突
3. 为项目定制 SwiftLint 规则
4. 疏忽这些警告 -- 这不是一个好的选项

修正冲突是最好的方法,当 SwiftLint 从项意图一初步就被整合时,这可以很简略的被完成。

下面是我写的示例代码,它遍历了 vertices 数组,创建了一条途径。运用enumerated方法生成了索引以及数据项,运用单个字符n作为变量名会导致编译时差错,仅运用字符作为变量名会导致编译时警告。

for (n, pt) in vertices.enumerated() {
     n == 0 ? path.move(to: pt) : path.addLine(to: pt)
}

这些“**标识符称谓”(identifier-name)**冲突不能被自动修正。为此类冲突创建一些破例或许会很有诱惑力,但是从长远来看,(此类规则)将有助于代码的可读性以及可维护性。

for (index, point) in vertices.enumerated() {
     index == 0 ? path.move(to: point) : path.addLine(to: point)
}

我发现关于enumerated苹果的示例代码存在着相同的问题!

用 SwiftLint 坚持 Swift 风格共同

SwiftLint 的标识符冲突无法被修正


一些规则的破例情况

在某些情况下,代码需求与某些外部API或数据源兼容。Open Weather API供应了如Read JSON with codeable in Swift中所描绘的 JSON 数据。这些气候数据中main数据段含有一些有下划线的标识符,比如,feels_like 。用于 Swift 解码此 JSON 的结构体必须与 JSON 中的字段称谓匹配,因为 SwiftLint 的”***identifier_name***”规则,Swift 代码会产生编译时差错。

气候数据的示例 JSON

{
    "coord": {
        "lon": -122.08,
        "lat": 37.39
    },
    "weather": [
        {
            "id": 800,
            "main": "Clear",
            "description": "clear sky",
            "icon": "01d"
        }
    ],
    "base": "stations",
    "main": {
        "temp": 9.4,
        "feels_like": 8.71,
        "temp_min": 7.22,
        "temp_max": 11.11,
        "pressure": 1023,
        "humidity": 100,
        "sea_level": 100
    },
    "visibility": 16093,
    "wind": {
        "speed": 1.5,
        "deg": 350
    },
    "clouds": {
        "all": 1
    },
    "dt": 1560350645,
    "sys": {
        "type": 1,
        "id": 5122,
        "message": 0.0139,
        "country": "US",
        "sunrise": 1560343627,
        "sunset": 1560396563
    },
    "timezone": -25200,
    "id": 420006353,
    "name": "Mountain View",
    "cod": 200
}
struct WeatherRawData: Codable {
    var name: String
    var timezone: Double
    var weather: [WeatherData]
    var main: MainData
    var wind: WindData
    var clouds: CloudsData
    struct WeatherData: Codable {
        var id: Double
        var main: String
        var description: String
        var icon: String
    }
    struct MainData: Codable {
        var temp: Double
        var feels_like: Double
        var temp_min: Double
        var temp_max: Double
        var pressure: Double
        var humidity: Double
    }
    struct WindData: Codable {
        var speed: Double
        var deg: Double
    }
    struct CloudsData: Codable {
        var all: Double
    }
}

用 SwiftLint 坚持 Swift 风格共同

不是每个(冲突)都需求被抛出。在这种情况下,可以在出现问题的代码之前简略地禁用 SwiftLint 规则,然后从头启用该规则。显着,假设这些启用/禁用代码片段在代码中到处都是,那就不太好了。这种技术应该谨慎地被运用。假设发现需求在多个方位禁用同一规则,请考虑为整个项目禁用该规则。

struct WeatherRawData: Codable {
    var name: String
    var timezone: Double
    var weather: [WeatherData]
    var main: MainData
    var wind: WindData
    var clouds: CloudsData
    struct WeatherData: Codable {
        var id: Double
        var main: String
        var description: String
        var icon: String
    }
    // swiftlint:disable identifier_name
    struct MainData: Codable {
        var temp: Double
        var feels_like: Double
        var temp_min: Double
        var temp_max: Double
        var pressure: Double
        var humidity: Double
    }
    // swiftlint:enable identifier_name
    struct WindData: Codable {
        var speed: Double
        var deg: Double
    }
    struct CloudsData: Codable {
        var all: Double
    }
}

用 SwiftLint 坚持 Swift 风格共同


不要急于禁用规则

偶尔会有一些 SwiftLint 规则的特例,但是不要急于禁用规则。在上面的比如中,有一种更好的方法,可以运用CodingKeys将 Swift 变量名映射到 JSON 内容。与其注释 SwiftLint 规则,不如运用属性名feelsLike并指定feels_like的可选值来匹配JSON数据。

// swiftlint:disable identifier_name
    struct MainData: Codable {
        var temp: Double
        var feels_like: Double
        var temp_min: Double
        var temp_max: Double
        var pressure: Double
        var humidity: Double
    }
    // swiftlint:enable identifier_name
struct MainData: Codable {
    let temp: Double
    let feelsLike: Double
    let tempMin: Double
    let tempMax: Double
    let pressure: Double
    let humidity: Double
    enum CodingKeys: String, CodingKey {
        case temp
        case feelsLike = "feels_like"
        case tempMin = "temp_min"
        case tempMax = "temp_max"
        case pressure
        case humidity
    }
}

用 SwiftLint 坚持 Swift 风格共同

运用 CodingKeys 来映射 JSON 变量好于禁用 SwiftLint 规则


自定义 SwiftLint 规则

假设将 SwiftLint 添加到闪现数百个问题的现有项目中,“修正全部冲突”的方法或许非常困难。在这种情况下,将 SwiftLint 配备添加到项目中或许更适宜。这是一个YAML文件,在该文件中可以禁用规则,列出挑选打开的规则,或许将规则仅限于此文件中的规则。这样, SwiftLint 就可以无限定制。有关更多详细信息,请参阅SwiftLint配备部分。

警告的一个比如是代码中存在 TODO 注释。SwiftLint 将这些 TODO 标记为警告,以表明这些当地还有未完成的作业。

用 SwiftLint 坚持 Swift 风格共同

TODO 注释被 SwiftLint 默许编译成一个警告

许多时分你既想兼并代码时保存这些 TODO,也期望在编译时没有这些警告。可以在每个单独的TODO注释前面加disable/enable,也可以在.swiftlint.yml文件中来禁用整个整个项意图此规则。将下方的.swiftlint.yml文件添加到项目中,会答应项目编译而不生成 TODO 注释警告,其他规则不受影响。

disabled_rules: # rule identifiers to exclude from running
  - todo
struct ContentView: View {
    var body: some View {
        VStack {
            Text("Hello, world!")
            // TODO: Remove this function when done
            let a = 24
            Text("second line \(a)")
            Spacer()
        }
    }
}

用 SwiftLint 坚持 Swift 风格共同

TODO 注释没有构成警告,其他规则不受影响

在已有的规则上运用 SwiftLint 最简略的方法是:

  1. 设备 SwiftLint
  2. 经过编译阶段脚本,将 SwiftLint 整合进 Xcode 项目中
  3. 编译以点评全部警告和差错
  4. 添加.swiftlint.yml文件,并禁用冲突数最多的规则
  5. 一次启用一条规则并修正代码中的问题

结论

关于任何 Swift 开发者来说,运用 SwiftLint 都是必要的。它有助于避免团队中关于代码样式的争辩,以及建立代码风格的统一性。就我而言,它帮我摆脱了诸如创建单字符标识符等坏习惯。

将 SwiftLint 添加到已有的代码库或许比添加到新项目要杂乱得多,因为它或许会闪现数百个警告和差错。经过配备规则,并逐渐打开更多的规则,可以在现有项目中选用 SwiftLint。

SwiftLint 的自动修正冲突的才干非常强大,经过自动修正冲突可以显着处理数百个冲突的初始情况。只需求保证代码在进行大范围的自动更改之前已经纳入了版别操控,这样在出问题时就能很简略吊销。


译者的一些补偿

关于 SwiftLint 的设备

设备的方法有几种,原文介绍的是运用 homebrew 设备。译者比较举荐直接运用**CocoaPods:**

pod 'SwiftLint', '0.46.5'

能明晰明了的指明项目运用了 SwiftLint ,一同也便利指定版别。

SwiftLint 不只仅能帮忙处理格式问题

SwiftLint 不只仅能处理许多格式问题,它的功用还有许多。比如限制一个函数参数的个数,函数、文件最长多少行,运用更精简,更Swift 的函数等等。这能在很大程度上帮忙我们写出高质量的代码。

许多团队同伴在写代码时,一初步的函数,文件或许没那么臃肿。但是随着功用的添加,不断地往一个函数添加参数,不断修正函数的功用,不断往一个文件添加新的函数等等,各个当地初步变得臃肿。当 SwiftLint 告知你函数参数个数超过了指定的个数,函数行数超过了最大值,文件超过了最大行数等等时,就应该仔细考虑是不是该重构了。

在已有项目中添加 SwiftLint

在添加 SwiftLint 之前,最重要的是整体应该开一个简略的会。用来同步以及确认规则。让全部人充沛表达意见,而不是一个人拟定,有些人不赞同。将一些不置可否的规则确认清楚之后,写入到 SwiftLint 配备傍边,全部人都应该遵循。

译者的项目非常的巨大,刚添加 SwiftLint 的时分,警告加差错高达5000多了,底子改不过来。我选用的方法是分途径配备 SwiftLint。那些比较老的,不怎么会动的目录选用较为宽松的配备。新起一个目录,之后的新代码原则上都应该在此目录之下。此目录的配备会较为严峻。

Hook git pre-commit在提交之前做规则查看,如有问题,直接报错,无法提交代码。这样就不会产生新的警告和差错,渐渐的再修正之前的代码,经过1年多,整个项目基本就覆盖全了。

其他,关于项意图警告也需求管理,许多时分有些成员写代码的时分无视警告,导致项目警告几百个,而且越来越多。这就导致警告失去了它原有的作用,译者项意图警告是0,可以很轻松的定位哪个当地发出了新的警告。一同代码 Review 也非常重要,有些成员为了避免费事,各个当地都直接 disable 了 SwiftLint 的规则,这是不应该的。

最后,永久记住你只是在运用的只是一个东西,而不是意图。请充沛衡量本钱和收益。

我正在参与技术社区创作者签约方案招募活动,点击链接报名投稿。