10. Enum with Indeterminate Type
Before OS X v10.5 and iOS
typedef enum {
NSNumberFormatterNoStyle,
NSNumberFormatterDecimalStyle,
NSNumberFormatterCurrencyStyle,
NSNumberFormatterPercentStyle,
NSNumberFormatterScientificStyle,
NSNumberFormatterSpellOutStyle
} NSNumberFormatterStyle;
//typedef int NSNumberFormatterStyle;
Pragma Night
11. Enum with Explicit Type
After OS X v10.5 and iOS
enum {
NSNumberFormatterNoStyle,
NSNumberFormatterDecimalStyle,
NSNumberFormatterCurrencyStyle,
NSNumberFormatterPercentStyle,
NSNumberFormatterScientificStyle,
NSNumberFormatterSpellOutStyle
};
typedef NSUInteger NSNumberFormatterStyle;
• Pro: 32-bit and 64-bit portability
• Con: no formal relationship between type and enum constants
Pragma Night
12. Enum with Fixed Underlying Type
LLVM 4.2+ Compiler
typedef enum NSNumberFormatterStyle : NSUInteger {
NSNumberFormatterNoStyle,
NSNumberFormatterDecimalStyle,
NSNumberFormatterCurrencyStyle,
NSNumberFormatterPercentStyle,
NSNumberFormatterScientificStyle,
NSNumberFormatterSpellOutStyle
} NSNumberFormatterStyle;
Xcode 4.4+
• Stronger type checking
• Better code completion
Pragma Night
13. Enum with Fixed Underlying Type
NS_ENUM macro
typedef NS_ENUM(NSUInteger, NSNumberFormatterStyle) {
NSNumberFormatterNoStyle,
NSNumberFormatterDecimalStyle,
NSNumberFormatterCurrencyStyle,
NSNumberFormatterPercentStyle,
NSNumberFormatterScientificStyle,
NSNumberFormatterSpellOutStyle
};
Xcode 4.4+
• Foundation declares like this
Pragma Night
14. Enum with Fixed Underlying Type
Stronger type checking (-Wenum-conversion)
NSNumberFormatterStyle style = NSNumberFormatterRoundUp; // 3
warning:
implicit conversion from enumeration type 'enum
NSNumberFormatterRoundingMode' to different enumeration type
'NSNumberFormatterStyle' (aka 'enum NSNumberFormatterStyle')
Pragma Night
15. Enum with Fixed Underlying Type
Handling all enum values (-Wswitch)
- (void) printStyle:(NSNumberFormatterStyle) style{
switch (style) {
case NSNumberFormatterNoStyle:
break;
case NSNumberFormatterSpellOutStyle:
break;
}
}
warning:
4 enumeration values not handled in switch:
'NSNumberFormatterDecimalStyle',
'NSNumberFormatterCurrencyStyle',
'NSNumberFormatterPercentStyle'...
Pragma Night
17. Properties Simplify Classes
@interface instance variables
@interface Person : NSObject {
NSString *_name;
}
@property(strong) NSString *name;
@end
@implementation Person
@synthesize name = _name;
@end
Pragma Night
18. Properties Simplify Classes
@implementation instance variables
@interface Person : NSObject
@property(strong) NSString *name;
@end
@implementation Person {
NSString *_name;
}
@synthesize name = _name;
@end
Pragma Night
19. Properties Simplify Classes
Synthesized instance variables
@interface Person : NSObject
@property(strong) NSString *name;
@end
@implementation Person
@synthesize name = _name;
@end
Pragma Night
20. @Synthesize by Default
LLVM 4.2+ Compiler
@interface Person : NSObject
@property(strong) NSString *name;
@end
@implementation Person
Xcode 4.4+
@end
Pragma Night
21. Instance Variable Name !?
Instance variables now prefixed with “_”
@interface Person : NSObject
@property(strong) NSString *name;
@end
@implementation Person
- (NSString *)description {
return _name; Xcode 4.4+
}
/* as if you'd written: @synthesize name = _name; */
@end
Pragma Night
22. Backward Compatibility !?
Be careful, when in doubt be fully explicit
@interface Person : NSObject
@property(strong) NSString *name;
@end
@implementation Person
@synthesize name;
/* as if you'd written: @synthesize name = name; */
@end
Pragma Night
23. To @Synthesize by Default
• Warning: @Synthesize by Default will not
synthesize a property declared in a protocol
• If you use custom instance variable naming
convention, enable this warning
( -Wobjc-missing-property-synthesis )
Pragma Night
24. Core Data NSManagedObject
Opts out of synthesize by default
/* NSManagedObject.h */
NS_REQUIRES_PROPERTY_DEFINITIONS
@interface NSManagedObject : NSObject {
• NSManagedObject synthesizes properties
• Continue to use @property to declare typed accessors
• Continue to use @dynamic to inhibit warnings
Pragma Night
26. NSNumber Creation
NSNumber *value;
value = [NSNumber numberWithChar:'X'];
value = [NSNumber numberWithInt:42];
value = [NSNumber numberWithUnsignedLong:42ul];
value = [NSNumber numberWithLongLong:42ll];
value = [NSNumber numberWithFloat:0.42f];
value = [NSNumber numberWithDouble:0.42];
value = [NSNumber numberWithBool:YES];
Pragma Night
27. NSNumber Creation
NSNumber *value;
value = @'X';
value = @42;
value = @42ul;
value = @42ll;
value = @0.42f;
Xcode 4.4+
value = @0.42;
value = @YES;
Pragma Night
28. Backward Compatibility !?
#define YES (BOOL)1 // Before iOS 6, OSX 10.8
#define YES ((BOOL)1) // After iOS 6, OSX 10.8
Workarounds
@(YES) // Use parentheses around BOOL Macros
#if __IPHONE_OS_VERSION_MAX_ALLOWED < 60000
#if __has_feature(objc_bool)
#undef YES
#undef NO // Redefine BOOL Macros
#define YES __objc_yes
#define NO __objc_no
#endif
#endif
Pragma Night
33. Array Creation
More choices, and more chances for errors
NSArray *array;
array = [NSArray array];
array = [NSArray arrayWithObject:a];
array = [NSArray arrayWithObjects:a, b, c, nil];
id objects[] = { a, b, c };
NSUInteger count = sizeof(objects) / sizeof(id);
array = [NSArray arrayWithObjects:objects count:count];
Pragma Night
34. Nil Termination
Inconsistent behavior
// if you write:
id a = nil, b = @"hello", c = @42;
NSArray *array
= [NSArray arrayWithObjects:a, b, c, nil];
Array will be empty
// if you write:
id objects[] = { nil, @"hello", @42 };
NSUInteger count = sizeof(objects)/ sizeof(id);
NSArray *array
= [NSArray arrayWithObjects:objects count:count];
Exception: attempt to insert nil object from objects[0]
Pragma Night
37. How Array Literals Work
// when you write this:
NSArray *array = @[ a, b, c ];
// compiler generates:
id objects[] = { a, b, c };
NSUInteger count = sizeof(objects)/ sizeof(id);
NSArray *array
= [NSArray arrayWithObjects:objects count:count];
Pragma Night
45. Array Subscripting
New syntax to access object at index: nsarray[index]
@implementation SongList
{
NSMutableArray *_songs;
}
- (Song *)replaceSong:(Song *)newSong
atIndex:(NSUInteger)idx
{
Song *oldSong = [_songs objectAtIndex:idx];
[_songs replaceObjectAtIndex:idx withObject:newSong];
return oldSong;
}
@end
Pragma Night
46. Array Subscripting
New syntax to access object at index: nsarray[index]
@implementation SongList
{
NSMutableArray *_songs;
}
- (Song *)replaceSong:(Song *)newSong
atIndex:(NSUInteger)idx
{ Xcode 4.4+
Song *oldSong = _songs[idx];
_songs[idx] = newSong;
return oldSong;
}
@end
Pragma Night
47. Dictionary Subscripting
New syntax to access object by key: nsdictionary[key]
@implementation Database
{
NSMutableDictionary *_storage;
}
- (id)replaceObject:(id)newObject
forKey:(id <NSCopying>)key
{
id oldObject = [_storage objectForKey:key];
[_storage setObject:newObject forKey:key];
return oldObject;
}
@end
Pragma Night
48. Dictionary Subscripting
New syntax to access object by key: nsdictionary[key]
@implementation Database
{
NSMutableDictionary *_storage;
}
- (id)replaceObject:(id)newObject
forKey:(id <NSCopying>)key
{ Xcode 4.4+
id oldObject = _storage[key];
_storage[key] = newObject;
return oldObject;
}
@end
Pragma Night
49. How Subscripting Works
iOS 6
Array Style: Indexed subscripting methods OSX 10.8
- (elementType)objectAtIndexedSubscript:(indexType)idx
- (void)setObject:(elementType)obj
atIndexedSubscript:(indexType)idx;
elementType must be an object pointer, indexType must be integral
iOS 6
Dictionary Style: Keyed subscripting methods OSX 10.8
- (elementType)objectForKeyedSubscript:(keyType)key;
- (void)setObject:(elementType)obj
forKeyedSubscript:(keyType)key;
elementType and keyType must be an object pointer
Pragma Night
54. Backward Compatibility !?
To deploy back to iOS 5 and iOS 4 you need ARCLite:
use ARC or set explicit linker flag: “-fobjc-arc”
To make compiler happy, you should add 4 categories:
#if __IPHONE_OS_VERSION_MAX_ALLOWED < 60000
@interface NSDictionary(BCSubscripting)
- (id)objectForKeyedSubscript:(id)key;
@end
@interface NSMutableDictionary(BCSubscripting)
- (void)setObject:(id)obj forKeyedSubscript:(id )key;
@end
@interface NSArray(BCSubscripting)
- (id)objectAtIndexedSubscript:(NSUInteger)idx;
@end
@interface NSMutableArray(BCSubscripting)
- (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx;
@end
#endif
Pragma Night