Learn Objective C(5)Programming with Objective-C - Working with Protocols and Va

Learn Objective C(5)Programming with Objective-C - Working with Protocols and Values and Collections

5. Working with Protocols
Objective-C allows you to define protocols, which declare the methods expected to be used for a particular situation.
a. Defining a protocol
b. Mark a class interface as conforming to a protocol

5.1 Protocols Define Messaging Contracts
A protocol is used to declare methods and properties that are independent of any specific class.

@protocol ProtocolName
//list of methods and properties

Think about a pie chart, number of segments, relative size of each segment, title of each segment.

@protocol ZJUPieChartViewDataSource
     - (NSUInteger) numberOfSegments;
     - (CGFloat) sizeOfSegmentAtIndex:(NSUInteger)segmentIndex;
     - (NSString *)titleForSegmentAtIndex:(NSUInteger)segmentIndex;

So the only thing the view class know is the id reference and protocol.
@interface ZJUPieChartView : UIView
     @property (weak) id <ZJUPieChartViewDataSource> dataSource;

Objective-C uses angle brackets to indicate conformance to a protocol.

Protocols Can Have Optional Methods
It is also possible to specify optional methods in a protocol. We can use @optional directive like this
- (NSString *) titleForSegmentAtIndex: (NSUInteger) segmentIndex;

The optional directive applies to any methods that follow it, either until the end of the protocol definition, or until another directive is encountered, such as @required.
- (CGFlot) sizeOfSegmentAtIndex: (NSUInteger) segementIndex;
- (NSString *) titleForSegmentAtINdex: (NSUInteger) segmentIndex;
- (BOOL) shouldExplodeSegmentAtIndex: (NSUInteger) segmentIndex;
- (UIColor *) colorForSegmentAtIndex: (NSUInteger) segmentIndex;

Check that Optional Methods Are Implemented at Runtime
We need to check the optional methods before we use them.

NSString *thisSegmentTitle;
if([self.dataSource respondsToSelector: @selector(titleForSegmentAtIndex:) ]){
     thisSegmentTitle = [self.dataSource titleForSegmentAtIndex:index];

Protocols Inherit from Other Protocols
@protocol MyProtocol <NSObject>


5.2 Conforming to Protocols
@interface MyClass : NSObject <MyProtocol>


If we need a class to adopt multiple protocols, we specify them as a comma-separated list.
@interface MyClass : NSObject <MyProtocol, AnotherProtocol, YetAnotherProtocol>


Cocoa and Cocoa Touch Define a Large Number of Protocols
NSTableView ------ NSTableViewDelegate
UITableView  ------  UITableViewDelegate

5.3 Protocols Are Used for Anonymity

6. Values and Collections
It is a superset of C, we can use any of the standard C scalar types like int, float and char in Objective-C.

If you plan to use NSArray or NSDictionary, we need to put NSValue, NSNumber, or NSString in the arrays.

6.1 Basic C Primitive Types Are Available in Objective-C
int someInteger = 42;

Objective-C Defines Additional Primitive Types
BOOL    ---- YES NO
USInteger --- building for a 32-bit environment, such as for iOS
USUInteger --- 64-bit environment, such as for OS X

It is best practice to use these platform-specific types as arguments or return values in method or function calls between application code and framework. For local variable, such as a counter in a loop.

C Structures Can Hold Primitive Values

6.2 Objects Can Represent Primitive Values
Strings Are Represented by Instances of the NSString Class
NSString *firstString = [[NSString alloc] initWithCString:"hello"
NSString *thirdString = @"hello";

NSString is immutable.

NSString *name = @"Carl";
name = [name stringByAppendingString:@"son"];   //return a new string object

NSMutableString *name = [NSMutableString stringWithString:@"John"];
[name appendString:@"ny"];    // same object with different value

NSString stringWithFormat:@"The magic number is %i", intNumber];

Numbers Are Represented by Instances of the NSNumber Class
NSNumber *magicNumber = [[NSNumber alloc] initWithInt:42];
NSNumber *longNumber = [[NSNumber alloc] initWithLong:42l];
NSNumber *boolNumber = [[NSNumber alloc] initWithBOOL:YES];

NSNumber *someChar = [NSNumber numberWithChar:'T'];

We can init NSNumber with all these primitive types, char, double, float, int, long, short, BOOL.

NSNumber *magicNumber = @42;
NSNumber *unsignedNumber = @42u;
NSNumber *longNumber = @42l;

NSNumber *boolNumber = @YES;

NSNumber *simpleFloat = @3.14f;
NSNumber *betterDouble = @3.1415;

NSNumber *someChar = @'T';

Once we have NSNumber, we can convert to any format we need.
[magicNumber intValue];
[unsignedNumber unsignedIntValue];
[longNumber longValue];

[boolNumber boolValue];

[simpleFloat floatValue];
[betterDouble doubleValue];

[someChar charValue];

NSNumber can also work with NSInteger and NSUInteger types.

Represent Other Values Using Instances of the NSValue Class
The NSNumber class is itself a subclass of the basic NSValue class.

NSString *mainString = @"this is a long string";
NSRange substringRange = [mainString rangeOfString:@"long"];
NSValue *rangeValue = [NSValue valueWithRange:substringRange];

6.3 Most Collections Are Objects
NSArray, NSSet and NSDictionary

Any item I wish to add to a collection must be an instance of an Objective-C class. The collection classes use strong references to keep track of their contents, this means that any object that we add to a collection will be kept alive at least as long as the collection is kept alive.

The basic NSArray, NSSet and NSDictionary classes are immutable, which means their contents are set at creation.

Arrays Are Ordered Collections
There is no requirement for each object to be an instance of the same class in Arrays. And this Array is ordered.

Creating Arrays
NSArray *someArray = [NSArray arrayWithObjects: someObject, someString, someNumber, someValue, nil];

In this case, the someObject, someString, someNumber, someValue can not be nil.

Liberal Syntax
NSArray *someArray = @[firstObject, secondObject, thirdObject];

We do not need to use nil to terminate the list of objects and nil is an invalid value.

Querying Array Objects
number of objects
NSUInteger numberOfItems = [someArray count];

check contain
if([someArray containsObject:someString]) { …snip… }

get the first object
if([someArray count] > 0){
     NSLog(@"First item is: %@", [someArray objectAtIndex:0]);

if([someArray count] > 0){
     NSLog(@"First item is: %@", someArray[0]);

Sorting Array Objects

If we add a mutable string to an immutable array

NSMutableString *mutableString = [NSMutableString stringWithString:@"hello"];
NSArray *immutableArray = @[mutableString];

if([immutableArray count] > 0){
     id string = immutableArray[0]
     if([string isKindOfClass: [NSMutableString class]]){
          (string appendString: @" world");

If we plan to add or remove objects from an array, we need NSMutableArray

NSMutableArray *mutableArray = [NSMutable array];
[mutableArray addObject:@"gama"];
[mutableArray addObject:@"carl"];

[mutableArray replaceObjectAtIndex:0 withObject:@"austin"];

Sets Are unordered Collections
An NSSet is unordered group of distinct objects.

NSSet *simpleSet = [NSSet setWithObjects: @"hello, world", @42, aVaue, anObject, nil];

NSNumber *number = @42
NSSet *number = [NSSet setWithObjects: number, number, number, nil];

Dictionaries Collect Key-Value Paris
NSDirectory stores objects against given keys, which can then be used for retrieval.

Creating Dictionaries
NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                   someObject, @"anObject",
          @"hello, wold", @"hellotstring",
               @42, @"magicNumber",
Each object is specified before its key, and the list of objects and keys must be nil-terminated.

Literal Syntax
NSDictionary *dictionary = @{
          @"anObject" : someObject,
          @"hellostring" : @"hello, world",
          @"magicNumber": @42
          @"aValue": someValue

Querying Dictionaries
NSNumber *storedNumber = [dictionary[@"magicNumber"];

NSNumber *storeNumber = [dictionary objectForKey:@"magicNumber"];

Need to use NSMutableDictionary to add and remove objects.

[dictionary setObject:@"another string" forKey:@"secondstring"];
[dictionary removeObjectForKey:@"anObject" ];

Represent nil with NSNull
We can not add nil to collection classes. So we can use NSNull.

NSNull is a singleton, so NSNull null will always return the same instance.

NSArray *array = @[ @"string", @42, [NSNull null] ];

for(id object in array ){
     if(object == [NSNull null ]){
          NSLog(@"Found it");

6.4 Use Collections to Persist Your Object Graph
The NSArray and NSDictionary classes make it easy to write their contents directly to disk.

NSURL *fileURL = …
NSArray *array = @[@"first", @"second", @"third"];

BOOL success = [array writeToURL:fileURL atomically:YES];

If all the objects are one of the property list types(NSArray, NSDictionary, NSString, NSData, NSDate and NSNumber), we can recreate the entire hierarchy from disk.

NSURL *fileURL = …
NSArray *array = [NSArray arrayWithContentsOfURL:fileURL];

6.5 Use the Most Efficient Collection Enumeration Techniques
Fast Enumeration Makes it Easy to Enumerate a Collection
NSArray, NSSet and NSDictionary conform to the NSFastEnumeration protocol.

for(<Type> <variable> in <collection>) {


for(id eachObject in array){
     NSLog(@"Object: %@", eachObject);

for (NSString *eachKey in dictionary) {
     id object = dictionary[eachKey];
     NSLog(@"Object: %@ for key: %@", objet, eachKey);

Most Collections Also Support Enumerator Objects