Memory Management on iOS

27

Transcript of Memory Management on iOS

Page 1: Memory Management on iOS
Page 2: Memory Management on iOS

MEMORY MANAGEMENT ON IOS

Page 3: Memory Management on iOS

AGENDA

Reference Count Based Memory Management

Manual Reference Counting

Automatic Reference Counting (ARC)

ARC vs. Tracing Garbage Collectors

Gotchas

Page 4: Memory Management on iOS

REFERENCE COUNT BASED MEMORY MANAGEMENT

Page 5: Memory Management on iOS

WHY DO WE NEED MEMORY MANAGEMENT?

func createPerson() { var p = Person()}

main

createPerson()

Person

Stack Heap

Page 6: Memory Management on iOS

WHY DO WE NEED MEMORY MANAGEMENT?

class Business { var owner: Person init() { self.owner = Person() } }

1

1

2

Person

Stack Heap

Business

ViewController

Reference Count

Page 7: Memory Management on iOS

MANUAL REFERENCE COUNTING

Page 8: Memory Management on iOS

MANUAL REFERENCE COUNTING

Objects are held in memory as long as they have a retain

count that is larger than 0

Page 9: Memory Management on iOS

MANUAL REFERENCE COUNTING

Retain count of an object is mainly determined by calls to three

different methods: retain, release, autorelease

Additionally objects you create have a retain count of 1 - in Obj-

C this is indicated by calling any method named “alloc”, “new”,

“copy”, or “mutableCopy”

Page 10: Memory Management on iOS

MANUAL REFERENCE COUNTING

- (void)createPerson { Person *person = [[[Person alloc] init] autorelease]; return person;}

+1 -1

Page 11: Memory Management on iOS

MANUAL REFERENCE COUNTING@interface Business : NSObject

@property (nonatomic, strong) Person *name;

@end

+1 -1- (void)createOwner { self.owner = [[[Person alloc] init] autorelease];} +1

- (void)freeOwner { self.owner = nil;}

-1

Page 12: Memory Management on iOS

AUTOMATIC REFERENCE COUNTING (ARC)

Page 13: Memory Management on iOS

AUTOMATIC REFERENCE COUNTING (ARC)

No manual calls to retain, release, autorelease anymore

Memory Management calls are inserted at compile time

Think in strong, weak and unowned references

Page 14: Memory Management on iOS

AUTOMATIC REFERENCE COUNTING

class Business { var owner: Person weak var building: Building? init() { self.owner = Person() self.building = Building() } }

+1+0

Page 15: Memory Management on iOS

ARC VS. TRACING GARBAGE COLLECTORS

Page 16: Memory Management on iOS

ARC VS. TRACING GARBAGE COLLECTORS

Tracing Garage Collectors are used in many higher level languages

such as C#, Java and Ruby (Python uses reference counts)

Page 17: Memory Management on iOS

ARC VS. TRACING GARBAGE COLLECTORS

Tracing GCs collect unreferenced objects after certain time periods at

runtime, typically work in two phases:

1. Mark all objects that are reachable from a root object

2. Delete all objects that are not reachable from a root object

Page 18: Memory Management on iOS

GOTCHAS

Page 19: Memory Management on iOS

GOTCHAS

Pure reference counting garbage collection mechanisms cannot detect retain cycles!

Retain cycles occur when multiple objects reference each

other strongly, but aren’t strongly referenced by any root object

Page 20: Memory Management on iOS

GOTCHASRetain cycles created by the usage of closures:

class UserViewController: UIViewController { var callback: UserDetailsCallback?

override func viewDidAppear(animated: Bool) { callback = { user in self.showUser(user) } } func showUser(user: User?) { //... } }

UserViewController

UserDetailsCallback+1

+1

Page 21: Memory Management on iOS

GOTCHASFix retain cycles using weak/unowned:

class UserViewController: UIViewController { var callback: UserDetailsCallback?

override func viewDidAppear(animated: Bool) { callback = { [unowned self] user in self.showUser(user) } } func showUser(user: User?) { //... } }

UserViewController

UserDetailsCallback+1

+0

Page 22: Memory Management on iOS

GOTCHASRetain cycles created by the usage of strong delegates:

protocol UserViewDelegate {}

class UserView { var delegate: UserViewDelegate? }

class UserViewController: UIViewController { var userView: UserView = UserView() func viewDidLoad() { super.viewDidLoad() userView.delegate = self } }

UserViewController

UserView+1

+1

Page 23: Memory Management on iOS

GOTCHASFix using a weak reference to the delegate:

protocol UserViewDelegate {}

class UserView { weak var delegate: UserViewDelegate? }

class UserViewController: UIViewController { var userView: UserView = UserView() func viewDidLoad() { super.viewDidLoad() userView.delegate = self } }

UserViewController

UserView+1

+0

Page 24: Memory Management on iOS

SUMMARY

Page 25: Memory Management on iOS

SUMMARYSwift’s memory management model is based on reference

counting

With ARC reference counting works semi-automatically, retain

and release calls are inferred from memory management specifiers (strong, weak, unowned)

Some types of memory issues that can be detected by tracing

GCs cannot be detected by reference counting, e.g. retain cycles

Page 26: Memory Management on iOS

ADDITIONAL RESOURCES

Page 27: Memory Management on iOS

ADDITIONAL RESOURCES

Apple: Advanced Memory Management Programming Guide

iOS Memory Management Using Autorelease

Wikipedia: Tracing Garbage Collectors