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.
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 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.
@IBOutlet
s shouldn’t be declared as weak SW-W1020By 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.
Force unwrapping should be avoided in Swift as it can lead to runtime errors and crashes. Force unwrapping is when an optional value is forcefully unwrapped using the exclamation mark (!) operator without checking if the value is nil or not. This can result in a fatal error if the optional value is actually nil at runtime.
deinit
SW-W1028When an object registers itself as an observer for notifications using the NotificationCenter API, it is responsible for removing itself as an observer when it is no longer needed. This is typically done in the deinit
method of the object. By removing itself as an observer in deinit
, the object ensures that it will no longer receive notifications after it has been deallocated. If an object removes itself as an observer outside of its deinit
method, it can lead to unexpected behavior. For example, if the object is deallocated before it removes itself as an observer, the notification center will still try to send notifications to the deallocated object, resulting in a crash.
Delegates in Swift should be declared as weak to avoid creating reference cycles. When a delegate is strongly referenced by the object it is delegating to, a retain cycle can occur preventing both objects from being deallocated and causing a memory leak.
This issue occurs when there are duplicate keys in a Swift dictionary. A dictionary is a collection data type that stores key-value pairs. Each key in a dictionary is unique, and it maps to a single value. When a dictionary contains duplicate keys, it leads to confusing and error-prone behavior.
nil
coalescing operator is never evaluated as it's in RHS SW-R1010Using the nil coalescing operator (??
) in Swift can be helpful to provide default values when dealing with optional types. However, it can be easy to fall into the trap of using it unnecessarily, leading to redundant code that
Duplicate conditions in branch instruction is likely a mistake and can lead to confusion and unexpected behavior in your code. In particular, having multiple if statements in an if-else chain with the same condition is redundant and can make your code harder to read and maintain. This can also lead to logical errors and unexpected side effects.
@IBInspectable
should be applied to variables only, have its type explicit and be of a supported type SW-W1006The @IBInspectable
attribute in Swift is used to expose properties to Interface Builder, allowing them to be configured visually. However, there are certain guidelines and restrictions that should be followed when using this attribute. The issue arises when the @IBInspectable
attribute is applied to something other than a variable, or when the type of the variable is not explicit or not one of the supported types (boolean, integer or floating point number, string, localized string, rectangle, point, size, color, range, and nil).
Enum should always have unique cases as having multiple cases with the same name can lead to unintended behavior. When cases in enum are not unique, it can cause confusion and make the code difficult to maintain. This is especially true when the cases are mapped to different values.
try!
statements should be avoided SW-W1008Force tries in Swift should be avoided as they can lead to runtime errors and make error handling difficult. Force tries are denoted by using a try!
statement before a throwing function call. It basically makes an assertion that although the function has the ability to throw an error, it will not throw in this particular scenario and you want to skip the error handling.
Unused control flow labels in Swift should be removed as they can clutter the code and make it harder to read and understand. Control flow labels are used to specify which loop or conditional statement to break or continue when there are multiple nested loops or conditional statements. However, if a label is not used, it should be removed to avoid unnecessary complexity and confusion.
Casting is a way to convert an instance of one type to another. Swift's type system is designed to be safe, and casts can lead to unexpected errors if done incorrectly. Why is this an issue:
unavailable
SW-W1014Unimplemented functions in Swift code can cause confusion for users who may think the function is available to use. This can lead to runtime errors and unexpected behavior. To prevent this issue, it's recommended to mark any unimplemented functions as unavailable using the @available
attribute. This communicates to users that the function is not yet implemented and should not be used.
private
are silently skipped SW-W1016Marking unit tests as private in Swift can lead to several issues and is generally considered a bad practice. Here are a few reasons why: Test Visibility: Unit tests are essential for verifying the correctness of your code. By marking tests as private, you limit their visibility only to the file where they are defined.
NSObject.self()
method, which is likely not expected SW-W1017When using self
inside a Swift class or struct, it normally refers to the instance of the class or struct. However, in certain cases, if self
is used in conjunction with the NSObject
class, it can unintentionally refer to the NSObject.self()
method instead of the instance of the class. This can lead to unexpected behavior and subtle bugs.
ExpressibleByArrayLiteral
shouldn’t be called directly SW-W1027Compiler protocols like ExpressibleByArrayLiteral
define a contract that types adopting the protocol must adhere to. By calling the initializer directly, you bypass this contract and can potentially create instances that do not conform to the expected behavior defined by the protocol. This can lead to runtime errors and unpredictable results. Compiler protocols often provide a convenient way to initialize instances of a type using literals. By calling the initializer directly, you lose the type safety that the protocol provides. This can lead to code that is harder to understand, maintain, and debug.
Using void functions with ternary operators can lead to unexpected behavior and should be avoided. When using a ternary operator, there must be a return value in both cases. If a void function is used as one of the return values, the function will be executed but the result will not be used. This can lead to confusion for other developers reading the code, as it may not be clear what the intended behavior is.