iPhone Development

Just another iPhone Blog

Category Archives: Objective C

How to compare objects of your custom classes?

[This post is intended only for audiences with Basic knowledge in Objective-C]

With Cocoa / UIKit framework has built-in support for comparing objects like NSDate, NSString, NSData, NSNumber and few others which would help us to identify whether two objects are EQUAL, GREATER THAN or LESSER THAN the other object. This in-turn is used in cases like sorting, searching.

 

We would like to see how the same can be achieved for the custom classes we write, where we can specify the Equality condition by our own.

By default, NSObject class allows us to determine equality between two objects whose class is derived from NSObject through

isEqual: method,

where Apple documentation defines it as

This method defines what it means for instances to be equal. For example, a container object might define two containers as equal if their corresponding objects all respond YES to an isEqual: request. See the NSArray, NSDictionary, NSString and NSData class specifications for examples of the use of this method.

If two objects are equal, they must have the same hash value. This last point is particularly important if you define isEqual: in a subclass and intend to put instances of that subclass into a collection. Make sure you also define hash in your subclass.

 

 

In short, At NSObject (root class) level, two objects are said be equal

  • if their hash value are same
  • two objects have same address.

Well this may not be the case when we write our custom class,  for example,  two NSString objects might have different  pointer addresses, but have same string value. Hence, one must override hash method and isEqual: method of NSObject. NSString class would have hash and isEqual defined as below

– (NSUInteger)hash

{

//return the hash value generated from the string.

}

-(BOOL)isEqual:(id)otherObject

{

// return strcmp ( [self’s cString] , [otherObject’s cString] )

}

 

Where do I apply this?

Well, if you encounter a situation where you have an array (or in general collection) of Employees for eg, and you would want to remove an employee of particular ID, then you can do it with a single call like this. This would save you from writing an search algorithm.

Employee *employeeToRemove;

[myEmployees removeObject: employeeToRemove]; // assuming myEmployees is of type NSMutableArray

As Apple document says, removeObject and its variants (see below list for variants) would pick the object to remove for which isEqual: would return TRUE

  • – removeObject:
  • – removeObjectIdenticalTo:
  • – removeObjectIdenticalTo:inRange:
  • – removeObjectsInArray:
  • – indexOfObject:
  • – indexOfObject:inRange:
  • – indexOfObjectIdenticalTo:
  • – indexOfObjectIdenticalTo:inRange:

 

Another method that does fall in this category, is compare: method (actually you can give a custom name to this method ) whose signature is

-(NSComparisonResult)compare:(id)otherObject

NSComparisonResult is an enum with values  as below

enum {

NSOrderedAscending = -1,

NSOrderedSame,

NSOrderedDescending

};

 

With this method implemented in your Custom class (for example, Employee class), you can sort your objects in a collection (NSMutableArray , NSArray) with a single statement

[ myEmployee sortArrayUsingSelector(compare:)];

Other variants where this strategy can be used are

– sortedArrayUsingSelector:

– sortUsingSelector:

 

Hope this tutorial find useful for you.

Happy Coding 🙂

 

Building Objective-C static libraries with categories

I just came across the usage of Linker flag -all_load and -ObjC

Basically, this is used in situations where you build a static library with Categories. When this static library is linked with the actual implemenation / application that use this library, -ObjC linker flag would inform the compiler to load all the Objective C classes implementation.

However, since there is a linker bug that prevents -ObjC from loading objects files from static libraries that contain only categories, we should use -all_load or -force_Load Linker flags.

For More Details. See Apple Technical QA QA1490

Quick Tip : Initializing static variables of a class in Objective C

Initializes the receiver before it’s used (before it receives its first message).

 

+ (void)initialize


Discussion The runtime sends initialize to each class in a program exactly one time just before the class, or any class that inherits from it, is sent its first message from within the program. (Thus the method may never be invoked if the class is not used.) The runtime sends the initialize message to classes in a thread-safe manner. Superclasses receive this message before their subclasses.


[Reference : NSObject Class Reference]

You can place all your static member variable initialization code in this method as it guarantees it would be called only once BEFORE any method in that Class is invoked through any of its objects.

Happy Coding 🙂

%d bloggers like this: