Swift

Swift

Made by DeepSource
Prefer using min() or max() over sorted().first or sorted().last SW-P1011
Performance
Major
Autofix

Using sorted().first or sorted().last can be inefficient, as the entire collection needs to be sorted, which is not required if we only need the minimum or maximum element. This can cause performance issues, especially when dealing with large collections.

Prefer using .first(where:) over .filter { }.first in collections SW-P1007
Performance
Major
Autofix

Using .first(where:) instead of .filter { }.first in collections, can result in cleaner and more efficient code.

Prefer using .last(where:) over .filter { }.last in collections SW-P1009
Performance
Minor
Autofix

Using .filter {}.last to get the last element of a collection is less efficient than using .last(where:). The former method first iterates through the entire collection to filter the elements and then returns the last element. This is less efficient because it allocates an intermediate buffer/allocation.

Prefer contains over range(of:) != nil and range(of:) == nil SW-P1012
Performance
Major
Autofix

Using range(of:) != nil and range(of:) == nil instead of contains can lead to slower performance and less readable code.

Prefer using Array(seq) over seq.map { $0 } to convert a sequence into an Array SW-R1000
Anti-pattern
Major
Autofix

Using 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.

Audit: Use of legacy functions to generate random values can be insecure SW-A1000
Security
Critical

Legacy functions like arc4random() or arc4random_uniform() should not be used for generating random numbers. These functions are provided through imported C APIs, and depending on the platform that is executing the code, their underlying implementations can be unsafe.

TODOs and FIXMEs should be resolved SW-D1000
Documentation
Minor

TODO/FIXME comments are usually placed within the source code to indicate that there might be a scenario that is either unaccounted for or that a feature requires further enhancements. In either way, they must be addressed when and where possible to avoid unintended side-effects or breakdown.

Shorthand syntactic sugar should be used, i.e. [Type] instead of Array<Type> SW-C1003
Style
Minor
Autofix

Using the shorthand syntactic sugar for defining arrays, i.e., [] instead of Array, can make the code more concise and readable. Here are some reasons why:

@objc is redundant when used with implicit Objective-C attribute SW-R1011
Anti-pattern
Minor
Autofix

The @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

Setter access control should be different from the variable's access level SW-R1013
Anti-pattern
Minor

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.

Avoid using unneeded break statements SW-R1018
Anti-pattern
Minor

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

Always specify message when invoking fatalError() SW-R1021
Anti-pattern
Major

When 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.

Do not name an enum member as none SW-R1025
Anti-pattern
Major

Using "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:

Fallthrough should be avoided SW-W1012
Bug risk
Minor

Using the fallthrough keyword in switch statements can lead to subtle and hard-to-find bugs in Swift. The fallthrough keyword allows the control flow to move to the next case in a switch statement. This can be useful in some cases, but it can also make the code harder to read and increase the risk of unexpected behavior.

Types used for hosting only static members should be implemented as a caseless enum to avoid instantiation SW-R1030
Anti-pattern
Minor

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.

String enum values can be omitted when they are equal to the enum case name SW-R1031
Anti-pattern
Minor

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.

An XCTFail call should include a description of the assertion SW-R1032
Anti-pattern
Major

When 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.

Unused setter value is likely a mistake SW-W1004
Bug risk
Critical

In Swift, setters should always access the value that is provided for the backing field. If a setter does not access this value, it is possible that the backing field contains a value other than what the user intended. This can result in unexpected behavior and is likely a mistake.

Comparing two identical operands is likely a mistake SW-W1015
Bug risk
Critical

Comparing two identical operands in a binary operator can be a mistake. If two identical operands are used in a binary operator, the result is always predictable and will always be true. This can lead to unintended consequences if the code is meant to compare two different variables.

@IBOutlets shouldn’t be declared as weak SW-W1020
Bug risk
Major
Autofix

By declaring @IBOutlets as weak, you are creating a weak reference to the outlet. Weak references do not keep the referenced object alive, meaning that the outlet can be deallocated if there are no other strong references to it. This can result in unexpected crashes or undefined behavior when accessing the outlet.