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.

Use of unrestricted base URL in web view SW-S1000
Security
Critical

When a web view loads content from a source (like a web page or HTML string), it can also make additional network requests to fetch resources such as images, scripts, stylesheets, etc. If the base URL for these requests is not properly restricted, an attacker could craft URLs that point to local files or malicious websites. This can result in unintended data leakage or execution of malicious scripts.

Function with cyclomatic complexity higher than threshold SW-R1002
Anti-pattern
Minor

A function with high cyclomatic complexity can be hard to understand and maintain. Cyclomatic complexity is a software metric that measures the number of independent paths through a function. A higher cyclomatic complexity indicates that the function has more decision points and is more complex.

Use of insufficient number of iterations during hash computation SW-S1001
Security
Critical

The number of iterations in the password hashing process directly impacts the computational complexity and time it takes to compute the hash. A low number of iterations can be easily computed by attackers, allowing them to use techniques like brute force or rainbow table attacks to quickly crack the hashed passwords.

Use of an insecure version of TLS protocol SW-S1002
Security
Critical

Choosing secure TLS versions in your app is important because using outdated or vulnerable TLS versions can expose your app's communication to potential attacks. Malicious actors could take advantage of known vulnerabilities in these older TLS versions to intercept sensitive information, compromise user privacy, or perform other malicious actions. TLS versions 1.0 and 1.1 have been found to have several vulnerabilities.

Use of an insecure block cipher mode SW-S1003
Security
Critical

ECB encrypts identical plaintext blocks into identical ciphertext blocks. This means that if the same plaintext block appears multiple times in the message, it will result in the same ciphertext block. This behavior makes the encryption vulnerable to certain attacks, such as replay attacks, where an attacker can intercept and replay the encrypted blocks to recreate the original message.

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:

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.