SlideShare une entreprise Scribd logo
1  sur  50
Memory Management
Quazi Ishtiaque Ahmed
BJIT Limited
Updated by: Saidul Islam Ziku
Memory Management
Manual Retain Release (MRR).
• Manually controlling object
ownership means to claim ownership
of any object when need and
remember to relinquish ownership
when you’re done with it.
• Balancing every alloc, retain, and
copy call with a release or
autorelease on the same object.
• Without releasing an object, its
underlying memory is never freed,
resulting in a memory leak.
• Nevertheless releasing an object too
many times, you’ll have what’s called
a dangling pointer.
MRR Memory Leak
• Simple method for
allocating a memory
without releasing after
usage. Causes Leak.
• The release method relinquishes
ownership of an object by
decrementing its reference
count.
• [inventory release];
//main.m
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSMutableArray *inventory =
[[NSMutableArray alloc] init];
[inventory addObject:@"Honda
Civic"];
NSLog(@"%@", inventory);
}
return 0;
}
MRR
Retain Removes Leaks
CarStore class implemention
// CarStore.m
#import "CarStore.h"
@implementation CarStore {
NSMutableArray *_inventory;
}
- (NSMutableArray *)inventory {
return _inventory;
}
-(void)setInventory:(NSMutableArray
*)newInventory {
_inventory = newInventory;
}
@end
CarStore class .h file
// CarStore.h
#import <Foundation/Foundation.h>
@interface CarStore : NSObject
- (NSMutableArray *)inventory;
- (void)setInventory:(NSMutableArray
*)newInventory;
@end
MRR
Retain Removes Leaks(Contd.)
Here carStore pointed the
same object as inventory
does. Thus after releasing
inventory carStore
property also be released.
//main.m
NSMutableArray *inventory =
[[NSMutableArray alloc] init];
[inventory addObject:@"Honda Civic"];
CarStore *superstore = [[CarStore
alloc] init];
[superstore setInventory:inventory];
[inventory release];
NSLog(@"%@", [superstore inventory]);
MRR
Dangling Pointer
But retain that object
causes not to update that
object with new object
passing the setter
method.
-(void)setInventory:(NSMutableArray
*)newInventory {
_inventory = [newInventory
retain];
}
MRR
Dangling Pointer(Contd.)
if (_inventory == newInventory) {
return;
}
NSMutableArray *oldValue =
_inventory; _inventory =
[newInventory retain];
[oldValue release];
}
Here How to remove dangling Pointing
ARC Defination
• In Objective-C programming, Automatic Reference Counting (ARC) is a
memory management enhancement where the burden of keeping track
of an object's reference count is lifted from the programmer to the
compiler.
• In traditional Objective-C, the programmer would send retain and release
messages to objects in order to mark objects for deallocation or to
prevent deallocation.
• Under ARC, the compiler does this automatically by examining the source
code and then adding the retain and release messages in the compiled
code.
ARC Rules
• You cannot call retain, release, retainCount, autorelease, or dealloc.
• The compiler automatically inserts the correct calls at compile time,
including messaging [super dealloc] in an override of dealloc.
Code example without ARC:
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
Code example with ARC:
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
// no need to call [super dealloc] here
}
ARC Rules (Contd.)
• You cannot cast directly between id and void.This includes casting
between Foundation objects and Core Foundation objects.
• You must use special casts, or calls to special functions, to tell the
compiler more information about the object's lifetime.
Code example without ARC:
- (NSString *)giveMeAString {
CFStringRef myString = [self someMethodThatCreatesACFString];
NSString *newString = (NSString *)myString;
return [newString autorelease];
}
Code example with ARC and a cast:
- (NSString *)giveMeAString {
CFStringRef myString = [self someMethodThatCreatesACFString]; // retain
count is 1
NSString *newString = (__bridge_transfer NSString *)myString; // the
ownership has now been transferred into ARC
return newString;
}
ARC Rules (Contd.)
• Code example with ARC and a function call:
- (NSString *)giveMeAString {
CFStringRef myString = [self
someMethodThatCreatesACFString]; // retain count is 1
NSString *newString = (NSString
*)CFBridgingRelease(myString); // the ownership has now
been transferred into ARC
return newString;
}
ARC Rules (Contd.)
• You cannot use NSAutoreleasePool objects.
• You must use the @autoreleasepool syntax. This syntax is now available
for all Objective-C modes.
Code example without ARC:
- (void)loopThroughArray:(NSArray *)array {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
for (id object in array) { // create a lot of temporary objects
}
[pool drain];
}
Code example with ARC:
- (void)loopThroughArray:(NSArray *)array {
- @autoreleasepool {
for (id object in array) {// create a lot of temporary objects
}
}
}
ARC Rules (Contd.)
• You cannot call the functions NSAllocateObject and NSDeallocateObject
• You cannot use object pointers in C structures (structs)
• You cannot use memory zones (NSZone)
• To properly cooperate with non-ARC code, you also cannot create a
method or a declared property (unless you explicitly choose a different
getter) that begins with "copy".
Pointer Variables and Object Ownership
Pointer variables imply ownership of the objects that they point to.
• When a method (or function) has a local variable that points to an object,
that variable is said to own the object being pointed to.
• When an object has an instance variable that points to another object,
the object with the pointer is said to own the object being pointed to.
Pointer Variables and Object Ownership
(Contd.)
• The idea of object ownership is useful for determining whether an object
will be destroyed so that its memory can be reused.
– An object with no owners will be destroyed.
– An object with one or more owners will not be destroyed.
How objects lose owners
• A variable that points to the object is changed to point to another object.
• A variable that points to the object is set to nil.
• The owner of the object is itself destroyed.
• The owner of the object is itself destroyed. An object in a collection, like
an array, is removed from that collection.
Ownership chains
• In main.m, after you finish printing out the array, you set the items
variable to nil. Setting items to nil causes the array to lose its only owner,
so the array is destroyed.
Ownership chains (Contd.)
• Let’s add some code so that you can see this destruction as it happens.
• NSObject implements a dealloc method, which is sent to an object just
before it is destroyed.
• You can override dealloc in BNRItem to print something to the console
when an item is destroyed.
- (void)dealloc {
NSLog(@"Destroyed: %@", self);
}
Strong Reference
• A strong reference (which you will use in most cases) means that you want to
"own" the object you are referencing with this property/variable. The compiler will
take care that any object that you assign to this property will not be destroyed as
long as you (or any other object) points to it with a strong reference. Only once
you set the property to nil then the object will get destroyed (unless one or more
other objects also hold a strong reference to it).
• A strong reference cycle occurs when two or more objects have strong references
to each other.
Step1: Add Strong Reference
• Let’s introduce a strong reference
cycle in RandomItems to see how this
works.
• First, you are going to give an
instance of BNRItem the ability to
hold another BNRItem (to represent
something like a backpack or a
purse). In addition, an item will know
which other item holds it.
• In BNRItem.h, declare two instance
variables and their accessors.
@interface BNRItem : NSObject {
NSString *_itemName;
NSString *_serialNumber;
int _valueInDollars;
NSDate *_dateCreated;
BNRItem *_containedItem;
BNRItem *_container;
}
+ (instancetype)randomItem;
- (instancetype)initWithItemName:
(NSString *)name valueInDollars:
(int)value serialNumber:(NSString
*)sNumber;
-(instancetype)initWithItemName:
(NSString *)name;
- (void)setContainedItem:(BNRItem
*)item;
- (BNRItem *)containedItem;
- (void)setContainer:(BNRItem
Step1: Add Strong Reference (Contd.)
-(BNRItem *)container;
In BNRItem.m, implement the
accessors.
-(void)setContainedItem:(BNRItem
*)item {
_containedItem = item; // When
given an item to contain, the
contained item will be given a
pointer to its container
item.container = self;
}
- (BNRItem *)containedItem {
return _containedItem;
}
- (void)setContainer:(BNRItem *)item
{
_container = item;
}
-(BNRItem *)container{
return _container;
}
In main.m, remove the code that
Step1: Add Strong Reference (Contd.)
NSLog(@"Setting items to nil...");
items = nil;
} return 0;
}
Here is what the application looks like now:
Memory Leak
• The two items cannot be accessed by any other part of the application (in this
case, main()), yet they still exist, doing nothing useful. Moreover, because they
cannot be destroyed, neither can the objects that their instance variables point to.
So it will cause a Memory Leak in the application.
• To fix this problem, one of the pointers between the items needs to be a weak
reference. To decide which one should be weak, think of the objects in the cycle as
being in a parent-child relationship. In this relationship, the parent can own its
child, but a child should never own its parent.
• In our strong reference cycle, the backpack is the parent, and the calculator is the
child. Thus, the backpack can keep its strong reference to the calculator (the
_containedItem instance variable), but the calculator’s reference to the backpack
(the _container instance variable) should be weak.
Weak References
• With a weak reference you signify that you don't want to have control over the
object's lifetime.
• The object you are referencing weakly only lives on because at least one other
object holds a strong reference to it.
• Once that is no longer the case, the object gets destroyed and your weak property
will automatically get set to nil.
• The most frequent use cases of weak references in iOS are:
 delegate properties, which are often referenced weakly to avoid retain cycles,
and
 subviews/controls of a view controller's main view because those views are
already strongly held by the main view.
Weak References (Contd.)
• Most strong reference cycles can be broken down into a parent-child relationship.
A parent typically keeps a strong reference to its child, so if a child needs a pointer
to its parent, that pointer must be a weak reference to avoid a strong reference
cycle.
• A child holding a strong reference to its parent’s parent also causes a strong
reference cycle. So the same rule applies in this situation: if a child needs a pointer
to its parent’s parent (or its parent’s parent’s parent, etc.), then that pointer must
be a weak reference.
• A weak reference knows when the object that it points to is destroyed and
responds by setting itself to nil. Thus, if the backpack is destroyed, the calculator’s
_container instance variable will be automatically set to nil. This is convenient. If
_container was not set to nil, then destroying the object would leave you with a
dangling pointer, which could crash your application.
Step-2: Add Weak Reference
• To declare a variable as a weak reference, you use the
__weak attribute. In BNRItem.h, change the container
instance variable to be a weak reference.
• __weak BNRItem *_container;
• Build and run the application again. This time, the objects are
destroyed properly.
Step-2: Add Weak References (Contd.)
Properties
Without properties With properties
BNRThing.h
@interface BNRThing :
NSObject {
NSString *_name;
}
-(void)setName:(NSString *)n;
-(NSString *)name;
@end
@interface BNRThing :
NSObject @property
NSString *name;
@end
BNRThing.m
@implementation BNRThing
- (void)setName:(NSString *)n {
_name = n;
}
-(NSString *)name {
return _name;
}
@end
@implementation
BNRThing
@end
Step-3: Declare Properties
Step-3: Declare Properties (Contd.)
@property BNRItem *containedItem;
@property BNRItem *container;
@property NSString *itemName;
@property NSString *serialNumber;
@property int valueInDollars;
@property NSDate *dateCreated;
@end
Step-4: Delete Accessor Methods
ARC Variable Qualifier
• __strong
• __weak
• __unsafe_unretained
• __autoreleasing
ARC Variable Qualifier (Contd.)
• __strong is the default. An object remains “alive” as long as there is a
strong pointer to it.
• __weak specifies a reference that does not keep the referenced object
alive. A weak reference is set to nil when there are no strong references
to the object.
• __unsafe_unretained specifies a reference that does not keep the
referenced object alive and is not set to nil when there are no strong
references to the object. If the object it references is deallocated, the
pointer is left dangling.
• __autoreleasing is used to denote arguments that are passed by
reference (id *) and are autoreleased on return.
ARC Property Attributes
• Retain
• Assign
• Unsafe_unretained
• Copy
• Strong
• Weak
• Readonly
• Readwrite
ARC Property Attributes
• retain 
 it says "keep this in the heap until I don't point to it anymore”
 In ARC it is used as strong
 Retain is the same as strong.
 Methods like "alloc" include an implicit "retain”
Example:
@property (nonatomic, retain) NSString *name;
• assign 
 Exactly like weak except it doesn't nil out the object when released
 Use assign for C primitive properties and weak references to
Objective-C objects.
Example:
@property (nonatomic, assign) NSString *address;
ARC Property Attributes (Contd.)
• copy
 copy is required when the object is mutable.
 Returns a copy of the object
Example:
@property (nonatomic, copy) NSArray *myArray;
• unsafe_unretained
 Doesn’t retain object like strong/retain attributes
 Does set to nil automatically like weak
Example:
@property (nonatomic, unsafe_unretained) NSString
*nickName;
ARC Property Attributes (Contd.)
• strong
 it says "keep this in the heap until I don't point to it anymore"
 Under ARC, strong is the default for object types.
 Retain is the same as strong.
Example:
@property(strong) MyClass *myObject
• weak
 it says "keep this as long as someone else points to it strongly"
 Under ARC, strong is the default for object types.
 Retain is the same as strong.
Example:
@property(weak) MyClass *myObject;
ARC Property Attributes (Contd.)
• readonly
 A readonly property just implements a getter.
 Can’t assign/change value
Example:
@property (nonatomic, readonly) NSDate *dateCreated;
• readwrite
 Implements both getter and setter
 Can assign/change value
Example:
@property (nonatomic, readwrite) NSDate *dateCreated;
Thread Management Property Attributes
• Nonautomic
 Nonatomic is thread unsafe.
 but it is fast in performance
Example:
@property (nonatomic, retain) NSString *name;
• Automic
 It is used as default
 Atomic is thread safe.
 It is slow in performance
• Example:
@property (retain) NSString *name;
Step-5: Add Nonautomic Attribute
• Unfortunately, the default value for this attribute is atomic, so you have
to specify that you want your properties to be nonatomic.
@interface BNRItem : NSObject
+ (instancetype)randomItem;
- (instancetype)initWithItemName:(NSString *)name valueInDollars:
(int)value serialNumber:(NSString *)sNumber;
- (instancetype)initWithItemName:(NSString *)name;
@property (nonatomic) BNRItem *containedItem;
@property (nonatomic) BNRItem *container;
@property (nonatomic) NSString *itemName;
@property (nonatomic) NSString *serialNumber;
@property (nonatomic) int valueInDollars;
@property (nonatomic) NSDate *dateCreated;
@end
Step-6: Add ReadOnly Attribute
• In BNRItem.h, declare dateCreated as a readonly property so that no
setter method is generated for this instance variable.
@property (nonatomic, readonly) NSDate *dateCreated;
Step-7: Add Strong/Weak Attribute
• In BNRItem.m, set the memory management attribute as strong for the
containedItem and dateCreated properties and weak for the container property.
@property (nonatomic, strong) BNRItem *containedItem;
@property (nonatomic, weak) BNRItem *container;
@property (nonatomic) NSString *itemName;
@property (nonatomic) NSString *serialNumber;
@property (nonatomic) int valueInDollars;
@property (nonatomic, readonly, strong) NSDate *dateCreated;
• Setting the container property to weak prevents the strong reference cycle that
you caused and fixed earlier.
Step-8: Add Copy Attribute
• In BNRItem.m, set the memory management attribute for itemName and
serialNumber as copy.
@property (nonatomic, strong) BNRItem *containedItem;
@property (nonatomic, weak) BNRItem *container;
@property (nonatomic, copy) NSString *itemName;
@property (nonatomic, copy) NSString *serialNumber;
@property (nonatomic) int valueInDollars;
@property (nonatomic, readonly, strong) NSDate
*dateCreated;
• Here is what the generated setter for itemName will look like:
- (void)setItemName:(NSString *)itemName {
_itemName = [itemName copy];
}
Step-9: Add Custom Accessor Property
• In BNRItem.m, add back an implementation for setContainedItem:.
- (void)setContainedItem:(BNRItem *)containedItem {
_containedItem = containedItem;
self.containedItem.container = self;
}
Custom Accessors with Properties
• By default, the accessors that a
property implements are very simple
and look like this:
- (void)setContainedItem:
(BNRItem *)item {
_containedItem = item;
}
- (BNRItem *)containedItem
{
return _containedItem;
}
• For most properties, this is exactly
what you want. However, for the
containedItem property, the default
setter method is not sufficient.
• The implementation of
setContainedItem: needs an extra step:
it should also set the container
property of the item being contained.
Custom Accessors with Properties (Contd.)
• When the compiler sees that you have implemented setContainedItem:, it
will not create a default setter for containedItem. It will still create the
getter method, containedItem.
• Note that if you implement both a custom setter and a custom getter (or
just a custom getter on a read-only property), then the compiler will not
create an instance variable for your property. If you need one, you must
declare it yourself.
• Note the moral: sometimes the default accessors do not do what you
need, and you will need to implement them yourself.
• Now you can build and run the application. The leaner BNRItem works in
the exact same way.
Synthesize Property
@synthesize age = _age; // Other methods go here @end
• This is how properties are automatically synthesized. The first attribute
(age) says “create methods named age and setAge:,” and the second
attribute (_age) says “the instance variable that backs these methods
should be _age.”
• You can optionally leave off the variable name, which creates a backing
variable with the same name as the accessors.
@synthesize age;
// Is the same as:
@synthesize age = age;
@autoreleasepool Directive
• With ARC, this is done automatically (and sometimes optimized out
completely). An autorelease pool is created by the @autoreleasepool
directive followed by curly braces.
• Inside those curly braces, any newly instantiated object returned from a
method that does not have alloc or copy in its name is placed in that
autorelease pool. When the curly brace closes, any object in the pool loses
an owner.
@autoreleasepool { // Get a BNRItem back from a method that
created it, method does not say alloc/copy
BNRItem *item = [BNRItem someItem];
} // Pool is drained, item loses an owner and is destroyed
• iOS applications automatically create an autorelease pool for you, and you
really do not have to concern yourself with it.
@autoreleasepool Directive (Contd.)
• Autorelease pool blocks provide a mechanism whereby you
can relinquish ownership of an object, but avoid the
possibility of it being deallocated immediately (such as when
you return an object from a method).
• Typically, you don’t need to create your own autorelease pool
blocks, but there are some situations in which either you
must or it is beneficial to do so.

Contenu connexe

Tendances

Useful and Practical Functionalities in Realm
Useful and Practical Functionalities in RealmUseful and Practical Functionalities in Realm
Useful and Practical Functionalities in RealmYusuke Kita
 
Advanced JavaScript
Advanced JavaScriptAdvanced JavaScript
Advanced JavaScriptNascenia IT
 
Object Oriented Programming in JavaScript
Object Oriented Programming in JavaScriptObject Oriented Programming in JavaScript
Object Oriented Programming in JavaScriptzand3rs
 
Ios development
Ios developmentIos development
Ios developmentelnaqah
 
Arc of developer part1
Arc of developer part1Arc of developer part1
Arc of developer part1Junpei Wada
 
Everything is Permitted: Extending Built-ins
Everything is Permitted: Extending Built-insEverything is Permitted: Extending Built-ins
Everything is Permitted: Extending Built-insAndrew Dupont
 
Action Script
Action ScriptAction Script
Action ScriptAngelin R
 
Advanced Javascript
Advanced JavascriptAdvanced Javascript
Advanced JavascriptAdieu
 
From C++ to Objective-C
From C++ to Objective-CFrom C++ to Objective-C
From C++ to Objective-Ccorehard_by
 
Omnisearch in AEM 6.2 - Search All the Things
Omnisearch in AEM 6.2 - Search All the ThingsOmnisearch in AEM 6.2 - Search All the Things
Omnisearch in AEM 6.2 - Search All the ThingsJustin Edelson
 
Writing native bindings to node.js in C++
Writing native bindings to node.js in C++Writing native bindings to node.js in C++
Writing native bindings to node.js in C++nsm.nikhil
 
Advanced JavaScript
Advanced JavaScriptAdvanced JavaScript
Advanced JavaScriptFu Cheng
 
Writing and using Hamcrest Matchers
Writing and using Hamcrest MatchersWriting and using Hamcrest Matchers
Writing and using Hamcrest MatchersShai Yallin
 
Advanced realm in swift
Advanced realm in swiftAdvanced realm in swift
Advanced realm in swiftYusuke Kita
 
A JIT Smalltalk VM written in itself
A JIT Smalltalk VM written in itselfA JIT Smalltalk VM written in itself
A JIT Smalltalk VM written in itselfESUG
 
Lombok Features
Lombok FeaturesLombok Features
Lombok Features文峰 眭
 

Tendances (20)

Useful and Practical Functionalities in Realm
Useful and Practical Functionalities in RealmUseful and Practical Functionalities in Realm
Useful and Practical Functionalities in Realm
 
Advanced JavaScript
Advanced JavaScriptAdvanced JavaScript
Advanced JavaScript
 
Object Oriented Programming in JavaScript
Object Oriented Programming in JavaScriptObject Oriented Programming in JavaScript
Object Oriented Programming in JavaScript
 
Ios development
Ios developmentIos development
Ios development
 
Extending Node.js using C++
Extending Node.js using C++Extending Node.js using C++
Extending Node.js using C++
 
Arc of developer part1
Arc of developer part1Arc of developer part1
Arc of developer part1
 
Realm database
Realm databaseRealm database
Realm database
 
Everything is Permitted: Extending Built-ins
Everything is Permitted: Extending Built-insEverything is Permitted: Extending Built-ins
Everything is Permitted: Extending Built-ins
 
Action Script
Action ScriptAction Script
Action Script
 
Advanced Javascript
Advanced JavascriptAdvanced Javascript
Advanced Javascript
 
JavaScript Basics
JavaScript BasicsJavaScript Basics
JavaScript Basics
 
From C++ to Objective-C
From C++ to Objective-CFrom C++ to Objective-C
From C++ to Objective-C
 
Omnisearch in AEM 6.2 - Search All the Things
Omnisearch in AEM 6.2 - Search All the ThingsOmnisearch in AEM 6.2 - Search All the Things
Omnisearch in AEM 6.2 - Search All the Things
 
Writing native bindings to node.js in C++
Writing native bindings to node.js in C++Writing native bindings to node.js in C++
Writing native bindings to node.js in C++
 
Advanced JavaScript
Advanced JavaScriptAdvanced JavaScript
Advanced JavaScript
 
Writing and using Hamcrest Matchers
Writing and using Hamcrest MatchersWriting and using Hamcrest Matchers
Writing and using Hamcrest Matchers
 
Advanced realm in swift
Advanced realm in swiftAdvanced realm in swift
Advanced realm in swift
 
A JIT Smalltalk VM written in itself
A JIT Smalltalk VM written in itselfA JIT Smalltalk VM written in itself
A JIT Smalltalk VM written in itself
 
Lombok Features
Lombok FeaturesLombok Features
Lombok Features
 
Advanced JavaScript
Advanced JavaScriptAdvanced JavaScript
Advanced JavaScript
 

Similaire à Lecture 3-ARC

【Unite 2017 Tokyo】ScriptableObjectを使ってプログラマーもアーティストも幸せになろう
【Unite 2017 Tokyo】ScriptableObjectを使ってプログラマーもアーティストも幸せになろう【Unite 2017 Tokyo】ScriptableObjectを使ってプログラマーもアーティストも幸せになろう
【Unite 2017 Tokyo】ScriptableObjectを使ってプログラマーもアーティストも幸せになろうUnity Technologies Japan K.K.
 
[OOP - Lec 13,14,15] Constructors / Destructor and its Types
[OOP - Lec 13,14,15] Constructors / Destructor and its Types[OOP - Lec 13,14,15] Constructors / Destructor and its Types
[OOP - Lec 13,14,15] Constructors / Destructor and its TypesMuhammad Hammad Waseem
 
2CPP13 - Operator Overloading
2CPP13 - Operator Overloading2CPP13 - Operator Overloading
2CPP13 - Operator OverloadingMichael Heron
 
iPhone dev intro
iPhone dev introiPhone dev intro
iPhone dev introVonbo
 
Beginning to iPhone development
Beginning to iPhone developmentBeginning to iPhone development
Beginning to iPhone developmentVonbo
 
Никита Корчагин - Programming Apple iOS with Objective-C
Никита Корчагин - Programming Apple iOS with Objective-CНикита Корчагин - Programming Apple iOS with Objective-C
Никита Корчагин - Programming Apple iOS with Objective-CDataArt
 
iOS Memory Management Basics
iOS Memory Management BasicsiOS Memory Management Basics
iOS Memory Management BasicsBilue
 
【Unite 2017 Tokyo】パフォーマンス向上のためのスクリプトのベストプラクティス
【Unite 2017 Tokyo】パフォーマンス向上のためのスクリプトのベストプラクティス【Unite 2017 Tokyo】パフォーマンス向上のためのスクリプトのベストプラクティス
【Unite 2017 Tokyo】パフォーマンス向上のためのスクリプトのベストプラクティスUnity Technologies Japan K.K.
 
Oop lec 5-(class objects, constructor & destructor)
Oop lec 5-(class objects, constructor & destructor)Oop lec 5-(class objects, constructor & destructor)
Oop lec 5-(class objects, constructor & destructor)Asfand Hassan
 
Connect.Tech- Swift Memory Management
Connect.Tech- Swift Memory ManagementConnect.Tech- Swift Memory Management
Connect.Tech- Swift Memory Managementstable|kernel
 
C++ Introduction brown bag
C++ Introduction brown bagC++ Introduction brown bag
C++ Introduction brown bagJacob Green
 
Objective-C for iOS Application Development
Objective-C for iOS Application DevelopmentObjective-C for iOS Application Development
Objective-C for iOS Application DevelopmentDhaval Kaneria
 

Similaire à Lecture 3-ARC (20)

【Unite 2017 Tokyo】ScriptableObjectを使ってプログラマーもアーティストも幸せになろう
【Unite 2017 Tokyo】ScriptableObjectを使ってプログラマーもアーティストも幸せになろう【Unite 2017 Tokyo】ScriptableObjectを使ってプログラマーもアーティストも幸せになろう
【Unite 2017 Tokyo】ScriptableObjectを使ってプログラマーもアーティストも幸せになろう
 
iOS Memory Management
iOS Memory ManagementiOS Memory Management
iOS Memory Management
 
[OOP - Lec 13,14,15] Constructors / Destructor and its Types
[OOP - Lec 13,14,15] Constructors / Destructor and its Types[OOP - Lec 13,14,15] Constructors / Destructor and its Types
[OOP - Lec 13,14,15] Constructors / Destructor and its Types
 
2CPP13 - Operator Overloading
2CPP13 - Operator Overloading2CPP13 - Operator Overloading
2CPP13 - Operator Overloading
 
Ahieving Performance C#
Ahieving Performance C#Ahieving Performance C#
Ahieving Performance C#
 
Day 2
Day 2Day 2
Day 2
 
iPhone dev intro
iPhone dev introiPhone dev intro
iPhone dev intro
 
Beginning to iPhone development
Beginning to iPhone developmentBeginning to iPhone development
Beginning to iPhone development
 
About Python
About PythonAbout Python
About Python
 
Никита Корчагин - Programming Apple iOS with Objective-C
Никита Корчагин - Programming Apple iOS with Objective-CНикита Корчагин - Programming Apple iOS with Objective-C
Никита Корчагин - Programming Apple iOS with Objective-C
 
iOS Memory Management Basics
iOS Memory Management BasicsiOS Memory Management Basics
iOS Memory Management Basics
 
【Unite 2017 Tokyo】パフォーマンス向上のためのスクリプトのベストプラクティス
【Unite 2017 Tokyo】パフォーマンス向上のためのスクリプトのベストプラクティス【Unite 2017 Tokyo】パフォーマンス向上のためのスクリプトのベストプラクティス
【Unite 2017 Tokyo】パフォーマンス向上のためのスクリプトのベストプラクティス
 
Memory Management In C++
Memory Management In C++Memory Management In C++
Memory Management In C++
 
Oop lec 5-(class objects, constructor & destructor)
Oop lec 5-(class objects, constructor & destructor)Oop lec 5-(class objects, constructor & destructor)
Oop lec 5-(class objects, constructor & destructor)
 
Connect.Tech- Swift Memory Management
Connect.Tech- Swift Memory ManagementConnect.Tech- Swift Memory Management
Connect.Tech- Swift Memory Management
 
Ios - Introduction to memory management
Ios - Introduction to memory managementIos - Introduction to memory management
Ios - Introduction to memory management
 
C++ Introduction brown bag
C++ Introduction brown bagC++ Introduction brown bag
C++ Introduction brown bag
 
KnockoutJS and MVVM
KnockoutJS and MVVMKnockoutJS and MVVM
KnockoutJS and MVVM
 
Objective-C for iOS Application Development
Objective-C for iOS Application DevelopmentObjective-C for iOS Application Development
Objective-C for iOS Application Development
 
Objective c
Objective cObjective c
Objective c
 

Lecture 3-ARC

  • 1. Memory Management Quazi Ishtiaque Ahmed BJIT Limited Updated by: Saidul Islam Ziku
  • 3. Manual Retain Release (MRR). • Manually controlling object ownership means to claim ownership of any object when need and remember to relinquish ownership when you’re done with it. • Balancing every alloc, retain, and copy call with a release or autorelease on the same object. • Without releasing an object, its underlying memory is never freed, resulting in a memory leak. • Nevertheless releasing an object too many times, you’ll have what’s called a dangling pointer.
  • 4. MRR Memory Leak • Simple method for allocating a memory without releasing after usage. Causes Leak. • The release method relinquishes ownership of an object by decrementing its reference count. • [inventory release]; //main.m #import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { NSMutableArray *inventory = [[NSMutableArray alloc] init]; [inventory addObject:@"Honda Civic"]; NSLog(@"%@", inventory); } return 0; }
  • 5. MRR Retain Removes Leaks CarStore class implemention // CarStore.m #import "CarStore.h" @implementation CarStore { NSMutableArray *_inventory; } - (NSMutableArray *)inventory { return _inventory; } -(void)setInventory:(NSMutableArray *)newInventory { _inventory = newInventory; } @end CarStore class .h file // CarStore.h #import <Foundation/Foundation.h> @interface CarStore : NSObject - (NSMutableArray *)inventory; - (void)setInventory:(NSMutableArray *)newInventory; @end
  • 6. MRR Retain Removes Leaks(Contd.) Here carStore pointed the same object as inventory does. Thus after releasing inventory carStore property also be released. //main.m NSMutableArray *inventory = [[NSMutableArray alloc] init]; [inventory addObject:@"Honda Civic"]; CarStore *superstore = [[CarStore alloc] init]; [superstore setInventory:inventory]; [inventory release]; NSLog(@"%@", [superstore inventory]);
  • 7. MRR Dangling Pointer But retain that object causes not to update that object with new object passing the setter method. -(void)setInventory:(NSMutableArray *)newInventory { _inventory = [newInventory retain]; }
  • 8. MRR Dangling Pointer(Contd.) if (_inventory == newInventory) { return; } NSMutableArray *oldValue = _inventory; _inventory = [newInventory retain]; [oldValue release]; } Here How to remove dangling Pointing
  • 9. ARC Defination • In Objective-C programming, Automatic Reference Counting (ARC) is a memory management enhancement where the burden of keeping track of an object's reference count is lifted from the programmer to the compiler. • In traditional Objective-C, the programmer would send retain and release messages to objects in order to mark objects for deallocation or to prevent deallocation. • Under ARC, the compiler does this automatically by examining the source code and then adding the retain and release messages in the compiled code.
  • 10. ARC Rules • You cannot call retain, release, retainCount, autorelease, or dealloc. • The compiler automatically inserts the correct calls at compile time, including messaging [super dealloc] in an override of dealloc. Code example without ARC: - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; [super dealloc]; } Code example with ARC: - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; // no need to call [super dealloc] here }
  • 11. ARC Rules (Contd.) • You cannot cast directly between id and void.This includes casting between Foundation objects and Core Foundation objects. • You must use special casts, or calls to special functions, to tell the compiler more information about the object's lifetime. Code example without ARC: - (NSString *)giveMeAString { CFStringRef myString = [self someMethodThatCreatesACFString]; NSString *newString = (NSString *)myString; return [newString autorelease]; } Code example with ARC and a cast: - (NSString *)giveMeAString { CFStringRef myString = [self someMethodThatCreatesACFString]; // retain count is 1 NSString *newString = (__bridge_transfer NSString *)myString; // the ownership has now been transferred into ARC return newString; }
  • 12. ARC Rules (Contd.) • Code example with ARC and a function call: - (NSString *)giveMeAString { CFStringRef myString = [self someMethodThatCreatesACFString]; // retain count is 1 NSString *newString = (NSString *)CFBridgingRelease(myString); // the ownership has now been transferred into ARC return newString; }
  • 13. ARC Rules (Contd.) • You cannot use NSAutoreleasePool objects. • You must use the @autoreleasepool syntax. This syntax is now available for all Objective-C modes. Code example without ARC: - (void)loopThroughArray:(NSArray *)array { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; for (id object in array) { // create a lot of temporary objects } [pool drain]; } Code example with ARC: - (void)loopThroughArray:(NSArray *)array { - @autoreleasepool { for (id object in array) {// create a lot of temporary objects } } }
  • 14. ARC Rules (Contd.) • You cannot call the functions NSAllocateObject and NSDeallocateObject • You cannot use object pointers in C structures (structs) • You cannot use memory zones (NSZone) • To properly cooperate with non-ARC code, you also cannot create a method or a declared property (unless you explicitly choose a different getter) that begins with "copy".
  • 15. Pointer Variables and Object Ownership Pointer variables imply ownership of the objects that they point to. • When a method (or function) has a local variable that points to an object, that variable is said to own the object being pointed to. • When an object has an instance variable that points to another object, the object with the pointer is said to own the object being pointed to.
  • 16. Pointer Variables and Object Ownership (Contd.) • The idea of object ownership is useful for determining whether an object will be destroyed so that its memory can be reused. – An object with no owners will be destroyed. – An object with one or more owners will not be destroyed.
  • 17. How objects lose owners • A variable that points to the object is changed to point to another object. • A variable that points to the object is set to nil. • The owner of the object is itself destroyed. • The owner of the object is itself destroyed. An object in a collection, like an array, is removed from that collection.
  • 18. Ownership chains • In main.m, after you finish printing out the array, you set the items variable to nil. Setting items to nil causes the array to lose its only owner, so the array is destroyed.
  • 19. Ownership chains (Contd.) • Let’s add some code so that you can see this destruction as it happens. • NSObject implements a dealloc method, which is sent to an object just before it is destroyed. • You can override dealloc in BNRItem to print something to the console when an item is destroyed. - (void)dealloc { NSLog(@"Destroyed: %@", self); }
  • 20. Strong Reference • A strong reference (which you will use in most cases) means that you want to "own" the object you are referencing with this property/variable. The compiler will take care that any object that you assign to this property will not be destroyed as long as you (or any other object) points to it with a strong reference. Only once you set the property to nil then the object will get destroyed (unless one or more other objects also hold a strong reference to it). • A strong reference cycle occurs when two or more objects have strong references to each other.
  • 21. Step1: Add Strong Reference • Let’s introduce a strong reference cycle in RandomItems to see how this works. • First, you are going to give an instance of BNRItem the ability to hold another BNRItem (to represent something like a backpack or a purse). In addition, an item will know which other item holds it. • In BNRItem.h, declare two instance variables and their accessors. @interface BNRItem : NSObject { NSString *_itemName; NSString *_serialNumber; int _valueInDollars; NSDate *_dateCreated; BNRItem *_containedItem; BNRItem *_container; } + (instancetype)randomItem; - (instancetype)initWithItemName: (NSString *)name valueInDollars: (int)value serialNumber:(NSString *)sNumber; -(instancetype)initWithItemName: (NSString *)name; - (void)setContainedItem:(BNRItem *)item; - (BNRItem *)containedItem; - (void)setContainer:(BNRItem
  • 22. Step1: Add Strong Reference (Contd.) -(BNRItem *)container; In BNRItem.m, implement the accessors. -(void)setContainedItem:(BNRItem *)item { _containedItem = item; // When given an item to contain, the contained item will be given a pointer to its container item.container = self; } - (BNRItem *)containedItem { return _containedItem; } - (void)setContainer:(BNRItem *)item { _container = item; } -(BNRItem *)container{ return _container; } In main.m, remove the code that
  • 23. Step1: Add Strong Reference (Contd.) NSLog(@"Setting items to nil..."); items = nil; } return 0; } Here is what the application looks like now:
  • 24. Memory Leak • The two items cannot be accessed by any other part of the application (in this case, main()), yet they still exist, doing nothing useful. Moreover, because they cannot be destroyed, neither can the objects that their instance variables point to. So it will cause a Memory Leak in the application. • To fix this problem, one of the pointers between the items needs to be a weak reference. To decide which one should be weak, think of the objects in the cycle as being in a parent-child relationship. In this relationship, the parent can own its child, but a child should never own its parent. • In our strong reference cycle, the backpack is the parent, and the calculator is the child. Thus, the backpack can keep its strong reference to the calculator (the _containedItem instance variable), but the calculator’s reference to the backpack (the _container instance variable) should be weak.
  • 25. Weak References • With a weak reference you signify that you don't want to have control over the object's lifetime. • The object you are referencing weakly only lives on because at least one other object holds a strong reference to it. • Once that is no longer the case, the object gets destroyed and your weak property will automatically get set to nil. • The most frequent use cases of weak references in iOS are:  delegate properties, which are often referenced weakly to avoid retain cycles, and  subviews/controls of a view controller's main view because those views are already strongly held by the main view.
  • 26. Weak References (Contd.) • Most strong reference cycles can be broken down into a parent-child relationship. A parent typically keeps a strong reference to its child, so if a child needs a pointer to its parent, that pointer must be a weak reference to avoid a strong reference cycle. • A child holding a strong reference to its parent’s parent also causes a strong reference cycle. So the same rule applies in this situation: if a child needs a pointer to its parent’s parent (or its parent’s parent’s parent, etc.), then that pointer must be a weak reference. • A weak reference knows when the object that it points to is destroyed and responds by setting itself to nil. Thus, if the backpack is destroyed, the calculator’s _container instance variable will be automatically set to nil. This is convenient. If _container was not set to nil, then destroying the object would leave you with a dangling pointer, which could crash your application.
  • 27. Step-2: Add Weak Reference • To declare a variable as a weak reference, you use the __weak attribute. In BNRItem.h, change the container instance variable to be a weak reference. • __weak BNRItem *_container; • Build and run the application again. This time, the objects are destroyed properly.
  • 28. Step-2: Add Weak References (Contd.)
  • 29. Properties Without properties With properties BNRThing.h @interface BNRThing : NSObject { NSString *_name; } -(void)setName:(NSString *)n; -(NSString *)name; @end @interface BNRThing : NSObject @property NSString *name; @end BNRThing.m @implementation BNRThing - (void)setName:(NSString *)n { _name = n; } -(NSString *)name { return _name; } @end @implementation BNRThing @end
  • 31. Step-3: Declare Properties (Contd.) @property BNRItem *containedItem; @property BNRItem *container; @property NSString *itemName; @property NSString *serialNumber; @property int valueInDollars; @property NSDate *dateCreated; @end
  • 33. ARC Variable Qualifier • __strong • __weak • __unsafe_unretained • __autoreleasing
  • 34. ARC Variable Qualifier (Contd.) • __strong is the default. An object remains “alive” as long as there is a strong pointer to it. • __weak specifies a reference that does not keep the referenced object alive. A weak reference is set to nil when there are no strong references to the object. • __unsafe_unretained specifies a reference that does not keep the referenced object alive and is not set to nil when there are no strong references to the object. If the object it references is deallocated, the pointer is left dangling. • __autoreleasing is used to denote arguments that are passed by reference (id *) and are autoreleased on return.
  • 35. ARC Property Attributes • Retain • Assign • Unsafe_unretained • Copy • Strong • Weak • Readonly • Readwrite
  • 36. ARC Property Attributes • retain   it says "keep this in the heap until I don't point to it anymore”  In ARC it is used as strong  Retain is the same as strong.  Methods like "alloc" include an implicit "retain” Example: @property (nonatomic, retain) NSString *name; • assign   Exactly like weak except it doesn't nil out the object when released  Use assign for C primitive properties and weak references to Objective-C objects. Example: @property (nonatomic, assign) NSString *address;
  • 37. ARC Property Attributes (Contd.) • copy  copy is required when the object is mutable.  Returns a copy of the object Example: @property (nonatomic, copy) NSArray *myArray; • unsafe_unretained  Doesn’t retain object like strong/retain attributes  Does set to nil automatically like weak Example: @property (nonatomic, unsafe_unretained) NSString *nickName;
  • 38. ARC Property Attributes (Contd.) • strong  it says "keep this in the heap until I don't point to it anymore"  Under ARC, strong is the default for object types.  Retain is the same as strong. Example: @property(strong) MyClass *myObject • weak  it says "keep this as long as someone else points to it strongly"  Under ARC, strong is the default for object types.  Retain is the same as strong. Example: @property(weak) MyClass *myObject;
  • 39. ARC Property Attributes (Contd.) • readonly  A readonly property just implements a getter.  Can’t assign/change value Example: @property (nonatomic, readonly) NSDate *dateCreated; • readwrite  Implements both getter and setter  Can assign/change value Example: @property (nonatomic, readwrite) NSDate *dateCreated;
  • 40. Thread Management Property Attributes • Nonautomic  Nonatomic is thread unsafe.  but it is fast in performance Example: @property (nonatomic, retain) NSString *name; • Automic  It is used as default  Atomic is thread safe.  It is slow in performance • Example: @property (retain) NSString *name;
  • 41. Step-5: Add Nonautomic Attribute • Unfortunately, the default value for this attribute is atomic, so you have to specify that you want your properties to be nonatomic. @interface BNRItem : NSObject + (instancetype)randomItem; - (instancetype)initWithItemName:(NSString *)name valueInDollars: (int)value serialNumber:(NSString *)sNumber; - (instancetype)initWithItemName:(NSString *)name; @property (nonatomic) BNRItem *containedItem; @property (nonatomic) BNRItem *container; @property (nonatomic) NSString *itemName; @property (nonatomic) NSString *serialNumber; @property (nonatomic) int valueInDollars; @property (nonatomic) NSDate *dateCreated; @end
  • 42. Step-6: Add ReadOnly Attribute • In BNRItem.h, declare dateCreated as a readonly property so that no setter method is generated for this instance variable. @property (nonatomic, readonly) NSDate *dateCreated;
  • 43. Step-7: Add Strong/Weak Attribute • In BNRItem.m, set the memory management attribute as strong for the containedItem and dateCreated properties and weak for the container property. @property (nonatomic, strong) BNRItem *containedItem; @property (nonatomic, weak) BNRItem *container; @property (nonatomic) NSString *itemName; @property (nonatomic) NSString *serialNumber; @property (nonatomic) int valueInDollars; @property (nonatomic, readonly, strong) NSDate *dateCreated; • Setting the container property to weak prevents the strong reference cycle that you caused and fixed earlier.
  • 44. Step-8: Add Copy Attribute • In BNRItem.m, set the memory management attribute for itemName and serialNumber as copy. @property (nonatomic, strong) BNRItem *containedItem; @property (nonatomic, weak) BNRItem *container; @property (nonatomic, copy) NSString *itemName; @property (nonatomic, copy) NSString *serialNumber; @property (nonatomic) int valueInDollars; @property (nonatomic, readonly, strong) NSDate *dateCreated; • Here is what the generated setter for itemName will look like: - (void)setItemName:(NSString *)itemName { _itemName = [itemName copy]; }
  • 45. Step-9: Add Custom Accessor Property • In BNRItem.m, add back an implementation for setContainedItem:. - (void)setContainedItem:(BNRItem *)containedItem { _containedItem = containedItem; self.containedItem.container = self; }
  • 46. Custom Accessors with Properties • By default, the accessors that a property implements are very simple and look like this: - (void)setContainedItem: (BNRItem *)item { _containedItem = item; } - (BNRItem *)containedItem { return _containedItem; } • For most properties, this is exactly what you want. However, for the containedItem property, the default setter method is not sufficient. • The implementation of setContainedItem: needs an extra step: it should also set the container property of the item being contained.
  • 47. Custom Accessors with Properties (Contd.) • When the compiler sees that you have implemented setContainedItem:, it will not create a default setter for containedItem. It will still create the getter method, containedItem. • Note that if you implement both a custom setter and a custom getter (or just a custom getter on a read-only property), then the compiler will not create an instance variable for your property. If you need one, you must declare it yourself. • Note the moral: sometimes the default accessors do not do what you need, and you will need to implement them yourself. • Now you can build and run the application. The leaner BNRItem works in the exact same way.
  • 48. Synthesize Property @synthesize age = _age; // Other methods go here @end • This is how properties are automatically synthesized. The first attribute (age) says “create methods named age and setAge:,” and the second attribute (_age) says “the instance variable that backs these methods should be _age.” • You can optionally leave off the variable name, which creates a backing variable with the same name as the accessors. @synthesize age; // Is the same as: @synthesize age = age;
  • 49. @autoreleasepool Directive • With ARC, this is done automatically (and sometimes optimized out completely). An autorelease pool is created by the @autoreleasepool directive followed by curly braces. • Inside those curly braces, any newly instantiated object returned from a method that does not have alloc or copy in its name is placed in that autorelease pool. When the curly brace closes, any object in the pool loses an owner. @autoreleasepool { // Get a BNRItem back from a method that created it, method does not say alloc/copy BNRItem *item = [BNRItem someItem]; } // Pool is drained, item loses an owner and is destroyed • iOS applications automatically create an autorelease pool for you, and you really do not have to concern yourself with it.
  • 50. @autoreleasepool Directive (Contd.) • Autorelease pool blocks provide a mechanism whereby you can relinquish ownership of an object, but avoid the possibility of it being deallocated immediately (such as when you return an object from a method). • Typically, you don’t need to create your own autorelease pool blocks, but there are some situations in which either you must or it is beneficial to do so.