Designs, patterns and practices in Object Oriented Programming
for iOS Developers
Agenda
• obvious best practices in Obj-C (or at least what I do)
• software design patterns
• In mean time there are some questions waiting for you
The obvious is that which is never seen until someone
expresses it simply.
Khalil Gibran
Best Practices
#pragma mark - group stuff
CHCamelCaseWordInEnglish
@properties vs iVars
NEON for the performance
Method naming
Examples
- (instancetype)initWithWidth:(CGFloat)width andHeight:(CGFloat)height;
- (UIView*)taggedView:(NSInteger)tag;
- (void)setT:(NSString *)text i:(UIImage *)image;
- (void)sendAction:(SEL)aSelector: (id)anObject :(BOOL)flag;
.Notation or [Brackets]
if (!error) return success;
Ternary operator
NSInteger value = 5; result = (value != 0) ? x : y;
int a = 1, b = 2, c = 3, d = 4; int x = 10, y = 5; int result = a > b ? x = c > d ? c : d : y;
Design Patterns
- are reusable solutions to common problems in software design.
!- They’re templates designed to help you write
code that’s easy to understand and reuse. !- They also help you create loosely coupled
code so that you can change or replace components in your code without too much of a hassle.
MVC
KVO
Singleton
How to use ?
Singletons in Obj-C
• [NSUserDefaults standardUserDefaults]
• [UIScreen mainScreen]
• [NSFileManager defaultManager]
• [UIApplication sharedApplication]
Façade• make a software library easier to
use, understand and test, since the facade has convenient methods for common tasks;
• make the library more readable, for the same reason;
• reduce dependencies of outside code on the inner workings of a library, since most code uses the facade, thus allowing more flexibility in developing the system;
• wrap a poorly designed collection of APIs with a single well-designed API (as per task needs).
Strategy
Strategy
• defines a family of algorithms,
• encapsulates each algorithm
• makes the algorithms interchangeable within that family.
@protocol Strategy <NSObject> !@optional - (void) execute; !@end
@interface ConcreteStrategyA : NSObject <Strategy> { // ivars for A } @end
@implementation ConcreteStrategyA !- (void) execute { NSLog(@"Called ConcreteStrategyA execute method"); } !@end
@interface Context : NSObject { id<Strategy> strategy; } @property (assign) id<Strategy> strategy; !- (void) execute; !@end
@implementation Context !@synthesize strategy; !- (void) execute { if ([strategy respondsToSelector:@selector(execute)]) { [strategy execute]; } } !@end
Decorator (Wrapper, Adapter)
is a design pattern that allows behavior to be added to an individual object, either statically or dynamically, without affecting the behavior of other objects from the same class.
Category#import "UIImage+Retina4.h" #import <objc/runtime.h> !static Method origImageNamedMethod = nil; !@implementation UIImage (Retina4) !+ (void)initialize { origImageNamedMethod = class_getClassMethod(self, @selector(imageNamed:)); method_exchangeImplementations(origImageNamedMethod, class_getClassMethod(self, @selector(retina4ImageNamed:))); } !+ (UIImage *)retina4ImageNamed:(NSString *)imageName { NSMutableString *imageNameMutable = [imageName mutableCopy]; NSRange retinaAtSymbol = [imageName rangeOfString:@"@"]; if (retinaAtSymbol.location != NSNotFound) { [imageNameMutable insertString:@"-568h" atIndex:retinaAtSymbol.location]; } else { CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height; if ([UIScreen mainScreen].scale == 2.f && screenHeight == 568.0f) { NSRange dot = [imageName rangeOfString:@"."]; if (dot.location != NSNotFound) { [imageNameMutable insertString:@"-568h@2x" atIndex:dot.location]; } else { [imageNameMutable appendString:@"-568h@2x"]; } } } NSString *imagePath = [[NSBundle mainBundle] pathForResource:imageNameMutable ofType:@""]; if (imagePath) { return [UIImage retina4ImageNamed:imageNameMutable]; } else { return [UIImage retina4ImageNamed:imageName]; } return nil; } !@end
DelegateThis is an important pattern. Apple uses this approach in most of the UIKit classes:
UITableViewUITextView
UITextField
UIWebView
UIAlertUIActionSheet
UICollectionView
UIGestureRecognizer
UIScrollView
UIPickerView
Commandis a behavioral design pattern in which an object is used to represent and encapsulate all the information needed to call a method at a later time
NSInvocation
!NSMethodSignature * mySignature = [NSMutableArray instanceMethodSignatureForSelector:@selector(addObject:)]; NSInvocation * myInvocation = [NSInvocation invocationWithMethodSignature:mySignature]; NSString * myString = @"String"; //Next, you would specify which object to send the message to: ![myInvocation setTarget:myArray]; //Specify the message you wish to send to that object: ![myInvocation setSelector:@selector(addObject:)]; //And fill in any arguments for that method: ![myInvocation setArgument:&myString atIndex:2]; //Note that object arguments must be passed by pointer. !//At this point, myInvocation is a complete object, describing a message that can be sent. To actually send the message, you would call: ![myInvocation invoke];
An NSInvocation is an Objective-C message rendered static, that is, it is an action turned into an object.
!
Where to go from that?
Thank you for your attention!Questions?