Swift

Optionals

  • If Statements and Forced Unwrapping
  • Optional Binding
  • Implicitly Unwrapped Optionals

Optional Chaining

  • Optional Chaining as an Alternative to Forced Unwrapping

Numeric Type Conversion

Use the Int type for all general-purpose integer constants and variables in your code, even if they’re known to be nonnegative. Using the default integer type in everyday situations means that integer constants and variables are immediately interoperable in your code and will match the inferred type for integer literal values.

Use other integer types only when they’re specifically needed for the task at hand, because of explicitly sized data from an external source, or for performance, memory usage, or other necessary optimization. Using explicitly sized types in these situations helps to catch any accidental value overflows and implicitly documents the nature of the data being used.

Assertions and Preconditions

Assertions and preconditions are checks that happen at runtime. You use them to make sure an essential condition is satisfied before executing any further code. If the Boolean condition in the assertion or precondition evaluates to true, code execution continues as usual. If the condition evaluates to false, the current state of the program is invalid; code execution ends, and your app is terminated.

Access Control

Swift’s access control model is based on the concept of modules and source files.

open you can access open classes and class members from any source file in the defining module or any module that imports that module. You can subclass an open class or override an open class member both within their defining module and any module that imports that module.

public allows the same access as open - any source file in any module - but has more restrictive subclassing and overriding. You can only subclass a public class within the same module. A public class member can only be overriden by subclasses in the same module. This is important if you are writing a framework. If you want a user of that framework to be able to subclass a class or override a method you must make it open.

internal allows use from any source file in the defining module but not from outside that module. This is the default access level.

fileprivate allows use only within the defining source file.

private allows use only from the enclosing declaration and new in Swift 4, to any extensions of that declaration in the same source file.

class Widget {
    private func privateMethod() {  }
    fileprivate func fileprivateMethod() {  }
}

class SpecialWidget: Widget {
    func start() {
        //privateMethod()      // No access to private method
        fileprivateMethod()  // fileprivate access allowed
    }
}

Defining a Capture List Each item in a capture list is a pairing of the weak or unowned keyword with a reference to a class instance (such as self) or a variable initialized with some value (such as delegate = self.delegate!). These pairings are written within a pair of square braces, separated by commas.

Place the capture list before a closure’s parameter list and return type if they are provided:

Common scenarios for retain cycles: delegates

If you need a non-optional self inside your closure, consider using an if let or guard let to get a strong, non-optional self inside the closure. Because you made this new, strong reference inside the Swift closure, you won’t be creating a retain cycle since this reference will be released at the end of the closure

Although it is good practice to capture self weakly in closures, it is not always necessary. Closures that are not retained by the self can capture it strongly without causing a retain cycle. A few common examples of this are

Capturing self strongly in these situations will not cause a retain cycle, but it also may not be what you want. For example, going back to GCD:

DispatchQueue.main.asyncAfter(deadline: .now() + 60) { self.doSomething() }Copy This closure will not run for another 60 seconds and will retain self until it does. This may be the behavior you want, but if you wanted self to be able to leave memory during this time, it would be better to capture it weakly and only run if self is still around:

DispatchQueue.main.asyncAfter(deadline: .now() + 60) { [weak self] in self?.doSomething() }

Detecting retain cycles

https://medium.com/mackmobile/avoiding-retain-cycles-in-swift-7b08d50fe3ef

https://medium.com/@vinodhswamy/strong-cycle-retain-cycle-in-swift-f452f07518b2

http://www.thomashanning.com/retain-cycles-weak-unowned-swift/

https://stablekernel.com/how-to-prevent-memory-leaks-in-swift-closures/

results matching ""

    No results matching ""