Skip to content

Instantly share code, notes, and snippets.

@cmcgheit
Last active August 11, 2023 14:13
Show Gist options
  • Save cmcgheit/914611995351b94228d15d91174a50c2 to your computer and use it in GitHub Desktop.
Save cmcgheit/914611995351b94228d15d91174a50c2 to your computer and use it in GitHub Desktop.
Self Taught iOS Beginner Developer Tips

Personal List of Tips for Self-Taught iOS/Swift Developers

**About 60% of these links are of Medium.com content, I highly recommend a Medium subscription, it is $5 a month and Medium has some of the best developer articles!

**Please comment any broken links/issues/suggestions, Happy Coding!

**May 2023: I moved this list to Medium

Basics

Swift - Swift development started in 2010 by Chris Lattner. Together with Bertrand Serlet, the head of the Apple's software team, they came to a new, better alternative to Objective-C through numerous whiteboard sessions. Swift was finally announced at Apple WWDC 2014. Swift was open sourced on December 3, 2015 with Swift version 2.2.

Variables - (temporary) containers that store information

Variables in swift must always have a value

  • Local variables: whose existence is limited to the method they are declared in
  • Instance variables (also known as “ivars” or properties) : that belong to the whole object and therefore can be used from within any method. Used when you need to keep that reference beyond the scope of its method.

Scope - lifetime of a variable

The scope of a local variable is smaller than that of an instance variable. Once the method ends, any local variables are destroyed.

Character - Holds just a single character.

Strings - collection/sequence of characters

Ints - Numbers

  • UInt - A variation on Int that you may encounter occasionally. The U stands for “unsigned”, meaning the type can hold positive values only. It’s called unsigned because it cannot have a negative sign (-) in front of the number. UInt can store numbers between 0 and 18 quintillion, but no negative numbers.

Doubles (Floats) - Numbers with decimal places

  • CGFloat - This isn’t really a Swift type but a type defined by the iOS SDK. It’s a decimal point number like Float and Double.

Collection Types:

Arrays - collection that stores a list objects/variables.

  • The objects it contains are ordered sequentially and you retrieve them by index. You can write an array as Array or [Type].

  • Use arrays when you want an ordered list of variables

Dictionary - collection that stores key-value pairs.

  • For indexing an array you always use a positive integer but for a dictionary you typically use a string.

  • Data type, or just type, of a variable determines what kind of values it can contain

  • Some variables hold simple values such as Int and Bool, others hold more complex objects such as String and Array

** You always need to convert the values explicitly in Swift **

  • Use dictionaries when there isn’t a particular order to what you need to store, but the data has meaningful association.

Set - collection of data where order does not matter. Sets are especially useful when you need to ensure that an item only appears once in the set

  • use sets when the unique values of the data matters, but order of the data does not.

Tuples - group of multiple values expressed separated by commas

  • no restrictions on number of values or type)

Understand the Proc and Cons of Tuples

Back to Top

Type inference/Type Annotation:

Swift uses type inference to determine the type

Ex. var i = 10, type inference determines this is an Int

Type annotation - You use it to override the guess made by Swift’s type inference mechanism

Ex. var f: Float = 3.14

OR

Ex. var i = 10.0 (just add decimal)

To use more complex types, you’ll need to instantiate an object first

var item: ChecklistItem - store checklistitem in object into item variable

item = ChecklistItem() - creates checklistitem object

Both are the process of instantiating, by making an instance.

combine both into: var item = ChecklistItem()

() parentheses – this is how Swift knows that you want to make a new instance

  • You can always guarantee that data will be available in viewDidLoad, if you initialized it

Literal (constants) - A literal is a representation of a value

Computed Properties - methods with no parameters that computes its properties on request

    var name: String
    let fileExtension: String
    
    // A computed property to generate a filename.
    var filename: String {
        return name + "." + fileExtension
    }
}

Stored Properties - storing a value for later use

Classes - reference types stored (passes as reference not copy) Classes can only inherit from a single super class, thus can become bloated. One of the four swift types (Classes, Enums, Structs, Protocols)

Objects - An object is something you get when you instantiate a class. An object is the same as an instance. Object’s instance variables and constants. We often refer to these as the object’s properties. Objects are what it’s all about. They combine data with functionality into coherent, reusable units

  • self keyword refers to object (used in closures)

Objects are a reference type because they are made from classes.

Back to Top

Value Types/Reference Types:

Value Types: Basic types such as Int, Bool, Float and Double, String, Array and Dictionary, as well as enums – are all value types.

When you put values into UILabels, etc. there is a number that is not the actual UILabel object but the memory address of where that UILabel object lives, this is the reference to the UILabel object. When the UILabel object is allocated, the computer puts it somewhere else in memory and returns the address of that memory location.

RULES:

  1. When you make a constant with let, you cannot change a value type once you have given it a value, but object from a reference type can always be changed, even if you used let. The reference itself is constant and you cannot put a new object into it.

  2. When you put an object with a value type into a new variable or constant, it is copied. Arrays are value types in Swift. That means when you put an array into a new variable it will actually make a copy.

** Objects defined with class are reference types, while objects defined with struct or enum are value types **

Strong/Weak references:

Most of the time when you declare a variable that holds a reference object, you are creating a strong relationship. This variable assumes ownership of the object, a responsibility that it shares with any other variables referencing the same object.

A variable with a weak relationship to an object is not helping to keep the object alive. You need to explicitly declare this with the weak keyword (and make it an optional)

The lifetime of an object is determined by how many owners it has at any given point. As soon as there are no more strong references to an object, no matter how many weak references there still are, the object is ruthlessly disposed of. That’s also when the object’s deinit method is called, giving the object one last chance to get its affairs in order before it meets its maker.

Ownership cycles and the weak reference: when objects keep each other alive, the app will never reclaim their memory after they’ve served their purpose. This slowly eats up the available memory for the app and can cause a memory leak. This is one of the main reasons to use the weak reference. This is also why weak variables must always be optionals (either ? or !) because they may become nil at some point.

Swift has a third type of relationship: unowned. Like weak this is used to break cycles. The difference is that unowned variables shouldn’t be nil and therefore don’t have to be optionals.

The concept of shared ownership and object relationships only applies to reference types. Value types are always copied from one place to the other, so they never have more than one owner.

** If you want to keep an object around for a while, you should store it with a strong relationship.

** If you don’t need to own the object and you don’t mind it going away at some point, use a weak or unowned reference.

NSObjects - fundamental base class for almost all the iOS frameworks

Inheritance - main principles of object-oriented programming (OOP) Allows for classes to be built on top of another. The new class takes over objects and methods of the upper or above class and adds it own specializations to it.

  • Class inheritance let's you re-use existing code with minimal effort.

  • Inheritance can also mean, you can extend from classes, derive from classes, base on or subclass from classes.

Polymorphism - is the ability of a class instance to be substituted by a class instance of one of its subclasses. With polymorphism, you define different behaviors for different objects while you are still using a shared interface.

Encapsulation - is a concept by which we hide data and methods from outside intervention and usage.

Back to Top

SuperClasses/Subclasses:

Superclasses - Most classes in Swift have one superclass. A superclass can have a single superclass of its own

Code example: class MyViewController: UIViewController, UITableViewController { }

MyViewController (Superclass) -> UIViewController (subclass) -> UITableViewController (subclass)

  • super keyword in methods refers to object's superclass

The required keyword is used to enforce that every subclass always implements the particular init method

Code example:

  override init(frame: CGRect) {
    super.init(frame: frame)
    backgroundColor = UIColor.black
  }

  required.init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
  }
 }  
}

Subclasses - Classes in Swift can have many Subclasses

Back to Top

Structs/Singletons:

Structs - holds multiple values of data (objects) to be reused (cannot be copied, but made with a new reference type) value types stored (new copies) Value type is recommended where possible, structs are preferable if smaller, copying is safer if you have less references to same instance. With structs you don't have to worry about memory leaks, multiple thread instances, etc. Structs also have built in initializers (init() methods, can have parameters). Structs cannot inherit from one another like classes can, but if you just need to pass around a set of data, it's easier to bundle them into structs. One of the four swift types (Classes, Enums, Structs, Protocols)

Mutating: When a method changes the value of a struct, it must be marked as mutating. The mutating keyword tells Swift that the method can only be used on strings that are made with var, but not on strings made with let

Singleton - holds one data service to be reused (through lifecycle of app)

Methods - used for communicating between class and subclass. Helps subclass perform specific behavior in certain circumstances. When a method ends all local variables are destroyed. While the instance variables and constants provide the data, methods provide the functionality.

Inside a method you can do the following things:

• Create local variables and constants. • Put new values into variables (both local and instance variables). • Call other methods. • Make decisions with the if or switch statements • Perform repetitions with the for or while statements • Return a value to the caller.

There are three kind of methods:

  1. Instance methods: typical method, to call such a method you first need to have an instance of the object.

  2. Class methods: method that works on the class as a whole and not on any particular instance. Also known as a convenience constructor. It is called a convenience constructor because it conveniently puts all the methods of the class into the function.

Example: class func { }

  1. Init methods: also known as initializers, are used during the creation of new object instances. The main purpose of an init method is to fill in the object’s instance variables. Objects can have more than one init method.

(initialization = the act of preparing an object or value for use )

Functions - creating something that is reusable to perform operations over and over again. Functions bundle functionality into small re-usable units – but live outside of any objects.

Parameters - work on data that comes from different sources

Passing a parameter:

Ex. var item = ChecklistItem(text: "Charge my iPhone", checked: false)

This calls the corresponding init(text, checked) method to prepare the newly allocated ChecklistItem object for usage.

Protocols - blueprint/requirements of methods, functions, properties, instructions to set something up, help with the bloating of super classes. One of the four swift types (Classes, Enums, Structs, Protocols) Protocols let objects wear different hats. A protocol is simply a list of method names. Protocols are often used to define delegates. Like classes, protocols can inherit from other protocols.

Example:

  func someMethod(value: Int)
  func anotherMethod() -> String
}

Static functions - functions that cannot be overridden, type methods that are called using dot syntax.

If/Else/Else If Statements:

If a condition is true then the statements in the following { } block are executed.

Ex.

  // statements
} else if condition == value2 {
  // statements
} else if condition == value3 {
  // statements
} else {
  // statements
}

** Whenever you need to unwrap an optional and also check the value of that optional, using if let is the best way to do that. **

Swift Statements: construct in the swift for making decisions. More convenient than if statements, easier to read

Ex.

  case value1:
    // statements
  case value2:
    // statements
  case value3:
    // statements
  default:
    // statements
}

Loops - This performs the statements inside the for in block once for each object from the items array. Loops can often be replaced by functional programming constructs such as map, filter, or reduce.

Example: for i in 0...2 { // do something }

** loop that repeats three times because the closed range 0...2 contains the numbers 0, 1, and 2

Optionals(?/!) - wrapper or box that may/may not have something inside. You may something optional (string, etc.) when you are not sure what the data will be right away (or if the data will be processed) != <- forced unwrapping of optional

It’s best to avoid optionals if you can. They make the logic more complex, they can cause the app to crash if you don’t unwrap them properly, and they require if let statements everywhere.

If you cannot set a property when it was created, then you must set that property to an optional using a question mark(?) This protects against your code trying to access the name if you never set it.

The difference between ? and ! is that the former requires you to manually unwrap the value with if let every time you want to use it.

If you are not 100% sure about the data/object processing, don't force unwrap!

Ranges

Ranges in Swift allow us to select parts of Strings, collections, and other types

Types of Ranges:

  • A closed range operator going from a...b defines a range that includes both a and b in which a must not be greater than b
print(range.first!) // 0
print(range.last!) // 10
  • A half-open range defines a range going from a to b but does not include b
print(names[0..<names.count]) // ["Antoine", "Maaike", "Jaap"]
  • A one-sided range operator only defines one side of the bounds, for example, a... or ...b
print(names[...2]) // ["Antoine", "Maaike", "Jaap"]

Implicitly Unwrapped Optionals/Optionals

  • var myData: String! //Implicitly unwrapped optional used when guarantee variable will have data
  • var myData: String? // Optional used when there may or may not be data in the variable at runtime

Back to Top

Casts:

When you are referring to an instance not by its own class, but by its superclass. examples: as? - casts that are allowed to fail, happens when object is nil or doesn't have a type that is compatible with the type you are trying to cast it to

as! - most common, casts between class and subclass, deals with UIKit cases often.

as - casts that can possibly never fail

Any! - meaning that you don’t really care what sort of object this is.

Extensions - extend/add more functionality to a class/subclass

Lazy var:

lazy initialization is when you, can be used with a closure. You don’t allocate them until you first use them. This makes your apps quicker to start and it saves memory

Property observers:

Property observers observe and respond to changes in a property’s value. Property observers are called every time a property’s value is set, even if the new value is the same as the property’s current value.

Enums - an enumeration is a data type consisting of a set of named values, called members. Enums are preferred by Apple. One of the four swift types (Classes, Enums, Structs, Protocols) An enum, or enumeration, is simply a list of possible values.

Each enum has a numeric value associated with it, called the raw value. Swift enums can have their own methods and properties, so let’s take advantage of that and improve the code even more. Swift enums cannot have instance variables, only computed properties.

Back to Top

Generics - returning multiple values within one function (Ints, Doubles, etc.)

Tuples - A tuple is nothing more than a list of values inside ( ) parentheses. Tuples have various uses, such as allowing a method to return more than one value (simply put the different values into a tuple and return that). They are also very convenient in switch statements.

Guard statement - used to exit a method or function early if a given statement returns false. The guard statement lets you try something. If the result is nil or false, the code from the else block is performed. If everything works like it’s supposed to, the code simply skips the else block and continues.

Example code: guard let x else { return }

Operators - similar to functions

Urinary operators - operator that works on one target

Binary operators - operator that works on two targets

Ternary operators - operator that works on three targets. The ? : construct is the ternary conditional operator. It works like an if – else statement compressed into a single line. Using ? : is often simpler than writing it out as if – else.

Property wrappers - a type that wraps a given value in order to attach additional logic to it

Object oriented programming:

  • create a blueprint of something (with objects) then create multiple copies of that

Back to Top

Model/View/Controller: MVC Design Pattern

  • Model Group: keeping data models, formatting data

  • View Group: keeping views for view controllers, anything that customizes view

  • Controller Group: keeping controllers for views, IB outlets/actions to pass data

  • Swift Architecture Gist

Threading/DispatchQueue:

When downloading images from internet, always put on asynchronous thread

  • main: main thread
  • async : background thread
  • queues: a list of closures to perform on a background thread

Grand Central Dispatch (GCD) - background thread process. GCD has a number of queues with different priorities. GCD greatly simplifies tasks that require parallel programming. GCD will pull the closures – or “blocks” as it calls them – from the queues one-by- one and perform their code in the background.

  • global queue: which is a queue provided by the system

  • main queue: associated with the main thread. If you need to do anything on the main thread from a background queue, you can simply create a new closure and schedule that on the main queue.

  • DispatchQueue.main.async: how to schedule a new closure on the main queue.

Ex.

let queue = DispatchQueue.global() <--- global queue
queue.async {
  // code that needs to run in the background
  DispatchQueue.main.async { <--- main queue closure
    // update the user interface
} }

Back to Top

Background Quality of Service/Threadding (QoS)

UserInteractive: For work that must be processed instantly. UserInitiated: For work that is nearly instantaneous, such as a few seconds or less. Utility: For work that can take some time, such as an API call. Background: For work that takes a very long time.

Frame/Bounds

Frame - describes the outside position and size of view in its parent view. To move a view from one position to another you change its frame property. The frame is actually derived from a combination of properties: the center position of the view, the bounds, and any transform that is set on the view. When you set Auto Layout constraints on a view, those constraints are used to calculate the view’s frame.

Bounds - describes the inside position and size of the view in its parent view. The X and Y coordinates of the bounds are (0, 0) and the width and height will be the same as the frame.

If you want to put a 150×50 label at position X: 100, Y: 30, then its frame is (100, 30, 150, 50). The bounds would be (0, 0, 150, 50)

Back to Top

Completion Handlers:

  • checking if requests/function have been completed
  • Can be @escaping or not to get the values out
  • tell method that functions have been completed

handler: @escaping () -> () EMPTY handler: @escaping (_handlerArray: [String]) -> ()) Passing handlerArray

Extension of a function, used to return values, have access and can be called anywhere annotation @escaping is necessary for closures that are not performed immediately

Closures:

  • variable, argument, data that is passed around used in code
  • to help start/continue other next tasks/other tasks
  • a piece of inline code that is not executed right away.
  • when a local variable is captured by a closure, it stays alive until the closure is done with it.
  • it stores a strong reference to objects
  • useful for other things, such as initializing objects and lazy loading
  • keeps all code in the same place

The -> symbol means that the type represents a closure

() -> () Swift notation for a parameter that takes a closure with no arguments and no return value

The type for a closure generally looks like this:

(parameter list) -> return type

both the parameter list and the return value are empty parameters in closures are separated by the “in” keyword can also be written as Void -> Void

Parentheses at the end of the closure invoke it immediately.

Example: var four: Int = { return 2 + 2 }()

Closure/Self - you use self inside of closures because closures capture any variables that are used inside the closure. When it captures a variable, the closure simply stores a reference to that variable. Self is one of the variables that gets captured by the closure.

Closures is that they capture any variables used inside the closure, including self. This can create ownership cycles, often leading to memory leaks. To avoid this, you can supply a capture list.

Example: let dataTask = session.dataTask(with: url) { [weak self] data, response, error in ... }

The @escaping annotation is necessary for closures that are not used immediately.

** no-escape closures don’t capture self, so you don’t have to write “self. **

Example of closures:let dataTask = session.dataTask(with: url, completionHandler: { data, response, error in . . . source code . . . })

Closures, functions, and methods are all blocks of source code that possibly take parameters and return a value. The difference is that a function is really just a closure with a name, and a method is a function that lives inside an object.

() -> () is a closure that takes no parameters and returns no value.

Void -> Void is the same as the previous example. Void and () mean the same thing.

(Int) -> Bool is a closure that takes one parameter, an Int, and returns a Bool. Int -> Bool is this is the same as above. If there is only one parameter, you can leave out the parentheses.

(Int, String) -> Bool is a closure taking two parameters, an Int and a String, and returning a Bool.

(Int, String) -> Bool? as above but now returns an optional Bool value.

(Int) -> (Int) -> Int is a closure that returns another closure that returns an Int. Freaky! Swift treats closures like any other type of object, so you can also pass them as parameters and return them from functions.

-Passing Data in iOS: Delegates, Notificatons and Closures

Back to Top

Typealias:

The typealias statement allows you to create a more convenient name for a data type, in order to save some keystrokes and to make the code more readable.

Dependency Injection

Dependency injection (DI) is the practice of providing an object with the other objects it depends on rather than creating them internally.

class Foo {
    let bar: Bar = Bar()
}

// With dependecy injection
class Foo {
    let bar: Bar

    init(bar: Bar) {
        self.bar = bar
    }
}

Do/Try Catch for Errors:

Any method that can potentially fail must have the try keyword in front of it. And that method call with the try keyword must be inside a do-catch block. Any method call that may potentially throw an error must be written as try methodName().

CRUD/Making Web Requests:

Client (browser, phone, etc.) makes the request, Server sends information back

CRUD - Create, Read, Update Delete Create - like posting a new request in web requests Read - like retrieving in web requests Put - like updating in web requests Delete - like deleting in web requests

Understanding Git:

git - a version control system for tracking changes in computer files and coordinating work on those files among multiple people.

Most common git commands:

git status - check status of changes/modifications in projects/files git add - add commits (changes/modifications) to history git commit - commit a change/modifications git pull - fetching and merging commits/changes/modifications git push - pushes commits/changes/modifications

Other git commands to know:

git checkout - checkout branches git branch - shows all branches for git file git log - shows log of all commits

  • Good video resource for the git basics : Link

  • Good video resource for local and remote repositories : Link

HTTP Requests/Web & APIs

JSON - format to encapsulate data, information transferred from API (data)

JavaScript Object Notation - similar to javascript, includes key and value objects

Web Sockets - free flow of information from client to server (preferably for Chat functions)

Sockets - send/receive information via emits

Core Data - framework to be used when you want to store complex data for offline use (data that is stored after close app)

**Basically you are setting up your own data attached to the app for offline use (storage)

BENEFITS OF CORE DATA:

  • No network API/calls
  • Save/Undo Functionality
  • Sorting/Filtering
  • Reduce amount of necessary code
  • Tracks changes, so better memory management
  • easier to display data
  • Data GUI, manage entities, attributes

entities - objects of data attributes - properties (like in typical OOP) of entities

Back to Top

ViewDidLoad, ViewDidAppear, AwakeFromNib (View Controller Lifecycle):

ViewDidLoad - method only called once, loads only once initially

ViewDidAppear - method called every time the view is shown, loads every time the view controller gets called

AwakeFromNib - method called after this cell object has been loaded from the nib but before the cell is added to the table view.

ViewWillLayoutSubviews() - Performs any calculations that use the view’s frame or bounds, may be invoked more than once

Auto Layout

A Constraint-based layout system that allows developers to create an adaptive interface, that responds appropriately to changes in screen size and device orientation

Back to Top

Common Interview Questions

Questions I've personally been asked during interviews, taken from:

  1. What is the difference strong, weaks, read only and copy?

strong, weak, assign property attributes define how memory for that property will be managed.

Strong means that the reference count will be increased and the reference to it will be maintained through the life of the object

Weak ( non-strong reference ), means that we are pointing to an object but not increasing its reference count. It’s often used when creating a parent child relationship. The parent has a strong reference to the child but the child only has a weak reference to the parent.

  1. What is the difference between Synchronous & Asynchronous task?
  • Synchronous: waits until the task has completed
  • Asynchronous: completes a task in background and can notify you when complete
  1. What is a Completion Handler?

Completion handlers are super convenient blocks of code that we can use when our app is making an API call, and we need to do something when that task is done, like updating the UI to show the data from the API call.

  1. What is the Observer Pattern?

In the Observer pattern, one object notifies other objects of any state changes.

Cocoa implements the observer pattern in two ways: Notifications and Key-Value Observing (KVO).

  1. Explain the MVC Pattern?

Models — responsible for the domain data or a data access layer which manipulates the data, think of ‘Person’ or ‘PersonDataProvider’ classes. Views — responsible for the presentation layer (GUI), for iOS environment think of everything starting with ‘UI’ prefix. Controller/Presenter/ViewModel — the glue or the mediator between the Model and the View, in general responsible for altering the Model by reacting to the user’s actions performed on the View and updating the View with changes from the Model.

Back to Top

  1. Advantages of using Swift?
  • Optional Types, which make applications crash-resistant
  • Built-in error handling
  • Closures
  • Much faster compared to other languages
  • Type-safe language
  • Supports pattern matching
  1. What is Concurrency?

Concurrency is dividing up the execution paths of your program so that they are possibly running at the same time. The common terminology: process, thread, multithreading, and others. Terminology;

  • Process, An instance of an executing app
  • Thread, Path of execution for code
  • Multithreading, Multiple threads or multiple paths of execution running at the same time.
  • Concurrency, Execute multiple tasks at the same time in a scalable manner.
  • Queues, Queues are lightweight data structures that manage objects in the order of First-in, First-out (FIFO).
  • Synchronous vs Asynchronous tasks
  1. What is Grand Central Dispatch (GCD)?

GCD is a library that provides a low-level and object-based API to run tasks concurrently while managing threads behind the scenes. Terminology;

Dispatch Queues, A dispatch queue is responsible for executing a task in the first-in, first-out order. Serial Dispatch Queue A serial dispatch queue runs tasks one at a time. Concurrent Dispatch Queue A concurrent dispatch queue runs as many tasks as it can without waiting for the started tasks to finish. Main Dispatch Queue A globally available serial queue that executes tasks on the application’s main thread.

  1. Explain Readers-Writers in Swift?

Multiple threads reading at the same time while there should be only one thread writing. The solution to the problem is a readers-writers lock which allows concurrent read-only access and an exclusive write access. Terminology;

  • Race Condition A race condition occurs when two or more threads can access shared data and they try to change it at the same time.
  • Deadlock A deadlock occurs when two or sometimes more tasks wait for the other to finish, and neither ever does.
  • Readers-Writers problem Multiple threads reading at the same time while there should be only one thread writing.
  • Readers-writer lock Such a lock allows concurrent read-only access to the shared resource while write operations require exclusive access.
  • Dispatch Barrier Block Dispatch barrier blocks create a serial-style bottleneck when working with concurrent queues.
  1. Explain [weak self] and [unowned self]?
  • unowned ( non-strong reference ) does the same as weak with one exception: The variable will not become nil and must not be an optional.

When you try to access the variable after its instance has been deallocated. That means, you should only use unowned when you are sure, that this variable will never be accessed after the corresponding instance has been deallocated.

However, if you don’t want the variable to be weak AND you are sure that it can’t be accessed after the corresponding instance has been deallocated, you can use unowned.

Every time used with non-optional types Every time used with let By declaring it [weak self] you get to handle the case that it might be nil inside the closure at some point and therefore the variable must be an optional. A case for using [weak self] in an asynchronous network request, is in a view controller where that request is used to populate the view.

Back to Top

Resources

App Tutorials

*Recommended Apps to build that teach the fundamentals of iOS programming

Back to Top

Interviews

Back to Top

Books

Back to Top

Swift

Back to Top

Resources - Examples/Tutorials/Courses

Back to Top

Algorithms

Back to Top

General

Back to Top

Accessibility

Back To Top

Debugging

Back to Top

Testing

Back to Top

Twitter

Back to Top

Github

Back to Top

Other

Back to Top

Gists

Back to Top

@usamaeltmsah
Copy link

All the links transit to an ad site, and from ad to ad

@cmcgheit
Copy link
Author

cmcgheit commented Jul 1, 2022

All the links transit to an ad site, and from ad to ad

all the links use a link shortener, I'm sure there are ads, but you should be able to get past the ads

@usamaeltmsah
Copy link

Actually, it's a tedious series of ads

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment