Modernizes your objective C - Oliviero

279
Modernizes your Objective-C Massimo Oliviero Software Developer @maxoly

description

Slides from Massimo Oliviero talk @Codemotion Roma 2014

Transcript of Modernizes your objective C - Oliviero

Page 1: Modernizes your objective C - Oliviero

Modernizes your Objective-C

Massimo Oliviero!Software Developer

@maxoly

Page 2: Modernizes your objective C - Oliviero

About

Massimo OlivieroFreelance Software Developer & Trainer#pragma mark founder

!

[email protected] @maxoly

Page 3: Modernizes your objective C - Oliviero

#pragma mark

iOS & OSX Developers Community

We organize the #PragmaConference, an event dedicated to iOS and OS X development

!

http://www.pragmamark.org

http://www.facebook.com/groups/pragmamark

@pragmamarkorg

Page 4: Modernizes your objective C - Oliviero

Agenda

Page 5: Modernizes your objective C - Oliviero

Agenda‣ Syntax

Page 6: Modernizes your objective C - Oliviero

Agenda‣ Syntax

‣ Conventions

Page 7: Modernizes your objective C - Oliviero

Agenda‣ Syntax

‣ Conventions

‣ Coding

Page 8: Modernizes your objective C - Oliviero

Agenda‣ Syntax

‣ Conventions

‣ Coding

‣ Framework

Page 9: Modernizes your objective C - Oliviero

Syntax

Page 10: Modernizes your objective C - Oliviero

use new literal syntaxyou can create NSArray, NSDictionary, NSNumber with a simple @

Page 11: Modernizes your objective C - Oliviero

Literals

NSArray *names = [NSArray arrayWithObjects:@"Marco", @"Paolo", @"Flavio", nil]; NSDictionary *jobs = [NSDictionary dictionaryWithObjectsAndKeys:@"Marco", @"CTO", @"Paolo", "CEO", nil]; NSNumber *one = [NSNumber numberWithInt:1]; NSNumber *boolNum = [NSNumber numberWithBool:YES]; NSNumber *square = [NSNumber numberWithDouble:sqrt(2)];

Page 12: Modernizes your objective C - Oliviero

Literals

NSArray *names = [NSArray arrayWithObjects:@"Marco", @"Paolo", @"Flavio", nil]; NSDictionary *jobs = [NSDictionary dictionaryWithObjectsAndKeys:@"Marco", @"CTO", @"Paolo", "CEO", nil]; NSNumber *one = [NSNumber numberWithInt:1]; NSNumber *boolNum = [NSNumber numberWithBool:YES]; NSNumber *square = [NSNumber numberWithDouble:sqrt(2)];

NSArray *names = @[ @"Marco", @"Paolo", @"Giuseppe" ]; ! NSDictionary *jobs = @{ @"CTO" : @"Marco", @"CEO" : @"Paolo" }; ! NSNumber *one = @1; NSNumber *boolNum = @YES; NSNumber *square = @(sqrt(2));

Page 13: Modernizes your objective C - Oliviero

Literals

Page 14: Modernizes your objective C - Oliviero

Literals‣ The new object literals significantly reduce the

verbosity of code

Page 15: Modernizes your objective C - Oliviero

Literals‣ The new object literals significantly reduce the

verbosity of code

‣ All objects made via literal (such an array or a dictionary) are immutable

Page 16: Modernizes your objective C - Oliviero

Literals‣ The new object literals significantly reduce the

verbosity of code

‣ All objects made via literal (such an array or a dictionary) are immutable

‣ Remember that @(expr) dynamically evaluates the boxed expression and returns the appropriate object literal based on its value

Page 17: Modernizes your objective C - Oliviero

use Object SubscriptingObject pointer values can now be used with C’s subscripting operator

Page 18: Modernizes your objective C - Oliviero

Object Subscripting

! NSArray *people = @[ @"John", @"Steve", @"Bill" ]; NSString *steve = [people objectAtIndex:1]; NSDictionary *books = @{ @"123" : @"Odyssey", @"234" : @"Illiad" }; NSString *illiad = [books objectForKey:@“234"]; ! // Mutable NSMutableArray *mPeople = [people mutableCopy]; [mPeople addObject:@"Ive"]; NSMutableDictionary *mBooks = [books mutableCopy]; [mBooks setObject:@"Othello" forKey:@"876"];

Page 19: Modernizes your objective C - Oliviero

Object Subscripting

! NSArray *people = @[ @"John", @"Steve", @"Bill" ]; NSString *steve = [people objectAtIndex:1]; NSDictionary *books = @{ @"123" : @"Odyssey", @"234" : @"Illiad" }; NSString *illiad = [books objectForKey:@“234"]; ! // Mutable NSMutableArray *mPeople = [people mutableCopy]; [mPeople addObject:@"Ive"]; NSMutableDictionary *mBooks = [books mutableCopy]; [mBooks setObject:@"Othello" forKey:@"876"];

! NSArray *people = @[ @"John", @"Steve", @"Bill" ]; NSString *steve = people[1]; NSDictionary *books = @{ @"123" : @"Odyssey", @"234" : @"Illiad" }; NSString *illiad = books[@"234"]; !! // Mutable NSMutableArray *mPeople = [people mutableCopy]; mPeople[3] = @"Ive"; NSMutableDictionary *mBooks = [books mutableCopy]; mBooks[@"876"] = @"Othello";

Page 20: Modernizes your objective C - Oliviero

Custom Subscripting

Page 21: Modernizes your objective C - Oliviero

Custom Subscripting@interface MGACustomer : NSObject

@property (nonatomic, strong, readonly) NSArray *orders;

// Custom Indexed Subscripting- (id)objectAtIndexedSubscript:(NSUInteger)idx;- (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx;

// Custom Keyed Subscripting- (id)objectForKeyedSubscript:(id <NSCopying>)key;- (void)setObject:(id)obj forKeyedSubscript:(id <NSCopying>)key;

@end

// how to use custom subscripting- (void)foo{

MGACustomer *customer = [[MGACustomer alloc] init];

id order67 = customer[67];id order34 = customer[@"order.34"];

}

Page 22: Modernizes your objective C - Oliviero

Object Subscripting

Page 23: Modernizes your objective C - Oliviero

Object Subscripting‣ Subscripting syntax can significantly reduce the

verbosity of code that deals heavily with arrays and dictionaries

Page 24: Modernizes your objective C - Oliviero

Object Subscripting‣ Subscripting syntax can significantly reduce the

verbosity of code that deals heavily with arrays and dictionaries

‣ Syntax similar to that found in common scripting languages

Page 25: Modernizes your objective C - Oliviero

Object Subscripting‣ Subscripting syntax can significantly reduce the

verbosity of code that deals heavily with arrays and dictionaries

‣ Syntax similar to that found in common scripting languages

‣ You can extend your own classes with subscripting support

Page 26: Modernizes your objective C - Oliviero

use new @import declaration@import is the new compiler directive introduced by Modules

Page 27: Modernizes your objective C - Oliviero

@import

#import <UIKit/UIKit.h> #import <MapKit/MapKit.h> // you must add framework from Target > Build Phases !!@interface MGAMapViewController : UIViewController !@property (weak, nonatomic) IBOutlet MKMapView *mapView; !@end

Page 28: Modernizes your objective C - Oliviero

@import

#import <UIKit/UIKit.h> #import <MapKit/MapKit.h> // you must add framework from Target > Build Phases !!@interface MGAMapViewController : UIViewController !@property (weak, nonatomic) IBOutlet MKMapView *mapView; !@end

@import UIKit; @import MapKit; // no additional steps required !!@interface MGAMapViewController : UIViewController !@property (weak, nonatomic) IBOutlet MKMapView *mapView; !@end

Page 29: Modernizes your objective C - Oliviero

@import

Page 30: Modernizes your objective C - Oliviero

@import‣ Modules provide an alternative, simpler way to use

software libraries that provides better compile-time scalability and eliminates many of the problems inherent to using the C preprocessor to access the API of a library

Page 31: Modernizes your objective C - Oliviero

@import‣ Modules provide an alternative, simpler way to use

software libraries that provides better compile-time scalability and eliminates many of the problems inherent to using the C preprocessor to access the API of a library

‣ Modules link frameworks automatically (no more need to link framework from Build Phases)

Page 32: Modernizes your objective C - Oliviero

@import‣ Modules provide an alternative, simpler way to use

software libraries that provides better compile-time scalability and eliminates many of the problems inherent to using the C preprocessor to access the API of a library

‣ Modules link frameworks automatically (no more need to link framework from Build Phases)

‣ At this time, modules are only available for Apple’s frameworks and have been implicitly disabled for C++

Page 33: Modernizes your objective C - Oliviero

use new type instancetypeinstancetype is a contextual keyword that can be used as a result type to signal that a method returns a related result type, you can use it as return type of an init method or

a (convenient)constructor

Page 34: Modernizes your objective C - Oliviero

instancetype@interface MGACustomer : NSObject !@property (nonatomic, readwrite, copy) NSString *name; + (id)customerWithName:(NSString *)name; !@end !@implementation MGACustomer !+ (id)customerWithName:(NSString *)name { id user = [[self alloc] init]; [user setName:name]; return user; } !@end !!!!!!!!

Page 35: Modernizes your objective C - Oliviero

instancetype@interface MGACustomer : NSObject !@property (nonatomic, readwrite, copy) NSString *name; + (id)customerWithName:(NSString *)name; !@end !@implementation MGACustomer !+ (id)customerWithName:(NSString *)name { id user = [[self alloc] init]; [user setName:name]; return user; } !@end !!!!!!!!

@interface MGACustomer : NSObject !@property (nonatomic, readwrite, copy) NSString *name; + (id)customerWithName:(NSString *)name; !@end !@implementation MGACustomer !+ (id)customerWithName:(NSString *)name { id user = [[self alloc] init]; [user setName:name]; return user; } !@end !.. !- (void)foo { // assign an object of type MGACustomer to a string variable // will not generate any error or warning at compile-time NSString *wrong = [MGACustomer customerWithName:@"test"]; }

Page 36: Modernizes your objective C - Oliviero

instancetype@interface MGACustomer : NSObject !@property (nonatomic, readwrite, copy) NSString *name; + (id)customerWithName:(NSString *)name; !@end !@implementation MGACustomer !+ (id)customerWithName:(NSString *)name { id user = [[self alloc] init]; [user setName:name]; return user; } !@end !!!!!!!!

@interface MGACustomer : NSObject !@property (nonatomic, readwrite, copy) NSString *name; + (id)customerWithName:(NSString *)name; !@end !@implementation MGACustomer !+ (id)customerWithName:(NSString *)name { id user = [[self alloc] init]; [user setName:name]; return user; } !@end !.. !- (void)foo { // assign an object of type MGACustomer to a string variable // will not generate any error or warning at compile-time NSString *wrong = [MGACustomer customerWithName:@"test"]; }

@interface MGACustomer : NSObject !@property (nonatomic, readwrite, copy) NSString *name; + (instancetype)customerWithName:(NSString *)name; !@end !@implementation MGACustomer !+ (instancetype)customerWithName:(NSString *)name { id user = [[self alloc] init]; [user setName:name]; return user; } !@end !.. !- (void)foo { // With ‘instancetype’ the compiler could infer type, it will generate: Incompatible // pointer types initializing 'NSString *' with an expression of type 'MGACustomer *' NSString *wrong = [MGACustomer customerWithName:@"test"]; }

Page 37: Modernizes your objective C - Oliviero

instancetype

Page 38: Modernizes your objective C - Oliviero

instancetype‣ With instancetype, the compiler will correctly infer

that the result of convenient constructor is an instance of a MGACustomer

Page 39: Modernizes your objective C - Oliviero

instancetype‣ With instancetype, the compiler will correctly infer

that the result of convenient constructor is an instance of a MGACustomer

‣ Instancetype, unlike id, can only be used as the result type in a method declaration

Page 40: Modernizes your objective C - Oliviero

instancetype‣ With instancetype, the compiler will correctly infer

that the result of convenient constructor is an instance of a MGACustomer

‣ Instancetype, unlike id, can only be used as the result type in a method declaration

‣ Init method should also use instancetype instead of id, instancetype is more explicit and therefore better than id

Page 41: Modernizes your objective C - Oliviero

use auto property synthesissynthesize not necessary for @property since Xcode 4.4

Page 42: Modernizes your objective C - Oliviero

auto property synthesis@interface MGACustomer : NSObject !@property (nonatomic, readwrite, copy) NSString *name; @property (nonatomic, readwrite, copy) NSString *address; !@end !!!!@implementation MGACustomer { NSString *_name; NSString *_address; } !@synthesize name = _name; @synthesize address = _address; !- (void)foo { _name = @"Apple Inc."; } !@end

Page 43: Modernizes your objective C - Oliviero

auto property synthesis@interface MGACustomer : NSObject !@property (nonatomic, readwrite, copy) NSString *name; @property (nonatomic, readwrite, copy) NSString *address; !@end !!!!@implementation MGACustomer { NSString *_name; NSString *_address; } !@synthesize name = _name; @synthesize address = _address; !- (void)foo { _name = @"Apple Inc."; } !@end

@interface MGACustomer : NSObject !@property (nonatomic, readwrite, copy) NSString *name; @property (nonatomic, readwrite, copy) NSString *address; !@end !!!!@implementation MGACustomer !!// compiler auto-synthesizes properties for you // and generate corresponding ivar(s) // with underscore as prefix !!!- (void)foo { _name = @"Apple Inc.”; // you can still access to ivar } !@end

Page 44: Modernizes your objective C - Oliviero

auto property synthesis

Page 45: Modernizes your objective C - Oliviero

auto property synthesis‣ Clang provides support for autosynthesis of declared

properties. Using this feature, clang provides default synthesis of those properties not declared @dynamic and not having user provided backing getter and setter methods.

Page 46: Modernizes your objective C - Oliviero

auto property synthesis‣ Clang provides support for autosynthesis of declared

properties. Using this feature, clang provides default synthesis of those properties not declared @dynamic and not having user provided backing getter and setter methods.

‣ Auto-synthesis is not support for properties defined in a protocol

Page 47: Modernizes your objective C - Oliviero

auto property synthesis‣ Clang provides support for autosynthesis of declared

properties. Using this feature, clang provides default synthesis of those properties not declared @dynamic and not having user provided backing getter and setter methods.

‣ Auto-synthesis is not support for properties defined in a protocol

‣ The compiler will add the ivar for you (with underscore prefix) when it adds the required accessor methods

Page 48: Modernizes your objective C - Oliviero

use copy for any immutable classfor attributes whose type is an immutable value class that conforms to the

NSCopying protocol (e.g.. NSDate, NSNumber, NSArray, NSSet), you almost always should specify copy in your @property declaration

Page 49: Modernizes your objective C - Oliviero

copy attribute

!!@interface MGACustomer : NSObject !@property (nonatomic, readwrite, strong) NSString *name; @property (nonatomic, readwrite, strong) NSString *address; @property (nonatomic, readwrite, strong) NSArray *orders; @property (nonatomic, readwrite, strong) NSDate *created; !@end !

Page 50: Modernizes your objective C - Oliviero

copy attribute

!!@interface MGACustomer : NSObject !@property (nonatomic, readwrite, strong) NSString *name; @property (nonatomic, readwrite, strong) NSString *address; @property (nonatomic, readwrite, strong) NSArray *orders; @property (nonatomic, readwrite, strong) NSDate *created; !@end !

!!@interface MGACustomer : NSObject !@property (nonatomic, readwrite, copy) NSString *name; @property (nonatomic, readwrite, copy) NSString *address; @property (nonatomic, readwrite, copy) NSArray *orders; @property (nonatomic, readwrite, copy) NSDate *created; !@end !

Page 51: Modernizes your objective C - Oliviero

copy attribute

Page 52: Modernizes your objective C - Oliviero

copy attribute‣ The reason of copy is that it is possible to have a

property that is declared as an immutable type (such as NSString) yet pass it a mutable type (such as NSMutableString). In which case it is possible to change the property from outside the class

Page 53: Modernizes your objective C - Oliviero

copy attribute‣ The reason of copy is that it is possible to have a

property that is declared as an immutable type (such as NSString) yet pass it a mutable type (such as NSMutableString). In which case it is possible to change the property from outside the class

‣ using copy is recommended, because it behaves sensibly with class clusters, sending copy to a mutable class returns an immutable copy of the object

Page 54: Modernizes your objective C - Oliviero

NS_ENUM & NS_OPTIONS macrothese macros are the new, preferred way to declare enum types.

Page 55: Modernizes your objective C - Oliviero

NS_ENUM

typedef enum MGAUserProfile : NSUInteger { MGAUserProfileAdmin, MGAUserProfileGuest, MGAUserProfileOperator } MGAUserProfile; !!!@interface MGACustomer : NSObject !@property (nonatomic, readwrite, assign) MGAUserProfile profile; !@end

Page 56: Modernizes your objective C - Oliviero

NS_ENUM

typedef enum MGAUserProfile : NSUInteger { MGAUserProfileAdmin, MGAUserProfileGuest, MGAUserProfileOperator } MGAUserProfile; !!!@interface MGACustomer : NSObject !@property (nonatomic, readwrite, assign) MGAUserProfile profile; !@end

typedef NS_ENUM(NSUInteger, MGAUserProfile) { MGAUserProfileAdmin, MGAUserProfileGuest, MGAUserProfileOperator }; !!!@interface MGACustomer : NSObject !@property (nonatomic, readwrite, assign) MGAUserProfile profile; !@end

Page 57: Modernizes your objective C - Oliviero

NS_OPTIONS

typedef enum MGAUserProfile : NSUInteger { MGAUserProfileAdmin = 1 << 0, MGAUserProfileGuest = 1 << 1, MGAUserProfileOperator = 1 << 2 } MGAUserProfile; !!!@interface MGACustomer : NSObject !@property (nonatomic, readwrite, assign) MGAUserProfile profile; !@end

Page 58: Modernizes your objective C - Oliviero

NS_OPTIONS

typedef enum MGAUserProfile : NSUInteger { MGAUserProfileAdmin = 1 << 0, MGAUserProfileGuest = 1 << 1, MGAUserProfileOperator = 1 << 2 } MGAUserProfile; !!!@interface MGACustomer : NSObject !@property (nonatomic, readwrite, assign) MGAUserProfile profile; !@end

typedef NS_OPTIONS(NSUInteger, MGAUserProfile) { MGAUserProfileAdmin = 1 << 0, MGAUserProfileGuest = 1 << 1, MGAUserProfileOperator = 1 << 2, }; !!!@interface MGACustomer : NSObject !@property (nonatomic, readwrite, assign) MGAUserProfile profile; !@end

Page 59: Modernizes your objective C - Oliviero

NS_ENUM & NS_OPTIONS

Page 60: Modernizes your objective C - Oliviero

NS_ENUM & NS_OPTIONS‣ The new macros combines the best of all ways to

declare an enum or an option, and even provide hints to the compiler for type-checking and switch statement completeness.

Page 61: Modernizes your objective C - Oliviero

NS_ENUM & NS_OPTIONS‣ The new macros combines the best of all ways to

declare an enum or an option, and even provide hints to the compiler for type-checking and switch statement completeness.

‣ If the compiler is operating in C++11 or Objective-C++11 mode, the macros behave slightly differently in order to make the code compatible with the mixed mode

Page 62: Modernizes your objective C - Oliviero

use extern const not #definethe best way to define a globally accessible constant is extern const

Page 63: Modernizes your objective C - Oliviero

extern const

Page 64: Modernizes your objective C - Oliviero

// Constants.h#define kMGAProjectConst @“myString"#define kMGASomeMagicValue 42

extern const

Page 65: Modernizes your objective C - Oliviero

// Constants.h#define kMGAProjectConst @“myString"#define kMGASomeMagicValue 42

extern const

// Constants.hextern NSString * const kMGAProjectConst;extern CGFloat const kMGASomeMagicValue;

// Constants.m#import “Constants.h"

NSString * const kMGAProjectConst = @“server.com”;CGFloat const kMGASomeMagicValue = 42.0f;

Page 66: Modernizes your objective C - Oliviero

// Constants.h#define kMGAProjectConst @“myString"#define kMGASomeMagicValue 42

extern const

// Constants.hextern NSString * const kMGAProjectConst;extern CGFloat const kMGASomeMagicValue;

// Constants.m#import “Constants.h"

NSString * const kMGAProjectConst = @“server.com”;CGFloat const kMGASomeMagicValue = 42.0f;

// Constants.h FOUNDATION_EXPORT NSString * const kMGAProjectConst; FOUNDATION_EXPORT CGFloat const kMGASomeMagicValue; !!!// Constants.m #import “Constants.h" !NSString * const kMGAProjectConst = @“server.com”; CGFloat const kMGASomeMagicValue = 42.0f;

Page 67: Modernizes your objective C - Oliviero

extern const

Page 68: Modernizes your objective C - Oliviero

extern const‣ It ensures that the compiler do a static type

checking and emit a warning if you try to use it somewhere where it isn't expecting

Page 69: Modernizes your objective C - Oliviero

extern const‣ It ensures that the compiler do a static type

checking and emit a warning if you try to use it somewhere where it isn't expecting

‣ One benefit is that changing the value of a constant does not cause a rebuild of your entire program.

Page 70: Modernizes your objective C - Oliviero

extern const‣ It ensures that the compiler do a static type

checking and emit a warning if you try to use it somewhere where it isn't expecting

‣ One benefit is that changing the value of a constant does not cause a rebuild of your entire program.

‣ Use FOUNDATION_EXPORT macro instead of extern if your code will be used in mixed C/C++ environments or on other platforms

Page 71: Modernizes your objective C - Oliviero

use Foundation Data Typesif you are unsure, the Foundation Data Types (like NSInterger or CGFloat) are the best

choice because they are architecture safe versions of the corresponding C types

Page 72: Modernizes your objective C - Oliviero

Foundation Data Types

Page 73: Modernizes your objective C - Oliviero

Foundation Data Types‣ The Fondation Data Types were introduced to make it

easier to write code that works on both 32-bit and 64-bit without modification

Page 74: Modernizes your objective C - Oliviero

Foundation Data Types‣ The Fondation Data Types were introduced to make it

easier to write code that works on both 32-bit and 64-bit without modification

‣ You usually want to use Foundation Data Types when you don't know what kind of processor architecture your code might run on

Page 75: Modernizes your objective C - Oliviero

Foundation Data Types‣ The Fondation Data Types were introduced to make it

easier to write code that works on both 32-bit and 64-bit without modification

‣ You usually want to use Foundation Data Types when you don't know what kind of processor architecture your code might run on

‣ However, if you need to take control on memory footprint you can use native types

Page 76: Modernizes your objective C - Oliviero

Use Class Extensions to Hide Private DataClass extensions are often used to extend the public interface with additional private

methods, properties or ivars for use within the implementation of the class itself

Page 77: Modernizes your objective C - Oliviero

// MGAMapViewController.h @interface MGAMapViewController : UIViewController !!!@end !// MGAMapViewController.m @interface MGAMapViewController () !!!!!!!!@end !@implementation MGAMapViewController !!!!!!!!!@end

Class Extensions

Page 78: Modernizes your objective C - Oliviero

// MGAMapViewController.h @interface MGAMapViewController : UIViewController !!!@end !// MGAMapViewController.m @interface MGAMapViewController () !!!!!!!!@end !@implementation MGAMapViewController !!!!!!!!!@end

// MGAMapViewController.h @interface MGAMapViewController : UIViewController !!!@end !// MGAMapViewController.m @interface MGAMapViewController () !!!!- (void)privateMethod; !!!@end !@implementation MGAMapViewController !!!!- (void)privateMethod { } !@end

Class Extensions

Page 79: Modernizes your objective C - Oliviero

// MGAMapViewController.h @interface MGAMapViewController : UIViewController !!!@end !// MGAMapViewController.m @interface MGAMapViewController () !!!!!!!!@end !@implementation MGAMapViewController !!!!!!!!!@end

// MGAMapViewController.h @interface MGAMapViewController : UIViewController !!!@end !// MGAMapViewController.m @interface MGAMapViewController () !!!!- (void)privateMethod; !!!@end !@implementation MGAMapViewController !!!!- (void)privateMethod { } !@end

// MGAMapViewController.h @interface MGAMapViewController : UIViewController !!!@end !// MGAMapViewController.m @interface MGAMapViewController () { NSString *privateString; } !- (void)privateMethod; !!!@end !@implementation MGAMapViewController !!!!- (void)privateMethod { privateString = @"hello"; } !@end

Class Extensions

Page 80: Modernizes your objective C - Oliviero

// MGAMapViewController.h @interface MGAMapViewController : UIViewController !!!@end !// MGAMapViewController.m @interface MGAMapViewController () !!!!!!!!@end !@implementation MGAMapViewController !!!!!!!!!@end

// MGAMapViewController.h @interface MGAMapViewController : UIViewController !!!@end !// MGAMapViewController.m @interface MGAMapViewController () !!!!- (void)privateMethod; !!!@end !@implementation MGAMapViewController !!!!- (void)privateMethod { } !@end

// MGAMapViewController.h @interface MGAMapViewController : UIViewController !!!@end !// MGAMapViewController.m @interface MGAMapViewController () { NSString *privateString; } !- (void)privateMethod; !!!@end !@implementation MGAMapViewController !!!!- (void)privateMethod { privateString = @"hello"; } !@end

Class Extensions// MGAMapViewController.h @interface MGAMapViewController : UIViewController !@property (nonatomic, readonly) NSArray *points; !@end !// MGAMapViewController.m @interface MGAMapViewController () { NSString *privateString; } !- (void)privateMethod; !

@property (nonatomic, strong, readwrite) NSArray *points; !@end !@implementation MGAMapViewController !!!!- (void)privateMethod { privateString = @"hello"; } !@end

Page 81: Modernizes your objective C - Oliviero

// MGAMapViewController.h @interface MGAMapViewController : UIViewController !!!@end !// MGAMapViewController.m @interface MGAMapViewController () !!!!!!!!@end !@implementation MGAMapViewController !!!!!!!!!@end

// MGAMapViewController.h @interface MGAMapViewController : UIViewController !!!@end !// MGAMapViewController.m @interface MGAMapViewController () !!!!- (void)privateMethod; !!!@end !@implementation MGAMapViewController !!!!- (void)privateMethod { } !@end

// MGAMapViewController.h @interface MGAMapViewController : UIViewController !!!@end !// MGAMapViewController.m @interface MGAMapViewController () { NSString *privateString; } !- (void)privateMethod; !!!@end !@implementation MGAMapViewController !!!!- (void)privateMethod { privateString = @"hello"; } !@end

Class Extensions// MGAMapViewController.h @interface MGAMapViewController : UIViewController !@property (nonatomic, readonly) NSArray *points; !@end !// MGAMapViewController.m @interface MGAMapViewController () { NSString *privateString; } !- (void)privateMethod; !

@property (nonatomic, strong, readwrite) NSArray *points; !@end !@implementation MGAMapViewController !!!!- (void)privateMethod { privateString = @"hello"; } !@end

// MGAMapViewController.h @interface MGAMapViewController : UIViewController !@property (nonatomic, readonly) NSArray *points; !@end !// MGAMapViewController.m @interface MGAMapViewController () { NSString *privateString; } !- (void)privateMethod; !

@property (nonatomic, strong, readwrite) NSArray *points; !@end !@implementation MGAMapViewController { NSInteger counter; } !- (void)privateMethod { privateString = @"hello"; } !@end

Page 82: Modernizes your objective C - Oliviero

Class Extensions

Page 83: Modernizes your objective C - Oliviero

Class Extensions‣ A class extension bears some similarity to a category,

but it can only be added to a class for which you have the source code at compile time. The methods declared by a class extension are implemented in the @implementation block for the original class

Page 84: Modernizes your objective C - Oliviero

Class Extensions‣ A class extension bears some similarity to a category,

but it can only be added to a class for which you have the source code at compile time. The methods declared by a class extension are implemented in the @implementation block for the original class

‣ By declaring the class extension inside the source code file for the class implementation, the information stays private to the class; the header files in theory should only expose public interface for your classes

Page 85: Modernizes your objective C - Oliviero

Class Extensions

Page 86: Modernizes your objective C - Oliviero

Class Extensions‣ It’s possible to use a class extension to add custom

instance variables. These are declared inside braces in the class extension interface

Page 87: Modernizes your objective C - Oliviero

Class Extensions‣ It’s possible to use a class extension to add custom

instance variables. These are declared inside braces in the class extension interface

‣ It’s also common, for example, to define a property as readonly in the interface, but as readwrite in a class extension declared above the implementation, in order that the internal methods of the class can change the property value directly

Page 88: Modernizes your objective C - Oliviero

Class Extensions‣ It’s possible to use a class extension to add custom

instance variables. These are declared inside braces in the class extension interface

‣ It’s also common, for example, to define a property as readonly in the interface, but as readwrite in a class extension declared above the implementation, in order that the internal methods of the class can change the property value directly

‣ It’s also possible to declare an ivar in the @implemetation block

Page 89: Modernizes your objective C - Oliviero

Conventions

Page 90: Modernizes your objective C - Oliviero

use prefixes on all classesclasses must be named uniquely in order to avoid name clashes

Page 91: Modernizes your objective C - Oliviero

use prefixes on all classes

@interface Customer : NSObject !@property (nonatomic, readwrite, copy) NSString *name; @property (nonatomic, readwrite, copy) NSString *address; !@end !!!!@interface HomeViewController : UIViewController !@property (weak, nonatomic) IBOutlet UILabel *userLabel; @property (weak, nonatomic) IBOutlet UILabel *logoLabel; @property (strong, nonatomic) Customer *user; !@end

Page 92: Modernizes your objective C - Oliviero

use prefixes on all classes

@interface Customer : NSObject !@property (nonatomic, readwrite, copy) NSString *name; @property (nonatomic, readwrite, copy) NSString *address; !@end !!!!@interface HomeViewController : UIViewController !@property (weak, nonatomic) IBOutlet UILabel *userLabel; @property (weak, nonatomic) IBOutlet UILabel *logoLabel; @property (strong, nonatomic) Customer *user; !@end

@interface MGACustomer : NSObject !@property (nonatomic, readwrite, copy) NSString *name; @property (nonatomic, readwrite, copy) NSString *address; !@end !!!!@interface MGAHomeViewController : UIViewController !@property (weak, nonatomic) IBOutlet UILabel *userLabel; @property (weak, nonatomic) IBOutlet UILabel *logoLabel; @property (strong, nonatomic) MAGCustomer *user; !@end

Page 93: Modernizes your objective C - Oliviero

use prefixes on all classes

Page 94: Modernizes your objective C - Oliviero

use prefixes on all classes‣ Choose a prefix with at least 3 uppercase chars that are

significant for the project

Page 95: Modernizes your objective C - Oliviero

use prefixes on all classes‣ Choose a prefix with at least 3 uppercase chars that are

significant for the project

‣ Two-letter prefixes are reserved by Apple for use in framework classes, so you must use 3 (or more)

Page 96: Modernizes your objective C - Oliviero

use prefixes on all classes‣ Choose a prefix with at least 3 uppercase chars that are

significant for the project

‣ Two-letter prefixes are reserved by Apple for use in framework classes, so you must use 3 (or more)

‣ Objective-C classes must be named uniquely not only within the code that you’re writing in a project, but also across any frameworks or bundles you might be including. As an example, you should avoid using generic class names like ViewController or TextParser because it’s possible a framework you include in your app may fail to follow conventions and create classes with the same names.

Page 97: Modernizes your objective C - Oliviero

use a prefix for method names in categories in a category you should include a prefix on the method name to avoid clashes

Page 98: Modernizes your objective C - Oliviero

prefix category methods

!@interface NSString (MGAAdditions) !- (NSString *)reverse; - (NSString *)sha256; !@end

Page 99: Modernizes your objective C - Oliviero

prefix category methods

!@interface NSString (MGAAdditions) !- (NSString *)reverse; - (NSString *)sha256; !@end

!@interface NSString (MGAAdditions) !- (NSString *)mga_reverse; - (NSString *)mga_sha256; !@end

Page 100: Modernizes your objective C - Oliviero

prefix category methods

Page 101: Modernizes your objective C - Oliviero

prefix category methods‣ If the name of a method declared in a category is the same as a

method in the original class, or a method in another category on the same class (or even a superclass), the behavior is undefined as to which method implementation is used at runtime.

Page 102: Modernizes your objective C - Oliviero

prefix category methods‣ If the name of a method declared in a category is the same as a

method in the original class, or a method in another category on the same class (or even a superclass), the behavior is undefined as to which method implementation is used at runtime.

‣ In order to avoid undefined behavior, it’s best practice to add a prefix to method names in categories on framework classes, just like you should add a prefix to the names of your own classes. You might choose to use the same three letters you use for your class prefixes, but lowercase to follow the usual convention for method names, then an underscore, before the rest of the method name

Page 103: Modernizes your objective C - Oliviero

properly define BOOL propertyfor Boolean properties the getter method should start with is

Page 104: Modernizes your objective C - Oliviero

properly define BOOL property

!@interface MGAUser !@property (nonatomic, assign) BOOL authenticated; !@end

!@interface MGAUser !@property (nonatomic, assign, getter = isAuthenticated) BOOL authenticated; !@end

Page 105: Modernizes your objective C - Oliviero

use ~iphone and ~ipadif you’re developing a universal app add tilde to xib name instead of underscore

!!

Page 106: Modernizes your objective C - Oliviero

~iphone and ~ipad

// MGAHomeViewController_iPhone.xib // MGAHomeViewController_iPad.xib !@implementation MGAHomeViewController !- (id)init { NSString *nibName = @"MGAHomeViewController_iPhone"; if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { nibName = @"MGAHomeViewController_iPad"; } return [super initWithNibName:nibName bundle:nil]; } !@end

Page 107: Modernizes your objective C - Oliviero

~iphone and ~ipad

// MGAHomeViewController_iPhone.xib // MGAHomeViewController_iPad.xib !@implementation MGAHomeViewController !- (id)init { NSString *nibName = @"MGAHomeViewController_iPhone"; if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { nibName = @"MGAHomeViewController_iPad"; } return [super initWithNibName:nibName bundle:nil]; } !@end

please stop doing that!

Page 108: Modernizes your objective C - Oliviero

~iphone and ~ipad

// MGAHomeViewController_iPhone.xib // MGAHomeViewController_iPad.xib !@implementation MGAHomeViewController !- (id)init { NSString *nibName = @"MGAHomeViewController_iPhone"; if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { nibName = @"MGAHomeViewController_iPad"; } return [super initWithNibName:nibName bundle:nil]; } !@end

// MGAHomeViewController~iphone.xib // MGAHomeViewController~ipad.xib !@implementation MGAHomeViewController !!!!!// no custom init required !!!!!!!@end

Page 109: Modernizes your objective C - Oliviero

use ~iphone and ~ipad

Page 110: Modernizes your objective C - Oliviero

use ~iphone and ~ipad‣ Adding ~iphone and ~ipad to xib file name, the

runtime will automatically infer the correct xib to load (e.g. MGAHomeViewController~iphone.xib and MGAHomeViewController~ipad.xib)

Page 111: Modernizes your objective C - Oliviero

use ~iphone and ~ipad‣ Adding ~iphone and ~ipad to xib file name, the

runtime will automatically infer the correct xib to load (e.g. MGAHomeViewController~iphone.xib and MGAHomeViewController~ipad.xib)

‣ note, it’s case sensitive so iPhone and iPad, with a capital P, do not work

Page 112: Modernizes your objective C - Oliviero

organize #import statementsit’s a good practice grouping and commenting #import statements

Page 113: Modernizes your objective C - Oliviero

organize #import statements!#import <CoreData/CoreData.h> !#import "MGAMapViewController.h" #import “MGAPictureView.h" #import “NSString+MGAAdditions.h” !#import “MGAUser.h" !#import <CoreLocation/CoreLocation.h> #import “NSDate+MGAAdditions.h” !#import “MGAOrderCell.h" #import “MGACustomer.h" #import "UIImage+MGAAdditions.h" !#import “MGAHomeViewController.h" #import <UIKit/UIKit.h> !#import “MGAUserCell.h"

Page 114: Modernizes your objective C - Oliviero

organize #import statements!#import <CoreData/CoreData.h> !#import "MGAMapViewController.h" #import “MGAPictureView.h" #import “NSString+MGAAdditions.h” !#import “MGAUser.h" !#import <CoreLocation/CoreLocation.h> #import “NSDate+MGAAdditions.h” !#import “MGAOrderCell.h" #import “MGACustomer.h" #import "UIImage+MGAAdditions.h" !#import “MGAHomeViewController.h" #import <UIKit/UIKit.h> !#import “MGAUserCell.h"

!// Frameworks #import <UIKit/UIKit.h> #import <CoreData/CoreData.h> #import <CoreLocation/CoreLocation.h> !// View Controllers #import "MGAMapViewController.h" #import “MGAHomeViewController.h” !// Views #import “MGAPictureView.h” !// Cells #import “MGAUserCell.h” #import “MGAOrderCell.h” !// Models #import “MGAUser.h" #import “MGACustomer.h” !// Categories #import “NSDate+MGAAdditions.h” #import “UIImage+MGAAdditions.h" #import “NSString+MGAAdditions.h”

Page 115: Modernizes your objective C - Oliviero

organize #import statements

Page 116: Modernizes your objective C - Oliviero

organize #import statements

‣ group #imports

Page 117: Modernizes your objective C - Oliviero

organize #import statements

‣ group #imports

‣ comment the groups

Page 118: Modernizes your objective C - Oliviero

organize #import statements

‣ group #imports

‣ comment the groups

‣ If your are pedantic you can sort #import by length :)

Page 119: Modernizes your objective C - Oliviero

use #pragma markorganize your code, visually

Page 120: Modernizes your objective C - Oliviero

#pragma mark#pragma mark - View !- (void)viewDidLoad { [super viewDidLoad]; … } !- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; … } !#pragma mark - UIScrollViewDelegate !- (void)scrollViewDidScroll:(UIScrollView *)scrollView { … } !- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { … } !#pragma mark - Actions !- (IBAction)loginButtonTouched:(id)sender { }

Page 121: Modernizes your objective C - Oliviero

#pragma mark

Page 122: Modernizes your objective C - Oliviero

#pragma mark

Page 123: Modernizes your objective C - Oliviero

#pragma mark‣ Use #pragma mark in your @implementation to divide

code into logical sections

Page 124: Modernizes your objective C - Oliviero

#pragma mark‣ Use #pragma mark in your @implementation to divide

code into logical sections

‣ It is also a way to organize your methods in the method list pop up view in Xcode

Page 125: Modernizes your objective C - Oliviero

Coding

Page 126: Modernizes your objective C - Oliviero

don’t #import in header file most #import statements should only be written in .m files, not .h headers

Page 127: Modernizes your objective C - Oliviero

don’t #import in header file #import "MGAUser.h" #import "MGANetworkManager.h" !@interface MGALoginViewController : UIViewController !@property (nonatomic, readonly) MGAUser *user; @property (nonatomic, strong, readwrite) MGANetworkManager *network; !@end !!!!// MGALoginViewController.m !@implementation MGALoginViewController !!@end

Page 128: Modernizes your objective C - Oliviero

don’t #import in header file #import "MGAUser.h" #import "MGANetworkManager.h" !@interface MGALoginViewController : UIViewController !@property (nonatomic, readonly) MGAUser *user; @property (nonatomic, strong, readwrite) MGANetworkManager *network; !@end !!!!// MGALoginViewController.m !@implementation MGALoginViewController !!@end

@class MGAUser; // forward class declaration @class MGANetworkManager; // forward class declaration !@interface MGALoginViewController : UIViewController !@property (nonatomic, readonly) MGAUser *user; @property (nonatomic, strong, readwrite) MGANetworkManager *network; !@end !!!!// MGALoginViewController.m !#import "MGAUser.h" #import “MGANetworkManager.h" !@implementation MGALoginViewController !!@end

Page 129: Modernizes your objective C - Oliviero

don’t #import in header file

Page 130: Modernizes your objective C - Oliviero

don’t #import in header file ‣ Rather than adding #import statements for each class,

it's good practice to use forward class declarations in the header, and import them in the implementation

Page 131: Modernizes your objective C - Oliviero

don’t #import in header file ‣ Rather than adding #import statements for each class,

it's good practice to use forward class declarations in the header, and import them in the implementation

‣ It reduce compile times and cyclical references

Page 132: Modernizes your objective C - Oliviero

don’t #import in header file ‣ Rather than adding #import statements for each class,

it's good practice to use forward class declarations in the header, and import them in the implementation

‣ It reduce compile times and cyclical references

‣ The one real exception is when subclassing another custom class, you'll need to #import its header.

Page 133: Modernizes your objective C - Oliviero

use typedef to simplify Block syntaxIf you need to define more than one block with the same signature, you might like to

define your own type for that signature

Page 134: Modernizes your objective C - Oliviero

blocks with typedef

Page 135: Modernizes your objective C - Oliviero

blocks with typedef

!!!@interface MGACustomer !!!- (void)createOrder:(void(^)(MGAOrder *order))completion; !@end

Page 136: Modernizes your objective C - Oliviero

blocks with typedef

!!!@interface MGACustomer !!!- (void)createOrder:(void(^)(MGAOrder *order))completion; !@end

typedef void(^MGACustomerBlock)(MGAOrder *order); !!@interface MGACustomer !!!- (void)createOrder:(void(^)(MGAOrder *order))completion; !@end

Page 137: Modernizes your objective C - Oliviero

blocks with typedef

!!!@interface MGACustomer !!!- (void)createOrder:(void(^)(MGAOrder *order))completion; !@end

typedef void(^MGACustomerBlock)(MGAOrder *order); !!@interface MGACustomer !!!- (void)createOrder:(void(^)(MGAOrder *order))completion; !@end

typedef void(^MGACustomerBlock)(MGAOrder *order); !!@interface MGACustomer !!!- (void)createOrder:(MGACustomerBlock)completion; !@end

Page 138: Modernizes your objective C - Oliviero

blocks with typedef

!!!@interface MGACustomer !!!- (void)createOrder:(void(^)(MGAOrder *order))completion; !@end

typedef void(^MGACustomerBlock)(MGAOrder *order); !!@interface MGACustomer !!!- (void)createOrder:(void(^)(MGAOrder *order))completion; !@end

typedef void(^MGACustomerBlock)(MGAOrder *order); !!@interface MGACustomer !!!- (void)createOrder:(MGACustomerBlock)completion; !@end

typedef void(^MGACustomerBlock)(MGAOrder *order); !!@interface MGACustomer !@property (nonatomic, copy) MGACustomerBlock completionBlock; !- (void)createOrder:(MGACustomerBlock)completion; !@end

Page 139: Modernizes your objective C - Oliviero

create types for blocks

Page 140: Modernizes your objective C - Oliviero

create types for blocks‣ types improve readability and clean up your method

definitions, life will be easier and It’s highly recommend making use of them as much as possible

Page 141: Modernizes your objective C - Oliviero

create types for blocks‣ types improve readability and clean up your method

definitions, life will be easier and It’s highly recommend making use of them as much as possible

‣ If you have to change the block signature, it is much easier to change the typedef. The compiler, being a nice fellow, will then tell you all the places the block signature doesn’t match

Page 142: Modernizes your objective C - Oliviero

how to access ivarsOh my!

Page 143: Modernizes your objective C - Oliviero

how to access ivars!- (instancetype)initWithUser:(MGAUser *)user { self = [super init]; if (self) { _user = user; } return self; } !- (void)viewDidLoad { [super viewDidLoad]; [self.usernameLabel setText:self.user.name]; } !- (void)createNewUser { self.usernameLabel = [THMUser alloc] init]; }

Page 144: Modernizes your objective C - Oliviero

how to access ivars

Page 145: Modernizes your objective C - Oliviero

how to access ivars‣ Direct access bypasses the property’s memory-

management semantics defined by the setter

Page 146: Modernizes your objective C - Oliviero

how to access ivars‣ Direct access bypasses the property’s memory-

management semantics defined by the setter

‣ KVO notifications would not be fired when accessing the instance variables directly

Page 147: Modernizes your objective C - Oliviero

how to access ivars‣ Direct access bypasses the property’s memory-

management semantics defined by the setter

‣ KVO notifications would not be fired when accessing the instance variables directly

‣ In init methods you should use direct instance variable access, because subclasses could override the setter

Page 148: Modernizes your objective C - Oliviero

how to access ivars‣ Direct access bypasses the property’s memory-

management semantics defined by the setter

‣ KVO notifications would not be fired when accessing the instance variables directly

‣ In init methods you should use direct instance variable access, because subclasses could override the setter

‣ On the other part of class read/write data through properties

Page 149: Modernizes your objective C - Oliviero

always declare atomic/nonatomicProperties are declared as atomic by default

Page 150: Modernizes your objective C - Oliviero

declare atomic/nonatomic#import <UIKit/UIKit.h> !@interface MGAMapViewController : UIViewController !@property (readonly) CERUser *user; @property (copy) NSArray *locations; @property (weak) IBOutlet UITableView *tableView; !@end

Page 151: Modernizes your objective C - Oliviero

declare atomic/nonatomic#import <UIKit/UIKit.h> !@interface MGAMapViewController : UIViewController !@property (readonly) CERUser *user; @property (copy) NSArray *locations; @property (weak) IBOutlet UITableView *tableView; !@end

#import <UIKit/UIKit.h> !@interface MGAMapViewController : UIViewController !@property (nonatomic, readonly) CERUser *user; @property (nonatomic, copy) NSArray *locations; @property (nonatomic, weak) IBOutlet UITableView *tableView; !@end

Page 152: Modernizes your objective C - Oliviero

declare atomic/nonatomic#import <UIKit/UIKit.h> !@interface MGAMapViewController : UIViewController !@property (readonly) CERUser *user; @property (copy) NSArray *locations; @property (weak) IBOutlet UITableView *tableView; !@end

#import <UIKit/UIKit.h> !@interface MGAMapViewController : UIViewController !@property (nonatomic, readonly) CERUser *user; @property (nonatomic, copy) NSArray *locations; @property (nonatomic, weak) IBOutlet UITableView *tableView; !@end

#import <UIKit/UIKit.h> !@interface MGAMapViewController : UIViewController !@property (nonatomic, readonly) CERUser *user; @property (nonatomic, readwrite, copy) NSArray *locations; @property (nonatomic, readwrite, weak) IBOutlet UITableView *tableView; !@end

Page 153: Modernizes your objective C - Oliviero

declare atomic/nonatomic

Page 154: Modernizes your objective C - Oliviero

declare atomic/nonatomic‣ By default, synthesized accessors include locking to

make them atomic

Page 155: Modernizes your objective C - Oliviero

declare atomic/nonatomic‣ By default, synthesized accessors include locking to

make them atomic

‣ If you not need locking on property use nonatomic on iOS, since performance is severely impacted if atomic is used

Page 156: Modernizes your objective C - Oliviero

use read-only propertiesread-only properties are great for exposing information, you should use them often

Page 157: Modernizes your objective C - Oliviero

read-only properties!@interface MGAMapViewController : UIViewController !@property (nonatomic, readonly) MGAUser *user; @property (nonatomic, readonly) NSArray *locations; !@end

Page 158: Modernizes your objective C - Oliviero

read-only properties!@interface MGAMapViewController : UIViewController !@property (nonatomic, readonly) MGAUser *user; @property (nonatomic, readonly) NSArray *locations; !@end

!@interface MGAMapViewController : UIViewController !@property (nonatomic, readonly) MGAUser *user; @property (nonatomic, readonly) NSArray *locations; !@end !!!!!!!!!!@implementation MGAMapViewController !- (instancetype)initWithUser:(MGaUser *)user { self = [super init]; if (self) { _user = user; } return self; } !@end

Page 159: Modernizes your objective C - Oliviero

read-only properties!@interface MGAMapViewController : UIViewController !@property (nonatomic, readonly) MGAUser *user; @property (nonatomic, readonly) NSArray *locations; !@end

!@interface MGAMapViewController : UIViewController !@property (nonatomic, readonly) MGAUser *user; @property (nonatomic, readonly) NSArray *locations; !@end !!!!!!!!!!@implementation MGAMapViewController !- (instancetype)initWithUser:(MGaUser *)user { self = [super init]; if (self) { _user = user; } return self; } !@end

!@interface MGAMapViewController : UIViewController !@property (nonatomic, readonly) MGAUser *user; @property (nonatomic, readonly) NSArray *locations; !@end !!@interface MGAMapViewController () !@property (nonatomic, strong, readwrite) MGAUser *user; @property (nonatomic, strong, readwrite) NSArray *locations; !@end !!@implementation MGAMapViewController !- (instancetype)initWithUser:(MGAUser *)user { self = [super init]; if (self) { _user = user; } return self; } !@end

Page 160: Modernizes your objective C - Oliviero

use read-only properties

Page 161: Modernizes your objective C - Oliviero

use read-only properties‣ expose object data with read-only properties, unless

you really need to allow access to internal data through a public setter

Page 162: Modernizes your objective C - Oliviero

use read-only properties‣ expose object data with read-only properties, unless

you really need to allow access to internal data through a public setter

‣ for read-only properties, you should defined a public getter but a private setter in class extension

Page 163: Modernizes your objective C - Oliviero

use weak to avoid retain cyclesa wrong memory management involves in memory leaks

Page 164: Modernizes your objective C - Oliviero

retain cycle

Page 165: Modernizes your objective C - Oliviero

retain cycle

Object BObject A

Page 166: Modernizes your objective C - Oliviero

retain cycle

Object B

@property (strong)

Object A

Page 167: Modernizes your objective C - Oliviero

retain cycle

Object B

@property (strong)

@property (strong)

Object A

Page 168: Modernizes your objective C - Oliviero

retain cycle

Object B

@property (strong)

@property (strong)

Object A

Page 169: Modernizes your objective C - Oliviero

retain cycle

Object B

@property (strong)

@property (strong)

Object A

Page 170: Modernizes your objective C - Oliviero

retain cycle

Object B

@property (strong)

Object A

@property (weak)

Page 171: Modernizes your objective C - Oliviero

use __weak typeofa wrong memory management involves in memory leaks

Page 172: Modernizes your objective C - Oliviero

use __weak typeof

Page 173: Modernizes your objective C - Oliviero

use __weak typeof- (void)viewDidLoad { [super viewDidLoad]; self.manager = [[MGANetworkManager alloc] init]; !!! [self.manager getUsers:^(NSArray *users, NSError *error) { if (!error) { self.users = elements; [self.usersTableView reloadData]; } }]; }

Page 174: Modernizes your objective C - Oliviero

use __weak typeof- (void)viewDidLoad { [super viewDidLoad]; self.manager = [[MGANetworkManager alloc] init]; !!! [self.manager getUsers:^(NSArray *users, NSError *error) { if (!error) { self.users = elements; [self.usersTableView reloadData]; } }]; }

Page 175: Modernizes your objective C - Oliviero

use __weak typeof- (void)viewDidLoad { [super viewDidLoad]; self.manager = [[MGANetworkManager alloc] init]; !!! [self.manager getUsers:^(NSArray *users, NSError *error) { if (!error) { self.users = elements; [self.usersTableView reloadData]; } }]; }

Page 176: Modernizes your objective C - Oliviero

use __weak typeof- (void)viewDidLoad { [super viewDidLoad]; self.manager = [[MGANetworkManager alloc] init]; !!! [self.manager getUsers:^(NSArray *users, NSError *error) { if (!error) { self.users = elements; [self.usersTableView reloadData]; } }]; }

- (void)viewDidLoad { [super viewDidLoad]; self.manager = [[MGANetworkManager alloc] init]; ! __weak THMReportsViewController weakSelf = self; ! [weakSelf.manager getUsers:^(NSArray *users, NSError *error) { if (!error) { weakSelf.users = elements; [weakSelf.usersTableView reloadData]; } }]; }

Page 177: Modernizes your objective C - Oliviero

use __weak typeof- (void)viewDidLoad { [super viewDidLoad]; self.manager = [[MGANetworkManager alloc] init]; !!! [self.manager getUsers:^(NSArray *users, NSError *error) { if (!error) { self.users = elements; [self.usersTableView reloadData]; } }]; }

- (void)viewDidLoad { [super viewDidLoad]; self.manager = [[MGANetworkManager alloc] init]; ! __weak THMReportsViewController weakSelf = self; ! [weakSelf.manager getUsers:^(NSArray *users, NSError *error) { if (!error) { weakSelf.users = elements; [weakSelf.usersTableView reloadData]; } }]; }

- (void)viewDidLoad { [super viewDidLoad]; self.manager = [[MGANetworkManager alloc] init]; ! __weak typeof(self) weakSelf = self; ! [weakSelf.manager getUsers:^(NSArray *users, NSError *error) { if (!error) { weakSelf.users = elements; [weakSelf.usersTableView reloadData]; } }]; }

Page 178: Modernizes your objective C - Oliviero

Manage third-part libraries with CocoaPodsit’s an application level dependency manager for the Objective-C projects

Page 179: Modernizes your objective C - Oliviero

Cocoapods

Page 180: Modernizes your objective C - Oliviero

Cocoapods$ sudo gem install cocoapods

$ cd MyGreatApp

$ pod init

$ edit Podfile

Page 181: Modernizes your objective C - Oliviero

Cocoapods$ sudo gem install cocoapods

$ cd MyGreatApp

$ pod init

$ edit Podfile

platform :ios, '6.1'

pod 'RestKit', '~> 0.22.0'pod 'FXKeychain', '~> 1.5'pod 'SDWebImage', '~> 3.5.2'pod 'SDWebImage-ProgressView', '~> 0.3.0'pod 'RHAddressBook', '~> 1.1.1'pod 'FormatterKit', '~> 1.4.2'

Page 182: Modernizes your objective C - Oliviero

Cocoapods$ sudo gem install cocoapods

$ cd MyGreatApp

$ pod init

$ edit Podfile

platform :ios, '6.1'

pod 'RestKit', '~> 0.22.0'pod 'FXKeychain', '~> 1.5'pod 'SDWebImage', '~> 3.5.2'pod 'SDWebImage-ProgressView', '~> 0.3.0'pod 'RHAddressBook', '~> 1.1.1'pod 'FormatterKit', '~> 1.4.2'

$ pod install

Page 183: Modernizes your objective C - Oliviero

Cocoapods$ sudo gem install cocoapods

$ cd MyGreatApp

$ pod init

$ edit Podfile

platform :ios, '6.1'

pod 'RestKit', '~> 0.22.0'pod 'FXKeychain', '~> 1.5'pod 'SDWebImage', '~> 3.5.2'pod 'SDWebImage-ProgressView', '~> 0.3.0'pod 'RHAddressBook', '~> 1.1.1'pod 'FormatterKit', '~> 1.4.2'

$ pod install

Page 184: Modernizes your objective C - Oliviero

Cocoapods$ sudo gem install cocoapods

$ cd MyGreatApp

$ pod init

$ edit Podfile

platform :ios, '6.1'

pod 'RestKit', '~> 0.22.0'pod 'FXKeychain', '~> 1.5'pod 'SDWebImage', '~> 3.5.2'pod 'SDWebImage-ProgressView', '~> 0.3.0'pod 'RHAddressBook', '~> 1.1.1'pod 'FormatterKit', '~> 1.4.2'

$ pod install

Page 185: Modernizes your objective C - Oliviero

Cocoapods$ sudo gem install cocoapods

$ cd MyGreatApp

$ pod init

$ edit Podfile

platform :ios, '6.1'

pod 'RestKit', '~> 0.22.0'pod 'FXKeychain', '~> 1.5'pod 'SDWebImage', '~> 3.5.2'pod 'SDWebImage-ProgressView', '~> 0.3.0'pod 'RHAddressBook', '~> 1.1.1'pod 'FormatterKit', '~> 1.4.2'

$ pod install

Analyzing dependencies

Page 186: Modernizes your objective C - Oliviero

Cocoapods$ sudo gem install cocoapods

$ cd MyGreatApp

$ pod init

$ edit Podfile

platform :ios, '6.1'

pod 'RestKit', '~> 0.22.0'pod 'FXKeychain', '~> 1.5'pod 'SDWebImage', '~> 3.5.2'pod 'SDWebImage-ProgressView', '~> 0.3.0'pod 'RHAddressBook', '~> 1.1.1'pod 'FormatterKit', '~> 1.4.2'

$ pod install

Analyzing dependencies

Page 187: Modernizes your objective C - Oliviero

Cocoapods$ sudo gem install cocoapods

$ cd MyGreatApp

$ pod init

$ edit Podfile

platform :ios, '6.1'

pod 'RestKit', '~> 0.22.0'pod 'FXKeychain', '~> 1.5'pod 'SDWebImage', '~> 3.5.2'pod 'SDWebImage-ProgressView', '~> 0.3.0'pod 'RHAddressBook', '~> 1.1.1'pod 'FormatterKit', '~> 1.4.2'

$ pod install

Analyzing dependencies

Downloading dependencies

Page 188: Modernizes your objective C - Oliviero

Cocoapods$ sudo gem install cocoapods

$ cd MyGreatApp

$ pod init

$ edit Podfile

platform :ios, '6.1'

pod 'RestKit', '~> 0.22.0'pod 'FXKeychain', '~> 1.5'pod 'SDWebImage', '~> 3.5.2'pod 'SDWebImage-ProgressView', '~> 0.3.0'pod 'RHAddressBook', '~> 1.1.1'pod 'FormatterKit', '~> 1.4.2'

$ pod install

Analyzing dependencies

Downloading dependenciesUsing AFNetworking (1.3.3)

Page 189: Modernizes your objective C - Oliviero

Cocoapods$ sudo gem install cocoapods

$ cd MyGreatApp

$ pod init

$ edit Podfile

platform :ios, '6.1'

pod 'RestKit', '~> 0.22.0'pod 'FXKeychain', '~> 1.5'pod 'SDWebImage', '~> 3.5.2'pod 'SDWebImage-ProgressView', '~> 0.3.0'pod 'RHAddressBook', '~> 1.1.1'pod 'FormatterKit', '~> 1.4.2'

$ pod install

Analyzing dependencies

Downloading dependenciesUsing AFNetworking (1.3.3)Using FXKeychain (1.5)

Page 190: Modernizes your objective C - Oliviero

Cocoapods$ sudo gem install cocoapods

$ cd MyGreatApp

$ pod init

$ edit Podfile

platform :ios, '6.1'

pod 'RestKit', '~> 0.22.0'pod 'FXKeychain', '~> 1.5'pod 'SDWebImage', '~> 3.5.2'pod 'SDWebImage-ProgressView', '~> 0.3.0'pod 'RHAddressBook', '~> 1.1.1'pod 'FormatterKit', '~> 1.4.2'

$ pod install

Analyzing dependencies

Downloading dependenciesUsing AFNetworking (1.3.3)Using FXKeychain (1.5)Using FormatterKit (1.4.2)

Page 191: Modernizes your objective C - Oliviero

Cocoapods$ sudo gem install cocoapods

$ cd MyGreatApp

$ pod init

$ edit Podfile

platform :ios, '6.1'

pod 'RestKit', '~> 0.22.0'pod 'FXKeychain', '~> 1.5'pod 'SDWebImage', '~> 3.5.2'pod 'SDWebImage-ProgressView', '~> 0.3.0'pod 'RHAddressBook', '~> 1.1.1'pod 'FormatterKit', '~> 1.4.2'

$ pod install

Analyzing dependencies

Downloading dependenciesUsing AFNetworking (1.3.3)Using FXKeychain (1.5)Using FormatterKit (1.4.2)Using ISO8601DateFormatterValueTransformer (0.5.0)

Page 192: Modernizes your objective C - Oliviero

Cocoapods$ sudo gem install cocoapods

$ cd MyGreatApp

$ pod init

$ edit Podfile

platform :ios, '6.1'

pod 'RestKit', '~> 0.22.0'pod 'FXKeychain', '~> 1.5'pod 'SDWebImage', '~> 3.5.2'pod 'SDWebImage-ProgressView', '~> 0.3.0'pod 'RHAddressBook', '~> 1.1.1'pod 'FormatterKit', '~> 1.4.2'

$ pod install

Analyzing dependencies

Downloading dependenciesUsing AFNetworking (1.3.3)Using FXKeychain (1.5)Using FormatterKit (1.4.2)Using ISO8601DateFormatterValueTransformer (0.5.0)Using RHAddressBook (1.1.1)

Page 193: Modernizes your objective C - Oliviero

Cocoapods$ sudo gem install cocoapods

$ cd MyGreatApp

$ pod init

$ edit Podfile

platform :ios, '6.1'

pod 'RestKit', '~> 0.22.0'pod 'FXKeychain', '~> 1.5'pod 'SDWebImage', '~> 3.5.2'pod 'SDWebImage-ProgressView', '~> 0.3.0'pod 'RHAddressBook', '~> 1.1.1'pod 'FormatterKit', '~> 1.4.2'

$ pod install

Analyzing dependencies

Downloading dependenciesUsing AFNetworking (1.3.3)Using FXKeychain (1.5)Using FormatterKit (1.4.2)Using ISO8601DateFormatterValueTransformer (0.5.0)Using RHAddressBook (1.1.1)Using RKValueTransformers (1.0.1)

Page 194: Modernizes your objective C - Oliviero

Cocoapods$ sudo gem install cocoapods

$ cd MyGreatApp

$ pod init

$ edit Podfile

platform :ios, '6.1'

pod 'RestKit', '~> 0.22.0'pod 'FXKeychain', '~> 1.5'pod 'SDWebImage', '~> 3.5.2'pod 'SDWebImage-ProgressView', '~> 0.3.0'pod 'RHAddressBook', '~> 1.1.1'pod 'FormatterKit', '~> 1.4.2'

$ pod install

Analyzing dependencies

Downloading dependenciesUsing AFNetworking (1.3.3)Using FXKeychain (1.5)Using FormatterKit (1.4.2)Using ISO8601DateFormatterValueTransformer (0.5.0)Using RHAddressBook (1.1.1)Using RKValueTransformers (1.0.1)Using RestKit (0.22.0)

Page 195: Modernizes your objective C - Oliviero

Cocoapods$ sudo gem install cocoapods

$ cd MyGreatApp

$ pod init

$ edit Podfile

platform :ios, '6.1'

pod 'RestKit', '~> 0.22.0'pod 'FXKeychain', '~> 1.5'pod 'SDWebImage', '~> 3.5.2'pod 'SDWebImage-ProgressView', '~> 0.3.0'pod 'RHAddressBook', '~> 1.1.1'pod 'FormatterKit', '~> 1.4.2'

$ pod install

Analyzing dependencies

Downloading dependenciesUsing AFNetworking (1.3.3)Using FXKeychain (1.5)Using FormatterKit (1.4.2)Using ISO8601DateFormatterValueTransformer (0.5.0)Using RHAddressBook (1.1.1)Using RKValueTransformers (1.0.1)Using RestKit (0.22.0)Using SDWebImage (3.5.4)

Page 196: Modernizes your objective C - Oliviero

Cocoapods$ sudo gem install cocoapods

$ cd MyGreatApp

$ pod init

$ edit Podfile

platform :ios, '6.1'

pod 'RestKit', '~> 0.22.0'pod 'FXKeychain', '~> 1.5'pod 'SDWebImage', '~> 3.5.2'pod 'SDWebImage-ProgressView', '~> 0.3.0'pod 'RHAddressBook', '~> 1.1.1'pod 'FormatterKit', '~> 1.4.2'

$ pod install

Analyzing dependencies

Downloading dependenciesUsing AFNetworking (1.3.3)Using FXKeychain (1.5)Using FormatterKit (1.4.2)Using ISO8601DateFormatterValueTransformer (0.5.0)Using RHAddressBook (1.1.1)Using RKValueTransformers (1.0.1)Using RestKit (0.22.0)Using SDWebImage (3.5.4)Using SDWebImage-ProgressView (0.3.1)

Page 197: Modernizes your objective C - Oliviero

Cocoapods$ sudo gem install cocoapods

$ cd MyGreatApp

$ pod init

$ edit Podfile

platform :ios, '6.1'

pod 'RestKit', '~> 0.22.0'pod 'FXKeychain', '~> 1.5'pod 'SDWebImage', '~> 3.5.2'pod 'SDWebImage-ProgressView', '~> 0.3.0'pod 'RHAddressBook', '~> 1.1.1'pod 'FormatterKit', '~> 1.4.2'

$ pod install

Analyzing dependencies

Downloading dependenciesUsing AFNetworking (1.3.3)Using FXKeychain (1.5)Using FormatterKit (1.4.2)Using ISO8601DateFormatterValueTransformer (0.5.0)Using RHAddressBook (1.1.1)Using RKValueTransformers (1.0.1)Using RestKit (0.22.0)Using SDWebImage (3.5.4)Using SDWebImage-ProgressView (0.3.1)Using SOCKit (1.1)

Page 198: Modernizes your objective C - Oliviero

Cocoapods$ sudo gem install cocoapods

$ cd MyGreatApp

$ pod init

$ edit Podfile

platform :ios, '6.1'

pod 'RestKit', '~> 0.22.0'pod 'FXKeychain', '~> 1.5'pod 'SDWebImage', '~> 3.5.2'pod 'SDWebImage-ProgressView', '~> 0.3.0'pod 'RHAddressBook', '~> 1.1.1'pod 'FormatterKit', '~> 1.4.2'

$ pod install

Analyzing dependencies

Downloading dependenciesUsing AFNetworking (1.3.3)Using FXKeychain (1.5)Using FormatterKit (1.4.2)Using ISO8601DateFormatterValueTransformer (0.5.0)Using RHAddressBook (1.1.1)Using RKValueTransformers (1.0.1)Using RestKit (0.22.0)Using SDWebImage (3.5.4)Using SDWebImage-ProgressView (0.3.1)Using SOCKit (1.1)Using TransitionKit (2.0.0)

Page 199: Modernizes your objective C - Oliviero

Cocoapods$ sudo gem install cocoapods

$ cd MyGreatApp

$ pod init

$ edit Podfile

platform :ios, '6.1'

pod 'RestKit', '~> 0.22.0'pod 'FXKeychain', '~> 1.5'pod 'SDWebImage', '~> 3.5.2'pod 'SDWebImage-ProgressView', '~> 0.3.0'pod 'RHAddressBook', '~> 1.1.1'pod 'FormatterKit', '~> 1.4.2'

$ pod install

Analyzing dependencies

Downloading dependenciesUsing AFNetworking (1.3.3)Using FXKeychain (1.5)Using FormatterKit (1.4.2)Using ISO8601DateFormatterValueTransformer (0.5.0)Using RHAddressBook (1.1.1)Using RKValueTransformers (1.0.1)Using RestKit (0.22.0)Using SDWebImage (3.5.4)Using SDWebImage-ProgressView (0.3.1)Using SOCKit (1.1)Using TransitionKit (2.0.0)Generating Pods project

Page 200: Modernizes your objective C - Oliviero

Cocoapods$ sudo gem install cocoapods

$ cd MyGreatApp

$ pod init

$ edit Podfile

platform :ios, '6.1'

pod 'RestKit', '~> 0.22.0'pod 'FXKeychain', '~> 1.5'pod 'SDWebImage', '~> 3.5.2'pod 'SDWebImage-ProgressView', '~> 0.3.0'pod 'RHAddressBook', '~> 1.1.1'pod 'FormatterKit', '~> 1.4.2'

$ pod install

Analyzing dependencies

Downloading dependenciesUsing AFNetworking (1.3.3)Using FXKeychain (1.5)Using FormatterKit (1.4.2)Using ISO8601DateFormatterValueTransformer (0.5.0)Using RHAddressBook (1.1.1)Using RKValueTransformers (1.0.1)Using RestKit (0.22.0)Using SDWebImage (3.5.4)Using SDWebImage-ProgressView (0.3.1)Using SOCKit (1.1)Using TransitionKit (2.0.0)Generating Pods projectIntegrating client project

Page 201: Modernizes your objective C - Oliviero

Cocoapods$ sudo gem install cocoapods

$ cd MyGreatApp

$ pod init

$ edit Podfile

platform :ios, '6.1'

pod 'RestKit', '~> 0.22.0'pod 'FXKeychain', '~> 1.5'pod 'SDWebImage', '~> 3.5.2'pod 'SDWebImage-ProgressView', '~> 0.3.0'pod 'RHAddressBook', '~> 1.1.1'pod 'FormatterKit', '~> 1.4.2'

$ pod install

Analyzing dependencies

Downloading dependenciesUsing AFNetworking (1.3.3)Using FXKeychain (1.5)Using FormatterKit (1.4.2)Using ISO8601DateFormatterValueTransformer (0.5.0)Using RHAddressBook (1.1.1)Using RKValueTransformers (1.0.1)Using RestKit (0.22.0)Using SDWebImage (3.5.4)Using SDWebImage-ProgressView (0.3.1)Using SOCKit (1.1)Using TransitionKit (2.0.0)Generating Pods projectIntegrating client project

Page 202: Modernizes your objective C - Oliviero

Cocoapods$ sudo gem install cocoapods

$ cd MyGreatApp

$ pod init

$ edit Podfile

platform :ios, '6.1'

pod 'RestKit', '~> 0.22.0'pod 'FXKeychain', '~> 1.5'pod 'SDWebImage', '~> 3.5.2'pod 'SDWebImage-ProgressView', '~> 0.3.0'pod 'RHAddressBook', '~> 1.1.1'pod 'FormatterKit', '~> 1.4.2'

$ pod install

Analyzing dependencies

Downloading dependenciesUsing AFNetworking (1.3.3)Using FXKeychain (1.5)Using FormatterKit (1.4.2)Using ISO8601DateFormatterValueTransformer (0.5.0)Using RHAddressBook (1.1.1)Using RKValueTransformers (1.0.1)Using RestKit (0.22.0)Using SDWebImage (3.5.4)Using SDWebImage-ProgressView (0.3.1)Using SOCKit (1.1)Using TransitionKit (2.0.0)Generating Pods projectIntegrating client project

$

Page 203: Modernizes your objective C - Oliviero

Cocoapods

Page 204: Modernizes your objective C - Oliviero

Cocoapods‣ CocoaPods manage dependency for you, it download

source files, imports headers and configures flags

Page 205: Modernizes your objective C - Oliviero

Cocoapods‣ CocoaPods manage dependency for you, it download

source files, imports headers and configures flags

‣ CocoaPods is strongly inspired by a combination of the Ruby projects RubyGems and Bundler

Page 206: Modernizes your objective C - Oliviero

Cocoapods‣ CocoaPods manage dependency for you, it download

source files, imports headers and configures flags

‣ CocoaPods is strongly inspired by a combination of the Ruby projects RubyGems and Bundler

‣ CocoaPods focuses on source-based distribution of third party code and automatic integration into Xcode projects

Page 207: Modernizes your objective C - Oliviero

Cocoapods‣ CocoaPods manage dependency for you, it download

source files, imports headers and configures flags

‣ CocoaPods is strongly inspired by a combination of the Ruby projects RubyGems and Bundler

‣ CocoaPods focuses on source-based distribution of third party code and automatic integration into Xcode projects

‣ CocoaPods runs from the command line

Page 208: Modernizes your objective C - Oliviero

Framework

Page 209: Modernizes your objective C - Oliviero

Key-Value Codingdynamically set and get properties and object graph

Page 210: Modernizes your objective C - Oliviero

Key-Value CodingMGACustomer *c1 = [[MGACustomer alloc] initWithName:@“ACME Inc.”]; c1.address = [[MGAAddress alloc] initWithZip:@“33568”]; !![c1 valueForKey:@"name"]; // ACME Inc. [c1 valueForKeyPath:@“address.zip"]; // 33568

Page 211: Modernizes your objective C - Oliviero

Key-Value CodingMGACustomer *c1 = [[MGACustomer alloc] initWithName:@“ACME Inc.”]; c1.address = [[MGAAddress alloc] initWithZip:@“33568”]; !![c1 valueForKey:@"name"]; // ACME Inc. [c1 valueForKeyPath:@“address.zip"]; // 33568

NSArray *names = @[ @"Steve", @"Bill", @"Ive" ]; !// you can “get the value” of any method with no parameter [names valueForKey:@"uppercaseString"]; // @[ @“STEVE”, @“BILL”, @“IVE”] [names valueForKey:@"lowercaseString"]; // @[ @“steve”, @“bill”, @“ive”] !!// It’s really any method. // For example, -[NSObject self] is a method like any other. [@"Steve" valueForKey:@“self"]; // @“Steve” !!// KVC automatically boxes and unboxes values [names valueForKey:@"length"]; // @[ @5, @4, @3 ]

Page 212: Modernizes your objective C - Oliviero

Key-Value Coding

Page 213: Modernizes your objective C - Oliviero

Key-Value Coding‣ Key-value coding is a mechanism for accessing an

object’s properties indirectly, using strings to identify properties

Page 214: Modernizes your objective C - Oliviero

Key-Value Coding‣ Key-value coding is a mechanism for accessing an

object’s properties indirectly, using strings to identify properties

‣ You can get the value of any method with no parameter

Page 215: Modernizes your objective C - Oliviero

Key-Value Coding‣ Key-value coding is a mechanism for accessing an

object’s properties indirectly, using strings to identify properties

‣ You can get the value of any method with no parameter

‣ Key-Value Coding automatically boxes and unboxes values into their object representation.

Page 216: Modernizes your objective C - Oliviero

discover KVC Collection Operatorssave a few extra lines of code

Page 217: Modernizes your objective C - Oliviero

KVC Collection Operators

Page 218: Modernizes your objective C - Oliviero

KVC Collection OperatorsMGAPerson *p1 = [[MGAPerson alloc] initWithName:@"Max" age:34];MGAPerson *p2 = [[MGAPerson alloc] initWithName:@"Steve" age:54];MGAPerson *p3 = [[MGAPerson alloc] initWithName:@"Bill" age:62];

NSArray *people = @[ p1, p2, p3 ];

// Simple Collection Operators[people valueForKeyPath:@"@count"]; // 3[people valueForKeyPath:@"@sum.age"]; // 150.00[people valueForKeyPath:@"@avg.age"]; // 50.00[people valueForKeyPath:@"@max.age"]; // 63.00

// Objects Operators[people valueForKeyPath:@"@unionOfObjects.name"]; // "Max", "Steve", “Bill"

// Simple Collection Operators with NSNumberNSArray *numbers = @[ @(1), @(2), @(3) ];

[numbers valueForKeyPath:@"@max.self"]; // 3

Page 219: Modernizes your objective C - Oliviero

KVC Collection Operators

Page 220: Modernizes your objective C - Oliviero

KVC Collection Operators‣ Collection operators allow actions to be performed on

the items of a collection using key path notation and an action operator

Page 221: Modernizes your objective C - Oliviero

KVC Collection Operators‣ Collection operators allow actions to be performed on

the items of a collection using key path notation and an action operator

‣ Collection operators are specialized key paths that are passed as the parameter to the valueForKeyPath: method

Page 222: Modernizes your objective C - Oliviero

KVC Collection Operators‣ Collection operators allow actions to be performed on

the items of a collection using key path notation and an action operator

‣ Collection operators are specialized key paths that are passed as the parameter to the valueForKeyPath: method

‣ The operator is specified by a string preceded by an at sign (@)

Page 223: Modernizes your objective C - Oliviero

discover NSBlockOperation class

Page 224: Modernizes your objective C - Oliviero

NSBlockOperation

Page 225: Modernizes your objective C - Oliviero

NSBlockOperationNSBlockOperation *blockOp = [[NSBlockOperation alloc] init];

Page 226: Modernizes your objective C - Oliviero

NSBlockOperationNSBlockOperation *blockOp = [[NSBlockOperation alloc] init];

Page 227: Modernizes your objective C - Oliviero

NSBlockOperationNSBlockOperation *blockOp = [[NSBlockOperation alloc] init];

__weak typeof(blockOp) weakOp = blockOp;

Page 228: Modernizes your objective C - Oliviero

NSBlockOperationNSBlockOperation *blockOp = [[NSBlockOperation alloc] init];

__weak typeof(blockOp) weakOp = blockOp;

Page 229: Modernizes your objective C - Oliviero

NSBlockOperationNSBlockOperation *blockOp = [[NSBlockOperation alloc] init];

__weak typeof(blockOp) weakOp = blockOp;

[blockOp addExecutionBlock:^

Page 230: Modernizes your objective C - Oliviero

NSBlockOperationNSBlockOperation *blockOp = [[NSBlockOperation alloc] init];

__weak typeof(blockOp) weakOp = blockOp;

[blockOp addExecutionBlock:^{

Page 231: Modernizes your objective C - Oliviero

NSBlockOperationNSBlockOperation *blockOp = [[NSBlockOperation alloc] init];

__weak typeof(blockOp) weakOp = blockOp;

[blockOp addExecutionBlock:^{

for (NSInteger i = 0; i < 10000; i++)

Page 232: Modernizes your objective C - Oliviero

NSBlockOperationNSBlockOperation *blockOp = [[NSBlockOperation alloc] init];

__weak typeof(blockOp) weakOp = blockOp;

[blockOp addExecutionBlock:^{

for (NSInteger i = 0; i < 10000; i++){

Page 233: Modernizes your objective C - Oliviero

NSBlockOperationNSBlockOperation *blockOp = [[NSBlockOperation alloc] init];

__weak typeof(blockOp) weakOp = blockOp;

[blockOp addExecutionBlock:^{

for (NSInteger i = 0; i < 10000; i++){

if ([weakOp isCancelled])

Page 234: Modernizes your objective C - Oliviero

NSBlockOperationNSBlockOperation *blockOp = [[NSBlockOperation alloc] init];

__weak typeof(blockOp) weakOp = blockOp;

[blockOp addExecutionBlock:^{

for (NSInteger i = 0; i < 10000; i++){

if ([weakOp isCancelled]){

Page 235: Modernizes your objective C - Oliviero

NSBlockOperationNSBlockOperation *blockOp = [[NSBlockOperation alloc] init];

__weak typeof(blockOp) weakOp = blockOp;

[blockOp addExecutionBlock:^{

for (NSInteger i = 0; i < 10000; i++){

if ([weakOp isCancelled]){

break;

Page 236: Modernizes your objective C - Oliviero

NSBlockOperationNSBlockOperation *blockOp = [[NSBlockOperation alloc] init];

__weak typeof(blockOp) weakOp = blockOp;

[blockOp addExecutionBlock:^{

for (NSInteger i = 0; i < 10000; i++){

if ([weakOp isCancelled]){

break;}

Page 237: Modernizes your objective C - Oliviero

NSBlockOperationNSBlockOperation *blockOp = [[NSBlockOperation alloc] init];

__weak typeof(blockOp) weakOp = blockOp;

[blockOp addExecutionBlock:^{

for (NSInteger i = 0; i < 10000; i++){

if ([weakOp isCancelled]){

break;}

Page 238: Modernizes your objective C - Oliviero

NSBlockOperationNSBlockOperation *blockOp = [[NSBlockOperation alloc] init];

__weak typeof(blockOp) weakOp = blockOp;

[blockOp addExecutionBlock:^{

for (NSInteger i = 0; i < 10000; i++){

if ([weakOp isCancelled]){

break;}

NSLog(@"%i", i);

Page 239: Modernizes your objective C - Oliviero

NSBlockOperationNSBlockOperation *blockOp = [[NSBlockOperation alloc] init];

__weak typeof(blockOp) weakOp = blockOp;

[blockOp addExecutionBlock:^{

for (NSInteger i = 0; i < 10000; i++){

if ([weakOp isCancelled]){

break;}

NSLog(@"%i", i);}

Page 240: Modernizes your objective C - Oliviero

NSBlockOperationNSBlockOperation *blockOp = [[NSBlockOperation alloc] init];

__weak typeof(blockOp) weakOp = blockOp;

[blockOp addExecutionBlock:^{

for (NSInteger i = 0; i < 10000; i++){

if ([weakOp isCancelled]){

break;}

NSLog(@"%i", i);}

}];

Page 241: Modernizes your objective C - Oliviero

NSBlockOperationNSBlockOperation *blockOp = [[NSBlockOperation alloc] init];

__weak typeof(blockOp) weakOp = blockOp;

[blockOp addExecutionBlock:^{

for (NSInteger i = 0; i < 10000; i++){

if ([weakOp isCancelled]){

break;}

NSLog(@"%i", i);}

}];

Page 242: Modernizes your objective C - Oliviero

NSBlockOperationNSBlockOperation *blockOp = [[NSBlockOperation alloc] init];

__weak typeof(blockOp) weakOp = blockOp;

[blockOp addExecutionBlock:^{

for (NSInteger i = 0; i < 10000; i++){

if ([weakOp isCancelled]){

break;}

NSLog(@"%i", i);}

}];

[blockOp start];

Page 243: Modernizes your objective C - Oliviero

NSBlockOperation

Page 244: Modernizes your objective C - Oliviero

NSBlockOperation‣ NSBlockOperation is a concrete subclass that wraps

block in operations

Page 245: Modernizes your objective C - Oliviero

NSBlockOperation‣ NSBlockOperation is a concrete subclass that wraps

block in operations

‣ You can use this object to execute several blocks at once without having to create separate operation objects for each

Page 246: Modernizes your objective C - Oliviero

NSBlockOperation‣ NSBlockOperation is a concrete subclass that wraps

block in operations

‣ You can use this object to execute several blocks at once without having to create separate operation objects for each

‣ When executing more than one block, the operation itself is considered finished only when all blocks have finished executing

Page 247: Modernizes your objective C - Oliviero

NSErrorit encapsulates richer and more extensible error information

Page 248: Modernizes your objective C - Oliviero

Create an NSError

Page 249: Modernizes your objective C - Oliviero

Create an NSErrorNSString * const kMGAErrorDomain = @“com.acmeinc.MyGreatApp”;

typedef NS_ENUM(NSInteger, MGAErrorCode){

MGAErrorCodeUnableToLocateUser = 500,MGAErrorCodeInvalidUser = 401

};

NSDictionary *userInfo =@{

NSLocalizedDescriptionKey:NSLocalizedString(@“Location error”, nil),

NSLocalizedFailureReasonErrorKey :NSLocalizedString(@"The location service is not active.", nil),

NSLocalizedRecoverySuggestionErrorKey :NSLocalizedString(@"Please turn on the location service and try again", nil)

};

NSError *error = [NSError errorWithDomain:kMGAErrorDomaincode:MGAErrorCodeUnableToLocateUser

userInfo:userInfo];

Page 250: Modernizes your objective C - Oliviero

Handle NSError

Page 251: Modernizes your objective C - Oliviero

Handle NSError- (void)handleError:(NSError *)error{

if (error){

NSString *errorMessage;errorMessage = [NSString stringWithFormat:@"%@\n%@",

error.localizedFailureReason,error.localizedRecoverySuggestion];

UIAlertView *alert = [[UIAlertView alloc]initWithTitle:error.localizedDescription

message:errorMessagedelegate:nil

cancelButtonTitle:NSLocalizedString(@"OK", nil)otherButtonTitles:nil, nil];

[alert show];}

}

Page 252: Modernizes your objective C - Oliviero

Consuming NSError

Page 253: Modernizes your objective C - Oliviero

Consuming NSError- (void)doLogin{

NSString *user = self.usernameTextField.text;NSString *pass = self.passwordTextField.text;

__weak typeof(self) weakSelf = self;

[self.service loginWithUser:user pass:pass completion:^(TMGAUser *user, NSError *error){

[weakSelf handleError:error];

if (!error){

[weakSelf navigateToHome];}

}];}

Page 254: Modernizes your objective C - Oliviero

NSError

Page 255: Modernizes your objective C - Oliviero

NSError‣ An NSError object encapsulates richer and more

extensible error information than is possible using only an error code or error string

Page 256: Modernizes your objective C - Oliviero

NSError‣ An NSError object encapsulates richer and more

extensible error information than is possible using only an error code or error string

‣ The core attributes of an NSError object are an error domain, a domain-specific error code and a user info dictionary containing application specific information.

Page 257: Modernizes your objective C - Oliviero

NSError‣ An NSError object encapsulates richer and more

extensible error information than is possible using only an error code or error string

‣ The core attributes of an NSError object are an error domain, a domain-specific error code and a user info dictionary containing application specific information.

‣ Domain-specific error codes are generally defined by constants in an enum.

Page 258: Modernizes your objective C - Oliviero

use NSCacheIt’s a collection-like container, or cache, that stores key-value pairs, similar to the

NSMutableDictionary class.

Page 259: Modernizes your objective C - Oliviero

NSCache

Page 260: Modernizes your objective C - Oliviero

NSCacheNSCache *cache = [[NSCache alloc] init]; !!// Sets the maximum number of objects that the cache can hold. !// This limit is not a strict limit, and if the cache goes over the limit, // an object in the cache could be evicted instantly, later, or possibly never, // all depending on the implementation details of the cache. [cache setCountLimit:50]; !!// Sets the maximum total cost that the cache can have before it starts evicting objects !// If adding this object to the cache causes the cache’s total cost to rise above // totalCostLimit, the cache could automatically evict some of its objects until its // total cost falls below totalCostLimit. The order in which the cache evicts objects is // not guaranteed. This limit is not a strict limit, and if the cache goes over the // limit, an object in the cache could be evicted instantly, at a later point in time, // or possibly never, all depending on the implementation details of the cache. [cache setTotalCostLimit:5000]; !!// Add object to cache with cost [cache setObject:customer1 forKey:@"c1" cost:10]; !!// Add object to cache without cost [cache setObject:customer2 forKey:@"c2"];

Page 261: Modernizes your objective C - Oliviero

NSCache

Page 262: Modernizes your objective C - Oliviero

NSCache‣ NSCache is basically just an NSMutableDictionary that

automatically evicts objects in order to free up space in memory as needed

Page 263: Modernizes your objective C - Oliviero

NSCache‣ NSCache is basically just an NSMutableDictionary that

automatically evicts objects in order to free up space in memory as needed

‣ The NSCache class incorporates various auto-removal policies, which ensure that it does not use too much of the system’s memory. The system automatically carries out these policies if memory is needed by other applications. When invoked, these policies remove some items from the cache, minimizing its memory footprint.

Page 264: Modernizes your objective C - Oliviero

NSCache

Page 265: Modernizes your objective C - Oliviero

NSCache‣ It is guaranteed to be thread-safe.

Page 266: Modernizes your objective C - Oliviero

NSCache‣ It is guaranteed to be thread-safe.

‣ It is much slower to access.

Page 267: Modernizes your objective C - Oliviero

NSCache‣ It is guaranteed to be thread-safe.

‣ It is much slower to access.

‣ It may throw out objects from time to time. You can set costs and limits, but they're not guaranteed to be followed.

Page 268: Modernizes your objective C - Oliviero

NSCache‣ It is guaranteed to be thread-safe.

‣ It is much slower to access.

‣ It may throw out objects from time to time. You can set costs and limits, but they're not guaranteed to be followed.

‣ It is not toll-free bridged to anything in CoreFoundation.

Page 269: Modernizes your objective C - Oliviero

NSCache‣ It is guaranteed to be thread-safe.

‣ It is much slower to access.

‣ It may throw out objects from time to time. You can set costs and limits, but they're not guaranteed to be followed.

‣ It is not toll-free bridged to anything in CoreFoundation.

‣ You can't query the number of objects that are in the cache.

Page 270: Modernizes your objective C - Oliviero

NSCache‣ It is guaranteed to be thread-safe.

‣ It is much slower to access.

‣ It may throw out objects from time to time. You can set costs and limits, but they're not guaranteed to be followed.

‣ It is not toll-free bridged to anything in CoreFoundation.

‣ You can't query the number of objects that are in the cache.

‣ You can't enumerate a cache.

Page 271: Modernizes your objective C - Oliviero

NSValueNSValue is a simple container for a single C or Objective-C data value

Page 272: Modernizes your objective C - Oliviero

NSValue

Page 273: Modernizes your objective C - Oliviero

NSValueNSMutableArray *items = [@[] mutableCopy];

[items addObject:[NSValue valueWithCGSize:CGSizeMake(200.0f, 300.0f)]];

NSValue *sizeValue = items[0];CGSize size = [sizeValue CGSizeValue];

// define new structtypedef struct MGAColor{

float red, blue, green;}MGAColor;

MGAColor color = { 255.0, 0.0f, 34.0 };

[items addObject:[NSValue valueWithBytes:&color objCType:@encode(MGAColor)]];

Page 274: Modernizes your objective C - Oliviero

NSValueNSMutableArray *items = [@[] mutableCopy];

[items addObject:[NSValue valueWithCGSize:CGSizeMake(200.0f, 300.0f)]];

NSValue *sizeValue = items[0];CGSize size = [sizeValue CGSizeValue];

// define new structtypedef struct MGAColor{

float red, blue, green;}MGAColor;

MGAColor color = { 255.0, 0.0f, 34.0 };

[items addObject:[NSValue valueWithBytes:&color objCType:@encode(MGAColor)]];

MGAUser *user = [[MGAUser alloc] init]; // it not conforms to <NSCopying>

NSMutableDictionary *items = [@{} mutableCopy];

// e.g. I want to store num of login attempts of a user// because my custom class MGAUser does not conform to <NSCopying>// I can’t use it as key value. The workaround is to box user instance// into NSValue object with valueWithNonretainedObject:[items setObject:numLogin forKey:[NSValue valueWithNonretainedObject:user]];

Page 275: Modernizes your objective C - Oliviero

NSValue

Page 276: Modernizes your objective C - Oliviero

NSValue ‣ It can hold scalars and value types, as well as pointers

and object IDs.

Page 277: Modernizes your objective C - Oliviero

NSValue ‣ It can hold scalars and value types, as well as pointers

and object IDs.

‣ NSValue uses type encoding to create the necessary data structures to represent values internally

Page 278: Modernizes your objective C - Oliviero

NSValue ‣ It can hold scalars and value types, as well as pointers

and object IDs.

‣ NSValue uses type encoding to create the necessary data structures to represent values internally

‣ valueWithNonretainedObject: allows objects to be added to a collection, without the need for satisfying <NSCopying> protocol

Page 279: Modernizes your objective C - Oliviero

Thanks!Massimo Oliviero

@maxoly