Array(seq)
over seq.map { $0 }
to convert a sequence into an Array SW-R1000Using the Array initializer Array(seq)
is a more concise and performant way of converting a sequence into an Array in Swift, as opposed to using seq.map { $0 }
. Here's why: Performance: When using seq.map { $0 }
to convert a sequence into an Array, the map
function creates a new array and copies all the elements from the sequence into the new array. The Array
initializer, on the other hand, creates an array with the exact same elements as the sequence, without any intermediate steps. This makes Array(seq)
more performant than seq.map { $0 }
for large sequences.
@objc
is redundant when used with implicit Objective-C attribute SW-R1011The @objc
attribute is used to expose Swift declarations to Objective-C code. However, it can be redundant in some cases, where the declaration is already implicitly @objc
, or it's not necessary for the declaration to be exposed to
This issue highlights the redundant use of access control for property setters in Swift. If the access level of the variable and the setter are the same, it's unnecessary to specify the access level for the setter explicitly.
Unneeded break
statements are often found in switch cases in Swift. These break
statements are redundant since they are executed automatically at the end of each case block. There is no harm in using break
explicitly, but it
fatalError()
SW-R1021When invoking fatalError()
in Swift, it is essential to provide a descriptive message to help with debugging and understanding the cause of the crash. This is because fatalError()
is essentially an assertion that always fails, and the message provided helps identify the source of the failure. If a message is not provided, it can be challenging to track down the issue that caused the crash. The developer would have to rely on the stack trace, which is often not sufficient to identify the root cause of the problem.
none
SW-R1025Using "none" as a member name in an enum may create ambiguity and confusion while working with optional values. This is because Optional.none
is a reserved keyword in Swift, and using it as a member name in an enum may conflict with that. If you use "none" as a member name in an enum, it may lead to unexpected behavior when working with optional values. For example, consider the following code:
Types that are used solely for hosting static members should be implemented as a caseless enum in Swift. By using a caseless enum, you explicitly indicate that the type should not be instantiated. This helps prevent accidental creation of instances, which can lead to unnecessary memory allocation and potential misuse of the type.
When defining enum cases in Swift, it is unnecessary and redundant to explicitly specify the enum values when they are same as the enum case name. Redundantly specifying the enum values can lead to code duplication and increase the likelihood of mistakes.
XCTFail
call should include a description of the assertion SW-R1032When a test case fails, the XCTFail call is used to indicate the failure. However, without a description, it becomes challenging to determine the specific reason for the failure. This can lead to confusion and increase debugging time, especially when multiple assertions are present in the same test case. It is recommended to always include a descriptive message when using XCTFail to provide clarity and context for failed assertions.
fileprivate
should be avoided SW-R1027Using the fileprivate
modifier in Swift can lead to several issues and is generally considered a bad practice. Here are a few reasons why:
hash(into:)
function instead of overriding hashValue
SW-R1001Overriding the hashValue
property in Swift for custom types is now considered an anti-pattern. Instead, use the hash(into:)
function to generate hash values for your objects. Here are a few reasons why: Clarity: The hash(into:)
function is more explicit than hashValue
. It makes it clear that the intent is to generate a hash value and not just return a random integer. This helps other developers understand the purpose of the function and avoid common pitfalls.
When using closures in Swift with multiple parameters, it is often necessary to split the closure into multiple lines to improve readability. However, if the arguments are not named explicitly, it can be difficult to determine which argument a particular line refers to. This can lead to bugs and make the code harder to understand and maintain. To improve the readability and maintainability of your code, it is recommended to use named arguments in closures that span multiple lines. This makes it clear which argument each line is referring to, and can make the code much easier to follow.
where
clauses are preferred over a single if
inside a for
loop SW-R1005Prefer using where clauses over a single if statement to filter items inside a for loop. Using where clauses results in more readable and expressive code.
Legacy convenience functions are often used to initialize values in Swift. However, Swift constructors provide a better alternative for initializing objects. Here are some reasons why:
.zero
over explicit init with zero parameters SW-R1009Using the .zero
initializer in Swift is generally more readable and concise than using a custom initializer with zero arguments when initializing an object with default values. Here are a few reasons why:
Optional
initialization SW-R1012Initializing an optional variable with nil
in Swift is redundant. This is because Swift automatically initializes all optional variables with nil
by default. Initializing with nil
adds no value to the code and makes it more
Void
should be avoided SW-R1014Returning values from a function that is declared to return Void
is unnecessary and can lead to confusion and potential bugs in the code. Here are a few reasons why returning values from a Void
function should be avoided:
Declaring operators as free functions in Swift can lead to several issues and make the code harder to read and maintain.
#unavailable
/#available
instead of #available
/#unavailable
with an empty body SW-R1017Using the #available
and #unavailable
compiler directives with an empty body can be misleading and result in unintended behavior. It is recommended to use the #available
directive with a non-empty body or the #unavailable
Using extensions to override declarations in Swift can lead to unexpected and hard-to-debug behavior. This is because extensions are intended to add new functionality to a type, not to modify or replace existing functionality. Overriding declarations in extensions can cause confusion, as it can be unclear which declaration is in effect at any given time.