App Development with Swift flashcards
App Development with Swift · Build recall with a focused review session.
32 cards. Read the term and the definition here. The deck at the top of this page is optional.
- let versus var
- let declares a constant that may be assigned only once; var declares a mutable variable. Both infer their type at compile time from the initializer.
- Type inference
- The compiler derives a declaration's type from its initializer, so writing let count = 0 gives count the type Int without any explicit annotation.
- Value type copying
- Structures, enumerations, and tuples are value types: assigning or passing one copies it, so mutating the copy never changes the original value.
- Explicit numeric conversion
- Swift never converts between numeric types implicitly. Writing Int(3.9) truncates toward zero, and a Double must be converted explicitly before use in Int arithmetic.
- Identity operator
- The === operator reports whether two class references point to the same instance, while == reports value equality and requires the type to conform to Equatable.
- Access control levels
- From narrowest to widest: private limits use to the enclosing declaration and same-file extensions, fileprivate to the file, internal to the module as the default, then public and open.
- Switch exhaustiveness and fallthrough
- A switch must cover every possible value of the matched type, and each case ends automatically; only the fallthrough keyword continues execution into the following case body.
- guard else must exit
- A guard statement requires its else block to leave the current scope by returning, breaking, continuing, throwing, or calling a Never-returning function; successful bindings stay in scope afterwards.
- Default argument labels
- A function parameter's name is also its external label at the call site; prefixing the name with an underscore removes that label, and a default value makes the argument omittable.
- inout parameters
- An inout parameter lets a function modify the caller's variable in place; the call site must pass a mutable variable prefixed with an ampersand, not a literal or constant.
- Escaping closures
- Closures are non-escaping by default, meaning they cannot outlive the call. Marking a parameter @escaping allows the closure to be stored or invoked later, as completion handlers are.
- Closure capture lists
- A capture list written before a closure's parameters, such as [weak self], defines how the closure holds captured references and is the standard remedy for retain cycles.
- Memberwise initializer
- A structure without a custom initializer receives a synthesized memberwise initializer that takes every stored property in declaration order; classes receive no such initializer.
- Struct versus class
- Structures are value types with memberwise initializers and no inheritance; classes are reference types that support inheritance, deinitializers, and identity comparison with the triple-equals operator.
- mutating methods
- Methods on a structure or enumeration that assign to stored properties must be marked mutating, because instances are value types and self is treated as a constant inside methods.
- Class initializer phases
- A designated initializer must set every stored property before using self or calling a method; convenience initializers delegate with self.init, and deinit runs when the instance is deallocated.
- Enum associated values
- An enumeration case may store associated values of any type in parentheses after its name; a switch with case let .name(value) extracts them for use in the case body.
- Raw value enumerations
- Giving an enumeration a raw type such as String or Int assigns each case a rawValue, implicit or explicit, and adds a failable init?(rawValue:) for converting back from the raw value.
- Protocol extension defaults
- A protocol extension can provide a default implementation for a requirement, inherited by conforming types that do not implement their own version; members declared only in extensions dispatch statically.
- Synthesized Codable
- A type conforms to Codable automatically when all of its stored properties are Codable; the compiler generates encoding and decoding keyed by property names unless CodingKeys are defined.
- compactMap versus map
- compactMap applies a transform that may return nil and discards those results, producing a non-optional array; map keeps every result, so an optional-returning transform yields an array of optionals.
- Optional chaining
- Placing a question mark after an optional value, as in person?.address?.city, short-circuits to nil when any link is nil and otherwise wraps the final result in an optional.
- Nil-coalescing operator
- The double-question-mark operator evaluates to the wrapped value of the optional on its left when that value is not nil, and to the default value on its right otherwise.
- try? versus try!
- try? turns a thrown error into a nil optional result; try! traps at runtime if an error is thrown, so it is reserved for failures that cannot possibly occur.
- Dictionary subscript behavior
- Reading a dictionary through a key subscript returns an optional that is nil when the key is missing; assigning nil to that subscript removes the existing key-value pair.
- Custom Error conformance
- Any type conforming to the Error protocol can be thrown from a throws function; enumerations are the usual choice, with one case per failure and do-catch matching cases by pattern.
- SwiftUI View body
- In SwiftUI a view is a value type conforming to View that returns its content from the computed body property; changing observed state re-evaluates body and updates the rendered hierarchy.
- @State versus @Binding
- @State declares storage owned by the view that survives body re-evaluation; @Binding references state owned by an ancestor, letting a child read and write it while both stay in sync.
- @StateObject versus @ObservedObject
- @StateObject creates and retains an ObservableObject for the lifetime of its view; @ObservedObject merely observes an instance that is created and owned somewhere else.
- UIViewController lifecycle order
- viewDidLoad runs once when the view loads; then viewWillAppear and viewDidAppear precede and follow each on-screen appearance, mirrored by viewWillDisappear and viewDidDisappear when leaving.
- Main-thread UI updates
- UIKit and SwiftUI require interface updates on the main thread, so results computed in the background must be handed back with MainActor.run or DispatchQueue.main.async.
- NavigationStack in SwiftUI
- NavigationStack manages a stack of pushed screens and works with NavigationLink or navigationDestination to present detail views, replacing the deprecated NavigationView container.