SlideShare a Scribd company logo
Swift Memory Management
By: Marcus Smith
Software Engineer
stable|kernel

marcus.smith@stablekernel.com
@stablekernel
Why should you care?
@stablekernel
Who am I?
• Marcus Smith
• iOS Developer at stable|kernel
• Struggled learning memory management
• Previously worked for BMW and Frozen Fire Studios
• Have a game in the app store
stable|kernel is an Atlanta-based mobile development company 

to craft smartly-designed mobile applications that connect brands 

directly with their users. 



Our team of engineers and designers takes clients from 

strategy through design, development and deployment, 

ensuring timely delivery of the highest quality applications.
Memory Management
@stablekernel
• Value & Reference Types
• Reference Counting & ARC
• Avoiding memory issues
Value & Reference Types
@stablekernel
• Value types contain data
• Reference types contain the location in memory where data is
Value Types
@stablekernel
• Structs, Enums and Tuples
• Copied on assignment or when passing to a function
struct Point {
var x, y: Int
}
let aPoint = Point(x: 0, y: 0)
var anotherPoint = aPoint
anotherPoint.x = 5
print(aPoint.x) // prints 0
Reference Types
@stablekernel
• Classes and Closures
• Creates another reference when assigned to a variable or passed to a function
• Implicit sharing
@stablekernel
class Person {
var name: String
var age: Int
init(name: String, age: Int) {…}
}
let bob = Person(name: “Bob”, age: 30)
let myNeighbor = bob
myNeighbor.age = 50
print(bob.age) // prints 50
func increaseAge(person: Person) {
person.age += 1
}
increaseAge(person: bob)
print(myNeighbor.age) // prints 51
Reference Types
@stablekernel
• More power, more responsibility
• Can have multiple owners
• Inheritance
• Require some memory management on the part of the programmer
• blog.stablekernel.com
Reference Counting
@stablekernel
• Type of garbage collection
• Objects keep a count of references
• When an object’s reference count gets down to 0, it is destroyed and its
memory is freed
• Used to be done manually with alloc, retain, copy, release
@stablekernel
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/MemoryMgmt.html
Automatic Reference Counting (ARC)
@stablekernel
• Compiler makes retain and release calls
• Has a problem with circular references creating retain cycles (memory leaks)
@stablekernel
class Person {
var name: String
var age: Int
init(name: String, age: Int) {…}
var apartment: Apartment?
}
class Apartment {
let unit: String
init(unit: String) {…}
var tenant: Person?
}
class SomeViewController: UIViewController {
var person: Person!
override func viewDidLoad() {
super.viewDidLoad()
person = Person(name: “Bob”, age: 30)
let unit4A = Apartment(unit: “4A”)
person.apartment = unit4A
unit4A.tenant = person
}
}
@stablekernel
UINavigationController SomeViewController
Person
Apartment
Push
1
1
1
2
0
Pop
ARC - Strong and Weak References
@stablekernel
• ARC deals with circular references by having strong and weak references
• Strong references increase an object’s reference count
• Weak references do not increase an object’s reference count
• In Swift, references are strong by default
class Apartment {
let unit: String
init(unit: String) {…}
var tenant: Person?
}
ARC - Strong and Weak References
@stablekernel
• ARC deals with circular references by having strong and weak references
• Strong references increase an object’s reference count
• Weak references do not increase an object’s reference count
• In Swift, references are strong by default
class Apartment {
let unit: String
init(unit: String) {…}
weak var tenant: Person?
}
@stablekernel
UINavigationController SomeViewController
Person
Apartment
Push
1
1
1
0
Pop
0
0
ARC - Weak References
@stablekernel
• Weak references help prevent retain cycles
• Can go nil at any time, which was problematic in Objective-C
• In Swift, weak references must be optional vars
weak var tenant: Person
weak let tenant: Person? ‘weak’ must be a mutable variable, because it may change at runtime
‘weak’ variable should have optional type ‘Person?’
ARC - Unowned References
@stablekernel
• Like weak references, but non-optional
• Should only be used if you can guarantee the object won’t become nil
• Objective-C name “Unsafe Unretained”
• In Objective-C dangling pointers could cause crashes or data corruption
“Swift guarantees your app will crash if you try to access an unowned reference
after the instance it references is deallocated. You will never encounter
unexpected behavior in this situation. Your app will always crash reliably, although
you should, of course, prevent it from doing so.”
unowned let tenant: Person
Avoiding Retain Cycles
@stablekernel
• Delegates
• Parent - Child relationships
• IBOutlets
• CoreData
• Closures
• Lazy properties
Delegates
@stablekernel
• Delegates should be weak
open class UITableView {
weak open var dataSource: UITableViewDataSource?
weak open var delegate: UITableViewDelegate?
...
}
protocol SomeDelegate {}
class SomeObject {
weak var delegate: SomeDelegate?
} ‘weak’ may only be applied to class and class-bound
protocol types, not ‘SomeDelegate’
Delegates
@stablekernel
• Delegates should be weak
open class UITableView {
weak open var dataSource: UITableViewDataSource?
weak open var delegate: UITableViewDelegate?
...
}
protocol SomeDelegate: class {}
class SomeObject {
weak var delegate: SomeDelegate?
} ‘weak’ may only be applied to class and class-bound
protocol types, not ‘SomeDelegate’
Parent - Child Relationships
@stablekernel
• Parents typically should hold a strong reference to their children
• Children should hold a weak reference to their parent
extension UIView {
open var superview: UIView? { get }
open var subviews: [UIView] { get }
...
}
open class UIViewController {
weak open var parent: UIViewController? { get }
open var childViewControllers: [UIViewController] { get }
...
}
IBOutlets
@stablekernel
• Weak by default (except root view)
• Retained by superviews
• Need to be declared as strong if you will be removing and re-adding
• Same is true for NSLayoutConstraint
@stablekernel
class ViewController: UIViewController {
@IBOutlet weak var someView: UIView!
/// A subview of `someView`
@IBOutlet weak var someSubView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
someView.removeFromSuperview()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
someSubView.backgroundColor = .red
}
}
Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
fatal error: unexpectedly found nil while unwrapping an Optional value
@stablekernel
class ViewController: UIViewController {
@IBOutlet var someView: UIView!
/// A subview of `someView`
@IBOutlet weak var someSubView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
someView.removeFromSuperview()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
someSubView.backgroundColor = .red
}
}
Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
fatal error: unexpectedly found nil while unwrapping an Optional value
Core Data
@stablekernel
• CoreData relationships on NSManagedObjects create retain cycles
• To break these retain cycles call refresh on NSManagedObjectContext:
context.refresh(someManagedObject, mergeChanges: false)
Closures
@stablekernel
• Blocks of code that can be passed around
let sayHello: (String) -> Void = { name in print("Hello (name)") }
sayHello("World") // prints "Hello World”
let add: (Int, Int) -> Int = { x, y in return x + y }
let total = add(3, 5) // returns 8
let numbers = [1, 2, 3, 4, 5]
let odds = numbers.filter { number in return number % 2 == 1 }
print(odds) // prints [1, 3, 5]
Closures
@stablekernel
• Reference type
• Have to capture and store references to the variables they need to run
let increaseBobsAgeBy: (Int) -> Void = { (value) in
bob.age += value
}
class Executable {
let bob: Person
init(bob: Person) {…}
func execute(value: Int) { bob.age += value }
}
increaseBobsAgeBy(2)
Closures - Capturing Self
@stablekernel
class SomeClass {
var completion: () -> Void
func doSomething() {…}
func makeNetworkRequest() {…}
func update() {
completion = {
doSomething()
}
makeNetworkRequest()
}
}
Call to method ‘doSomething’ in closure requires explicit ‘self.’ to make capture semantics explicit
Closures - Capturing Self
@stablekernel
class SomeClass {
var completion: () -> Void
func doSomething() {…}
func makeNetworkRequest() {…}
func update() {
completion = {
self.doSomething()
}
makeNetworkRequest()
}
}
Call to method ‘doSomething’ in closure requires explicit ‘self.’ to make capture semantics explicit
• Closures require an explicit self
• Can cause retain cycles if an object owns a closure that captures itself
Closures - Capturing Self
@stablekernel
class SomeClass {
var completion: () -> Void
func doSomething() {…}
func update() {
completion = {
self.doSomething()
}
}
}
class Executable {
let someClass: SomeClass
init(someClass: SomeClass) {…}
func execute() { someClass.doSomething() }
}
Closures - Capturing Self
@stablekernel
class SomeClass {
var completion: () -> Void
func doSomething() {…}
func update() {
completion = { [weak self] in
self.doSomething()
}
}
}
class Executable {
let someClass: SomeClass
init(someClass: SomeClass) {…}
func execute() { someClass.doSomething() }
}
Closures - Capturing Self
@stablekernel
class SomeClass {
var completion: () -> Void
func doSomething() {…}
func update() {
completion = { [weak self] in
self.doSomething()
}
}
}
class Executable {
weak var someClass: SomeClass?
init(someClass: SomeClass) {…}
func execute() { someClass.doSomething() }
}
Closures - Capturing Self
@stablekernel
class SomeClass {
var completion: () -> Void
func doSomething() {…}
func update() {
completion = { [weak self] in
self?.doSomething()
}
}
}
class Executable {
weak var someClass: SomeClass?
init(someClass: SomeClass) {…}
func execute() { someClass?.doSomething() }
}
Closures - Capturing Self
@stablekernel
class SomeClass {
var completion: () -> Void
func doSomethingWithNonOptional(_ someClass: SomeClass) {…}
func update() {
completion = { [weak self] in
}
}
}
Closures - Capturing Self
@stablekernel
class SomeClass {
var completion: () -> Void
func doSomethingWithNonOptional(_ someClass: SomeClass) {…}
func update() {
completion = { [unowned self] in
doSomethingWithNonOptional(self)
}
}
}
Closures - Capturing Self
@stablekernel
class SomeClass {
var completion: () -> Void
func doSomethingWithNonOptional(_ someClass: SomeClass) {…}
func update() {
completion = { [weak self] in
if let strongSelf = self {
doSomethingWithNonOptional(strongSelf)
}
}
}
}
Closures - Capturing Self
@stablekernel
class SomeClass {
var completion: () -> Void
func doSomethingWithNonOptional(_ someClass: SomeClass) {…}
func update() {
completion = { [weak self] in
guard let strongSelf = self else { return }
doSomethingWithNonOptional(strongSelf)
}
}
}
Closures - Capturing Self
@stablekernel
• Self does not always need to be captured weakly
• Depends on what objects may own the closure with self
DispatchQueue.main.async {
self.doSomething() // Not a retain cycle
}
UIView.animate(withDuration: 1) {
self.doSomething() // Not a retain cycle
}
DispatchQueue.main.asyncAfter(deadline: .now() + 30) {
self.doSomething() // Not a retain cycle, but...
}
Lazy Properties
@stablekernel
• Lazy closure properties need to capture self weakly to prevent retain cycles
class Person {
lazy var greeting: () -> String = { [unowned self] in
return “Hi, I’m (self.name)”
}
}
class Person {
lazy var fullName: String = {
return “(self.firstName) (self.lastName)”
}()
}
• Other lazy properties do not
Avoiding Retain Cycles
@stablekernel
• Delegates - delegate should be weak
• Parent - Child relationships - parent property should be weak
• IBOutlets - weak or strong is fine, but strong if removing and re-adding
• CoreData - refresh changes to turn back into faults
• Closures - be careful what you capture and how
• Lazy properties - only need to capture self weakly for closure properties
Questions?
Business Inquiries:
Sarah Woodward
Director of Business Development
sarah.woodward@stablekernel.com
Marcus Smith
Software Engineer
marcus.smith@stablekernel.com
blog.stablekernel.com

More Related Content

PDF
Connect.Tech- Enhancing Your Workflow With Xcode Source Editor Extensions
PDF
Connect.Tech- Level Up Your Game With TravisCI
PDF
Memory Management on iOS
PDF
Distributing information on iOS
PDF
Reactive Programming with JavaScript
ODP
From object oriented to functional domain modeling
PDF
Activator and Reactive at Play NYC meetup
PDF
Practical tips for building apps with kotlin
Connect.Tech- Enhancing Your Workflow With Xcode Source Editor Extensions
Connect.Tech- Level Up Your Game With TravisCI
Memory Management on iOS
Distributing information on iOS
Reactive Programming with JavaScript
From object oriented to functional domain modeling
Activator and Reactive at Play NYC meetup
Practical tips for building apps with kotlin

What's hot (20)

PDF
Workshop 26: React Native - The Native Side
PDF
Save time with kotlin in android development
PDF
Workshop 23: ReactJS, React & Redux testing
PDF
Android Architecture Components with Kotlin
PDF
What To Expect From PHP7
PPTX
Mastering Java Bytecode With ASM - 33rd degree, 2012
PDF
Automatic Reference Counting @ Pragma Night
PDF
Http4s, Doobie and Circe: The Functional Web Stack
PDF
Rails Best Practices
PPT
PDF
Workshop 17: EmberJS parte II
PDF
Boost your angular app with web workers
PDF
Workshop 25: React Native - Components
PDF
How to build to do app using vue composition api and vuex 4 with typescript
KEY
25 Real Life Tips In Ruby on Rails Development
PDF
Workshop 13: AngularJS Parte II
PPTX
Academy PRO: React native - navigation
PDF
Object Oriented Exploitation: New techniques in Windows mitigation bypass
PDF
Web注入+http漏洞等描述
PDF
Workshop 19: ReactJS Introduction
Workshop 26: React Native - The Native Side
Save time with kotlin in android development
Workshop 23: ReactJS, React & Redux testing
Android Architecture Components with Kotlin
What To Expect From PHP7
Mastering Java Bytecode With ASM - 33rd degree, 2012
Automatic Reference Counting @ Pragma Night
Http4s, Doobie and Circe: The Functional Web Stack
Rails Best Practices
Workshop 17: EmberJS parte II
Boost your angular app with web workers
Workshop 25: React Native - Components
How to build to do app using vue composition api and vuex 4 with typescript
25 Real Life Tips In Ruby on Rails Development
Workshop 13: AngularJS Parte II
Academy PRO: React native - navigation
Object Oriented Exploitation: New techniques in Windows mitigation bypass
Web注入+http漏洞等描述
Workshop 19: ReactJS Introduction
Ad

Similar to Connect.Tech- Swift Memory Management (20)

PDF
Automatic reference counting (arc) and memory management in swift
PDF
Automatic reference counting in Swift
PDF
Memory Management In Swift
PPTX
iOS Development using Swift: Enums, ARC, Delegation, Closures, Table View and...
PDF
Swift - One step forward from Obj-C
PPT
Swift Programming - Part 2
PPTX
iOS Beginners Lesson 2
PDF
Migrating Objective-C to Swift
PDF
Swift 성능 이해하기
PDF
Working with Cocoa and Objective-C
PPT
Lecture 3-ARC
PDF
Denis Lebedev, Swift
PDF
Custom view
PPT
Memory management in Objective C
PDF
From android/java to swift (3)
PPTX
iOS Memory Management
PDF
Objective-C Is Not Java
PDF
Advanced debugging
PPTX
Memory Management & Debugging
PPT
Objective C Memory Management
Automatic reference counting (arc) and memory management in swift
Automatic reference counting in Swift
Memory Management In Swift
iOS Development using Swift: Enums, ARC, Delegation, Closures, Table View and...
Swift - One step forward from Obj-C
Swift Programming - Part 2
iOS Beginners Lesson 2
Migrating Objective-C to Swift
Swift 성능 이해하기
Working with Cocoa and Objective-C
Lecture 3-ARC
Denis Lebedev, Swift
Custom view
Memory management in Objective C
From android/java to swift (3)
iOS Memory Management
Objective-C Is Not Java
Advanced debugging
Memory Management & Debugging
Objective C Memory Management
Ad

Recently uploaded (20)

PPTX
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
PDF
System and Network Administration Chapter 2
PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
PPTX
VVF-Customer-Presentation2025-Ver1.9.pptx
PDF
Wondershare Filmora 15 Crack With Activation Key [2025
PDF
System and Network Administraation Chapter 3
PDF
Understanding Forklifts - TECH EHS Solution
PDF
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
PDF
How to Migrate SBCGlobal Email to Yahoo Easily
PDF
AI in Product Development-omnex systems
PPTX
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
PPTX
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
PPTX
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
PDF
top salesforce developer skills in 2025.pdf
PPTX
Operating system designcfffgfgggggggvggggggggg
PPTX
Reimagine Home Health with the Power of Agentic AI​
PDF
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
PDF
Digital Strategies for Manufacturing Companies
PPTX
Transform Your Business with a Software ERP System
PPTX
Introduction to Artificial Intelligence
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
System and Network Administration Chapter 2
Navsoft: AI-Powered Business Solutions & Custom Software Development
VVF-Customer-Presentation2025-Ver1.9.pptx
Wondershare Filmora 15 Crack With Activation Key [2025
System and Network Administraation Chapter 3
Understanding Forklifts - TECH EHS Solution
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
How to Migrate SBCGlobal Email to Yahoo Easily
AI in Product Development-omnex systems
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
top salesforce developer skills in 2025.pdf
Operating system designcfffgfgggggggvggggggggg
Reimagine Home Health with the Power of Agentic AI​
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
Digital Strategies for Manufacturing Companies
Transform Your Business with a Software ERP System
Introduction to Artificial Intelligence

Connect.Tech- Swift Memory Management

  • 1. Swift Memory Management By: Marcus Smith Software Engineer stable|kernel
 marcus.smith@stablekernel.com
  • 3. @stablekernel Who am I? • Marcus Smith • iOS Developer at stable|kernel • Struggled learning memory management • Previously worked for BMW and Frozen Fire Studios • Have a game in the app store
  • 4. stable|kernel is an Atlanta-based mobile development company 
 to craft smartly-designed mobile applications that connect brands 
 directly with their users. 
 
 Our team of engineers and designers takes clients from 
 strategy through design, development and deployment, 
 ensuring timely delivery of the highest quality applications.
  • 5. Memory Management @stablekernel • Value & Reference Types • Reference Counting & ARC • Avoiding memory issues
  • 6. Value & Reference Types @stablekernel • Value types contain data • Reference types contain the location in memory where data is
  • 7. Value Types @stablekernel • Structs, Enums and Tuples • Copied on assignment or when passing to a function struct Point { var x, y: Int } let aPoint = Point(x: 0, y: 0) var anotherPoint = aPoint anotherPoint.x = 5 print(aPoint.x) // prints 0
  • 8. Reference Types @stablekernel • Classes and Closures • Creates another reference when assigned to a variable or passed to a function • Implicit sharing
  • 9. @stablekernel class Person { var name: String var age: Int init(name: String, age: Int) {…} } let bob = Person(name: “Bob”, age: 30) let myNeighbor = bob myNeighbor.age = 50 print(bob.age) // prints 50 func increaseAge(person: Person) { person.age += 1 } increaseAge(person: bob) print(myNeighbor.age) // prints 51
  • 10. Reference Types @stablekernel • More power, more responsibility • Can have multiple owners • Inheritance • Require some memory management on the part of the programmer • blog.stablekernel.com
  • 11. Reference Counting @stablekernel • Type of garbage collection • Objects keep a count of references • When an object’s reference count gets down to 0, it is destroyed and its memory is freed • Used to be done manually with alloc, retain, copy, release
  • 13. Automatic Reference Counting (ARC) @stablekernel • Compiler makes retain and release calls • Has a problem with circular references creating retain cycles (memory leaks)
  • 14. @stablekernel class Person { var name: String var age: Int init(name: String, age: Int) {…} var apartment: Apartment? } class Apartment { let unit: String init(unit: String) {…} var tenant: Person? } class SomeViewController: UIViewController { var person: Person! override func viewDidLoad() { super.viewDidLoad() person = Person(name: “Bob”, age: 30) let unit4A = Apartment(unit: “4A”) person.apartment = unit4A unit4A.tenant = person } }
  • 16. ARC - Strong and Weak References @stablekernel • ARC deals with circular references by having strong and weak references • Strong references increase an object’s reference count • Weak references do not increase an object’s reference count • In Swift, references are strong by default class Apartment { let unit: String init(unit: String) {…} var tenant: Person? }
  • 17. ARC - Strong and Weak References @stablekernel • ARC deals with circular references by having strong and weak references • Strong references increase an object’s reference count • Weak references do not increase an object’s reference count • In Swift, references are strong by default class Apartment { let unit: String init(unit: String) {…} weak var tenant: Person? }
  • 19. ARC - Weak References @stablekernel • Weak references help prevent retain cycles • Can go nil at any time, which was problematic in Objective-C • In Swift, weak references must be optional vars weak var tenant: Person weak let tenant: Person? ‘weak’ must be a mutable variable, because it may change at runtime ‘weak’ variable should have optional type ‘Person?’
  • 20. ARC - Unowned References @stablekernel • Like weak references, but non-optional • Should only be used if you can guarantee the object won’t become nil • Objective-C name “Unsafe Unretained” • In Objective-C dangling pointers could cause crashes or data corruption “Swift guarantees your app will crash if you try to access an unowned reference after the instance it references is deallocated. You will never encounter unexpected behavior in this situation. Your app will always crash reliably, although you should, of course, prevent it from doing so.” unowned let tenant: Person
  • 21. Avoiding Retain Cycles @stablekernel • Delegates • Parent - Child relationships • IBOutlets • CoreData • Closures • Lazy properties
  • 22. Delegates @stablekernel • Delegates should be weak open class UITableView { weak open var dataSource: UITableViewDataSource? weak open var delegate: UITableViewDelegate? ... } protocol SomeDelegate {} class SomeObject { weak var delegate: SomeDelegate? } ‘weak’ may only be applied to class and class-bound protocol types, not ‘SomeDelegate’
  • 23. Delegates @stablekernel • Delegates should be weak open class UITableView { weak open var dataSource: UITableViewDataSource? weak open var delegate: UITableViewDelegate? ... } protocol SomeDelegate: class {} class SomeObject { weak var delegate: SomeDelegate? } ‘weak’ may only be applied to class and class-bound protocol types, not ‘SomeDelegate’
  • 24. Parent - Child Relationships @stablekernel • Parents typically should hold a strong reference to their children • Children should hold a weak reference to their parent extension UIView { open var superview: UIView? { get } open var subviews: [UIView] { get } ... } open class UIViewController { weak open var parent: UIViewController? { get } open var childViewControllers: [UIViewController] { get } ... }
  • 25. IBOutlets @stablekernel • Weak by default (except root view) • Retained by superviews • Need to be declared as strong if you will be removing and re-adding • Same is true for NSLayoutConstraint
  • 26. @stablekernel class ViewController: UIViewController { @IBOutlet weak var someView: UIView! /// A subview of `someView` @IBOutlet weak var someSubView: UIView! override func viewDidLoad() { super.viewDidLoad() someView.removeFromSuperview() } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) someSubView.backgroundColor = .red } } Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0) fatal error: unexpectedly found nil while unwrapping an Optional value
  • 27. @stablekernel class ViewController: UIViewController { @IBOutlet var someView: UIView! /// A subview of `someView` @IBOutlet weak var someSubView: UIView! override func viewDidLoad() { super.viewDidLoad() someView.removeFromSuperview() } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) someSubView.backgroundColor = .red } } Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0) fatal error: unexpectedly found nil while unwrapping an Optional value
  • 28. Core Data @stablekernel • CoreData relationships on NSManagedObjects create retain cycles • To break these retain cycles call refresh on NSManagedObjectContext: context.refresh(someManagedObject, mergeChanges: false)
  • 29. Closures @stablekernel • Blocks of code that can be passed around let sayHello: (String) -> Void = { name in print("Hello (name)") } sayHello("World") // prints "Hello World” let add: (Int, Int) -> Int = { x, y in return x + y } let total = add(3, 5) // returns 8 let numbers = [1, 2, 3, 4, 5] let odds = numbers.filter { number in return number % 2 == 1 } print(odds) // prints [1, 3, 5]
  • 30. Closures @stablekernel • Reference type • Have to capture and store references to the variables they need to run let increaseBobsAgeBy: (Int) -> Void = { (value) in bob.age += value } class Executable { let bob: Person init(bob: Person) {…} func execute(value: Int) { bob.age += value } } increaseBobsAgeBy(2)
  • 31. Closures - Capturing Self @stablekernel class SomeClass { var completion: () -> Void func doSomething() {…} func makeNetworkRequest() {…} func update() { completion = { doSomething() } makeNetworkRequest() } } Call to method ‘doSomething’ in closure requires explicit ‘self.’ to make capture semantics explicit
  • 32. Closures - Capturing Self @stablekernel class SomeClass { var completion: () -> Void func doSomething() {…} func makeNetworkRequest() {…} func update() { completion = { self.doSomething() } makeNetworkRequest() } } Call to method ‘doSomething’ in closure requires explicit ‘self.’ to make capture semantics explicit • Closures require an explicit self • Can cause retain cycles if an object owns a closure that captures itself
  • 33. Closures - Capturing Self @stablekernel class SomeClass { var completion: () -> Void func doSomething() {…} func update() { completion = { self.doSomething() } } } class Executable { let someClass: SomeClass init(someClass: SomeClass) {…} func execute() { someClass.doSomething() } }
  • 34. Closures - Capturing Self @stablekernel class SomeClass { var completion: () -> Void func doSomething() {…} func update() { completion = { [weak self] in self.doSomething() } } } class Executable { let someClass: SomeClass init(someClass: SomeClass) {…} func execute() { someClass.doSomething() } }
  • 35. Closures - Capturing Self @stablekernel class SomeClass { var completion: () -> Void func doSomething() {…} func update() { completion = { [weak self] in self.doSomething() } } } class Executable { weak var someClass: SomeClass? init(someClass: SomeClass) {…} func execute() { someClass.doSomething() } }
  • 36. Closures - Capturing Self @stablekernel class SomeClass { var completion: () -> Void func doSomething() {…} func update() { completion = { [weak self] in self?.doSomething() } } } class Executable { weak var someClass: SomeClass? init(someClass: SomeClass) {…} func execute() { someClass?.doSomething() } }
  • 37. Closures - Capturing Self @stablekernel class SomeClass { var completion: () -> Void func doSomethingWithNonOptional(_ someClass: SomeClass) {…} func update() { completion = { [weak self] in } } }
  • 38. Closures - Capturing Self @stablekernel class SomeClass { var completion: () -> Void func doSomethingWithNonOptional(_ someClass: SomeClass) {…} func update() { completion = { [unowned self] in doSomethingWithNonOptional(self) } } }
  • 39. Closures - Capturing Self @stablekernel class SomeClass { var completion: () -> Void func doSomethingWithNonOptional(_ someClass: SomeClass) {…} func update() { completion = { [weak self] in if let strongSelf = self { doSomethingWithNonOptional(strongSelf) } } } }
  • 40. Closures - Capturing Self @stablekernel class SomeClass { var completion: () -> Void func doSomethingWithNonOptional(_ someClass: SomeClass) {…} func update() { completion = { [weak self] in guard let strongSelf = self else { return } doSomethingWithNonOptional(strongSelf) } } }
  • 41. Closures - Capturing Self @stablekernel • Self does not always need to be captured weakly • Depends on what objects may own the closure with self DispatchQueue.main.async { self.doSomething() // Not a retain cycle } UIView.animate(withDuration: 1) { self.doSomething() // Not a retain cycle } DispatchQueue.main.asyncAfter(deadline: .now() + 30) { self.doSomething() // Not a retain cycle, but... }
  • 42. Lazy Properties @stablekernel • Lazy closure properties need to capture self weakly to prevent retain cycles class Person { lazy var greeting: () -> String = { [unowned self] in return “Hi, I’m (self.name)” } } class Person { lazy var fullName: String = { return “(self.firstName) (self.lastName)” }() } • Other lazy properties do not
  • 43. Avoiding Retain Cycles @stablekernel • Delegates - delegate should be weak • Parent - Child relationships - parent property should be weak • IBOutlets - weak or strong is fine, but strong if removing and re-adding • CoreData - refresh changes to turn back into faults • Closures - be careful what you capture and how • Lazy properties - only need to capture self weakly for closure properties
  • 44. Questions? Business Inquiries: Sarah Woodward Director of Business Development sarah.woodward@stablekernel.com Marcus Smith Software Engineer marcus.smith@stablekernel.com blog.stablekernel.com