Objective-C – Useful Resources ”; Previous Next The following resources contain additional information on Objective C. Please use them to get more in-depth knowledge on this topic. Useful Video Courses Understanding S.M.A.R.T. Objectives 19 Lectures 1 hours PARTHA MAJUMDAR More Detail Econometrics For Dummies: Learn The Basic 20 Lectures 51 mins Pedro Planas More Detail Master Creating Well-Defined Marketing Objectives in 30 mins 6 Lectures 25 mins Ken Burke More Detail Build Landing Page Design for Higher Sales & Lead Generation 20 Lectures 1.5 hours Being Commerce More Detail Build Landing Page Optimization for higher conversion rate 20 Lectures 1.5 hours Being Commerce More Detail RECRUITMENT: IT basics for IT Recruiters Featured 61 Lectures 5 hours Valeria Frisch More Detail Print Page Previous Next Advertisements ”;
Category: objective C
Obj-C – Memory Management
Obj-C Memory Management ”; Previous Next Memory management is one of the most important process in any programming language. It is the process by which the memory of objects are allocated when they are required and deallocated when they are no longer required. Managing object memory is a matter of performance; if an application doesn”t free unneeded objects, its memory footprint grows and performance suffers. Objective-C Memory management techniques can be broadly classified into two types. “Manual Retain-Release” or MRR “Automatic Reference Counting” or ARC “Manual Retain-Release” or MRR In MRR, we explicitly manage memory by keeping track of objects on our own. This is implemented using a model, known as reference counting, that the Foundation class NSObject provides in conjunction with the runtime environment. The only difference between MRR and ARC is that the retain and release is handled by us manually in former while its automatically taken care of in the latter. The following figure represents an example of how memory management work in Objective-C. The memory life cycle of the Class A object is shown in the above figure. As you can see, the retain count is shown below the object, when the retain count of an object becomes 0, the object is freed completely and its memory is deallocated for other objects to use. Class A object is first created using alloc/init method available in NSObject. Now, the retain count becomes 1. Now, class B retains the Class A”s Object and the retain count of Class A”s object becomes 2. Then, Class C makes a copy of the object. Now, it is created as another instance of Class A with same values for the instance variables. Here, the retain count is 1 and not the retain count of the original object. This is represented by the dotted line in the figure. The copied object is released by Class C using the release method and the retain count becomes 0 and hence the object is destroyed. In case of the initial Class A Object, the retain count is 2 and it has to be released twice in order for it to be destroyed. This is done by release statements of Class A and Class B which decrements the retain count to 1 and 0, respectively. Finally, the object is destroyed. MRR Basic Rules We own any object we create: We create an object using a method whose name begins with “alloc”, “new”, “copy”, or “mutableCopy” We can take ownership of an object using retain: A received object is normally guaranteed to remain valid within the method it was received in, and that method may also safely return the object to its invoker. We use retain in two situations − In the implementation of an accessor method or an init method, to take ownership of an object we want to store as a property value. To prevent an object from being invalidated as a side-effect of some other operation. When we no longer need it, we must relinquish ownership of an object we own: We relinquish ownership of an object by sending it a release message or an autorelease message. In Cocoa terminology, relinquishing ownership of an object is therefore typically referred to as “releasing” an object. You must not relinquish ownership of an object you do not own: This is just corollary of the previous policy rules stated explicitly. #import <Foundation/Foundation.h> @interface SampleClass:NSObject – (void)sampleMethod; @end @implementation SampleClass – (void)sampleMethod { NSLog(@”Hello, World! n”); } – (void)dealloc { NSLog(@”Object deallocated”); [super dealloc]; } @end int main() { /* my first program in Objective-C */ SampleClass *sampleClass = [[SampleClass alloc]init]; [sampleClass sampleMethod]; NSLog(@”Retain Count after initial allocation: %d”, [sampleClass retainCount]); [sampleClass retain]; NSLog(@”Retain Count after retain: %d”, [sampleClass retainCount]); [sampleClass release]; NSLog(@”Retain Count after release: %d”, [sampleClass retainCount]); [sampleClass release]; NSLog(@”SampleClass dealloc will be called before this”); // Should set the object to nil sampleClass = nil; return 0; } When we compile the above program, we will get the following output. 2013-09-28 04:39:52.310 demo[8385] Hello, World! 2013-09-28 04:39:52.311 demo[8385] Retain Count after initial allocation: 1 2013-09-28 04:39:52.311 demo[8385] Retain Count after retain: 2 2013-09-28 04:39:52.311 demo[8385] Retain Count after release: 1 2013-09-28 04:39:52.311 demo[8385] Object deallocated 2013-09-28 04:39:52.311 demo[8385] SampleClass dealloc will be called before this “Automatic Reference Counting” or ARC In Automatic Reference Counting or ARC, the system uses the same reference counting system as MRR, but it inserts the appropriate memory management method calls for us at compile-time. We are strongly encouraged to use ARC for new projects. If we use ARC, there is typically no need to understand the underlying implementation described in this document, although it may in some situations be helpful. For more about ARC, see Transitioning to ARC Release Notes. As mentioned above, in ARC, we need not add release and retain methods since that will be taken care by the compiler. Actually, the underlying process of Objective-C is still the same. It uses the retain and release operations internally making it easier for the developer to code without worrying about these operations, which will reduce both the amount of code written and the possibility of memory leaks. There was another principle called garbage collection, which is used in Mac OS-X along with MRR, but since its deprecation in OS-X Mountain Lion, it has not been discussed along with MRR. Also, iOS objects never had garbage collection feature. And with ARC, there is no use of garbage collection in OS-X too. Here is a simple ARC example. Note this won”t work on online compiler since it does not support ARC. #import <Foundation/Foundation.h> @interface SampleClass:NSObject – (void)sampleMethod; @end @implementation SampleClass – (void)sampleMethod { NSLog(@”Hello, World! n”); } – (void)dealloc { NSLog(@”Object deallocated”); } @end int main() { /* my first program in Objective-C */ @autoreleasepool { SampleClass *sampleClass = [[SampleClass alloc]init]; [sampleClass sampleMethod]; sampleClass = nil; } return 0; } When we compile the above program, we will get the following output. 2013-09-28 04:45:47.310 demo[8385] Hello, World! 2013-09-28
Objective-C – Categories
Objective-C Categories ”; Previous Next Sometimes, you may find that you wish to extend an existing class by adding behavior that is useful only in certain situations. In order add such extension to existing classes, Objective-C provides categories and extensions. If you need to add a method to an existing class, perhaps, to add functionality to make it easier to do something in your own application, the easiest way is to use a category. The syntax to declare a category uses the @interface keyword, just like a standard Objective-C class description, but does not indicate any inheritance from a subclass. Instead, it specifies the name of the category in parentheses, like this − @interface ClassName (CategoryName) @end Characteristics of Category A category can be declared for any class, even if you don”t have the original implementation source code. Any methods that you declare in a category will be available to all instances of the original class, as well as any subclasses of the original class. At runtime, there”s no difference between a method added by a category and one that is implemented by the original class. Now, let”s look at a sample category implementation. Let”s add a category to the Cocoa class NSString. This category will make it possible for us to add a new method getCopyRightString which helps us in returning the copyright string. It is shown below. Live Demo #import <Foundation/Foundation.h> @interface NSString(MyAdditions) +(NSString *)getCopyRightString; @end @implementation NSString(MyAdditions) +(NSString *)getCopyRightString { return @”Copyright TutorialsPoint.com 2013″; } @end int main(int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; NSString *copyrightString = [NSString getCopyRightString]; NSLog(@”Accessing Category: %@”,copyrightString); [pool drain]; return 0; } Now when we compile and run the program, we will get the following result. 2013-09-22 21:19:12.125 Categories[340:303] Accessing Category: Copyright TutorialsPoint.com 2013 Even though any methods added by a category are available to all instances of the class and its subclasses, you”ll need to import the category header file in any source code file where you wish to use the additional methods, otherwise you”ll run into compiler warnings and errors. In our example, since we just have a single class, we have not included any header files, in such a case we should include the header files as said above. Print Page Previous Next Advertisements ”;
Objective-C – Protocols
Objective-C Protocols ”; Previous Next Objective-C allows you to define protocols, which declare the methods expected to be used for a particular situation. Protocols are implemented in the classes conforming to the protocol. A simple example would be a network URL handling class, it will have a protocol with methods like processCompleted delegate method that intimates the calling class once the network URL fetching operation is over. A syntax of protocol is shown below. @protocol ProtocolName @required // list of required methods @optional // list of optional methods @end The methods under keyword @required must be implemented in the classes that conforms to the protocol and the methods under @optional keyword are optional to implement. Here is the syntax for class conforming to protocol @interface MyClass : NSObject <MyProtocol> … @end This means that any instance of MyClass will respond not only to the methods declared specifically in the interface, but that MyClass also provides implementations for the required methods in MyProtocol. There”s no need to redeclare the protocol methods in the class interface – the adoption of the protocol is sufficient. If you need a class to adopt multiple protocols, you can specify them as a comma-separated list. We have a delegate object that holds the reference of the calling object that implements the protocol. An example is shown below. Live Demo #import <Foundation/Foundation.h> @protocol PrintProtocolDelegate – (void)processCompleted; @end @interface PrintClass :NSObject { id delegate; } – (void) printDetails; – (void) setDelegate:(id)newDelegate; @end @implementation PrintClass – (void)printDetails { NSLog(@”Printing Details”); [delegate processCompleted]; } – (void) setDelegate:(id)newDelegate { delegate = newDelegate; } @end @interface SampleClass:NSObject<PrintProtocolDelegate> – (void)startAction; @end @implementation SampleClass – (void)startAction { PrintClass *printClass = [[PrintClass alloc]init]; [printClass setDelegate:self]; [printClass printDetails]; } -(void)processCompleted { NSLog(@”Printing Process Completed”); } @end int main(int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; SampleClass *sampleClass = [[SampleClass alloc]init]; [sampleClass startAction]; [pool drain]; return 0; } Now when we compile and run the program, we will get the following result. 2013-09-22 21:15:50.362 Protocols[275:303] Printing Details 2013-09-22 21:15:50.364 Protocols[275:303] Printing Process Completed In the above example we have seen how the delgate methods are called and executed. Its starts with startAction, once the process is completed, the delegate method processCompleted is called to intimate the operation is completed. In any iOS or Mac app, we will never have a program implemented without a delegate. So its important we understand the usage of delegates. Delegates objects should use unsafe_unretained property type to avoid memory leaks. Print Page Previous Next Advertisements ”;
Objective-C Dynamic Binding ”; Previous Next Dynamic binding is determining the method to invoke at runtime instead of at compile time. Dynamic binding is also referred to as late binding. In Objective-C, all methods are resolved dynamically at runtime. The exact code executed is determined by both the method name (the selector) and the receiving object. Dynamic binding enables polymorphism. For example, consider a collection of objects including Rectangle and Square. Each object has its own implementation of a printArea method. In the following code fragment, the actual code that should be executed by the expression [anObject printArea] is determined at runtime. The runtime system uses the selector for the method run to identify the appropriate method in whatever class of anObject turns out to be. Let us look at a simple code that would explain dynamic binding. Live Demo #import <Foundation/Foundation.h> @interface Square:NSObject { float area; } – (void)calculateAreaOfSide:(CGFloat)side; – (void)printArea; @end @implementation Square – (void)calculateAreaOfSide:(CGFloat)side { area = side * side; } – (void)printArea { NSLog(@”The area of square is %f”,area); } @end @interface Rectangle:NSObject { float area; } – (void)calculateAreaOfLength:(CGFloat)length andBreadth:(CGFloat)breadth; – (void)printArea; @end @implementation Rectangle – (void)calculateAreaOfLength:(CGFloat)length andBreadth:(CGFloat)breadth { area = length * breadth; } – (void)printArea { NSLog(@”The area of Rectangle is %f”,area); } @end int main() { Square *square = [[Square alloc]init]; [square calculateAreaOfSide:10.0]; Rectangle *rectangle = [[Rectangle alloc]init]; [rectangle calculateAreaOfLength:10.0 andBreadth:5.0]; NSArray *shapes = [[NSArray alloc]initWithObjects: square, rectangle,nil]; id object1 = [shapes objectAtIndex:0]; [object1 printArea]; id object2 = [shapes objectAtIndex:1]; [object2 printArea]; return 0; } Now when we compile and run the program, we will get the following result. 2013-09-28 07:42:29.821 demo[4916] The area of square is 100.000000 2013-09-28 07:42:29.821 demo[4916] The area of Rectangle is 50.000000 As you can see in the above example, printArea method is dynamically selected in runtime. It is an example for dynamic binding and is quite useful in many situations when dealing with similar kind of objects. Print Page Previous Next Advertisements ”;
Objective-C Fast Enumeration ”; Previous Next Fast enumeration is an Objective-C”s feature that helps in enumerating through a collection. So in order to know about fast enumeration, we need know about collection first which will be explained in the following section. Collections in Objective-C Collections are fundamental constructs. It is used to hold and manage other objects. The whole purpose of a collection is that it provides a common way to store and retrieve objects efficiently. There are several different types of collections. While they all fulfill the same purpose of being able to hold other objects, they differ mostly in the way objects are retrieved. The most common collections used in Objective-C are − NSSet NSArray NSDictionary NSMutableSet NSMutableArray NSMutableDictionary If you want to know more about these structures, please refer data storage in Foundation Framework. Fast enumeration Syntax for (classType variable in collectionObject ) { statements } Here is an example for fast enumeration. Live Demo #import <Foundation/Foundation.h> int main() { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; NSArray *array = [[NSArray alloc] initWithObjects:@”string1″, @”string2″,@”string3″,nil]; for(NSString *aString in array) { NSLog(@”Value: %@”,aString); } [pool drain]; return 0; } Now when we compile and run the program, we will get the following result. 2013-09-28 06:26:22.835 demo[7426] Value: string1 2013-09-28 06:26:22.836 demo[7426] Value: string2 2013-09-28 06:26:22.836 demo[7426] Value: string3 As you can see in the output, each of the objects in the array is printed in an order. Fast Enumeration Backwards for (classType variable in [collectionObject reverseObjectEnumerator] ) { statements } Here is an example for reverseObjectEnumerator in fast enumeration. Live Demo #import <Foundation/Foundation.h> int main() { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; NSArray *array = [[NSArray alloc] initWithObjects:@”string1″, @”string2″,@”string3″,nil]; for(NSString *aString in [array reverseObjectEnumerator]) { NSLog(@”Value: %@”,aString); } [pool drain]; return 0; } Now when we compile and run the program, we will get the following result. 2013-09-28 06:27:51.025 demo[12742] Value: string3 2013-09-28 06:27:51.025 demo[12742] Value: string2 2013-09-28 06:27:51.025 demo[12742] Value: string1 As you can see in the output, each of the objects in the array is printed but in the reverse order as compared to normal fast enumeration. Print Page Previous Next Advertisements ”;
Command-Line Arguments
Command-Line Arguments ”; Previous Next It is possible to pass some values from the command line to your Objective-C programs when they are executed. These values are called command line arguments and many times they are important for your program, especially when you want to control your program from outside instead of hard coding those values inside the code. The command line arguments are handled using main() function arguments where argc refers to the number of arguments passed, and argv[] is a pointer array, which points to each argument passed to the program. Following is a simple example, which checks if there is any argument supplied from the command line and take action accordingly − Live Demo #import <Foundation/Foundation.h> int main( int argc, char *argv[] ) { if( argc == 2 ) { NSLog(@”The argument supplied is %sn”, argv[1]); } else if( argc > 2 ) { NSLog(@”Too many arguments supplied.n”); } else { NSLog(@”One argument expected.n”); } } When the above code is compiled and executed with a single argument, say “testing”, it produces the following result. 2013-09-13 03:01:17.333 demo[7640] The argument supplied is testing When the above code is compiled and executed with two arguments, say testing1 and testing2, it produces the following result. 2013-09-13 03:01:18.333 demo[7640] Too many arguments supplied. When the above code is compiled and executed without passing any argument, it produces the following result. 2013-09-13 03:01:18.333 demo[7640] One argument expected It should be noted that argv[0] holds the name of the program itself and argv[1] is a pointer to the first command-line argument supplied, and *argv[n] is the last argument. If no arguments are supplied, argc will be one, otherwise if you pass one argument, then argc is set at 2. You pass all the command line arguments separated by a space, but if argument itself has a space, then you can pass such arguments by putting them inside double quotes “” or single quotes ””. Let us re-write above example once again where we will print program name and we also pass a command-line argument by putting inside double quotes − Live Demo #import <Foundation/Foundation.h> int main( int argc, char *argv[] ) { NSLog(@”Program name %sn”, argv[0]); if( argc == 2 ) { NSLog(@”The argument supplied is %sn”, argv[1]); } else if( argc > 2 ) { NSLog(@”Too many arguments supplied.n”); } else { NSLog(@”One argument expected.n”); } return 0; } When the above code is compiled and executed with a single argument separated by space but inside double quotes say “Testing1 Testing2”, it produces the following result. 2017-11-30 06:36:59.081 main[71010] Program name main 2017-11-30 06:36:59.082 main[71010] One argument expected. Print Page Previous Next Advertisements ”;
Objective-C – Log Handling
Objective-C Log Handling ”; Previous Next NSLog method In order to print logs, we use the NSLog method in Objective-C programming language which we have used right from the Hello World example. Let us look at a simple code that would print the words “Hello World” − Live Demo #import <Foundation/Foundation.h> int main() { NSLog(@”Hello, World! n”); return 0; } Now, when we compile and run the program, we will get the following result. 2013-09-16 00:32:50.888 demo[16669] Hello, World! Disabling logs in Live apps Since the NSLogs we use in our application, it will be printed in logs of device and it is not good to print logs in a live build. Hence, we use a type definition for printing logs and we can use them as shown below. Live Demo #import <Foundation/Foundation.h> #if DEBUG == 0 #define DebugLog(…) #elif DEBUG == 1 #define DebugLog(…) NSLog(__VA_ARGS__) #endif int main() { DebugLog(@”Debug log, our custom addition gets printed during debug only” ); NSLog(@”NSLog gets printed always” ); return 0; } Now, when we compile and run the program in debug mode, we will get the following result. 2013-09-11 02:47:07.723 demo[618] Debug log, our custom addition gets printed during debug only 2013-09-11 02:47:07.723 demo[618] NSLog gets printed always Now, when we compile and run the program in release mode, we will get the following result. 2013-09-11 02:47:45.248 demo[3158] NSLog gets printed always Print Page Previous Next Advertisements ”;
Objective-C – Posing
Objective-C Posing ”; Previous Next Before starting about Posing in Objective-C, I would like to bring to your notice that posing was declared deprecated in Mac OS X 10.5 and it”s not available for use thereafter. So for those who are not concerned about these deprecated methods can skip this chapter. Objective-C permits a class to wholly replace another class within a program. The replacing class is said to “pose as” the target class. For the versions that supported posing, all messages sent to the target class are instead received by the posing class. NSObject contains the poseAsClass − method that enables us to replace the existing class as said above. Restrictions in Posing A class may only pose as one of its direct or indirect superclasses. The posing class must not define any new instance variables that are absent from the target class (though it may define or override methods). The target class may not have received any messages prior to the posing. A posing class can call overridden methods through super, thus incorporating the implementation of the target class. A posing class can override methods defined in categories. #import <Foundation/Foundation.h> @interface MyString : NSString @end @implementation MyString – (NSString *)stringByReplacingOccurrencesOfString:(NSString *)target withString:(NSString *)replacement { NSLog(@”The Target string is %@”,target); NSLog(@”The Replacement string is %@”,replacement); } @end int main() { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; [MyString poseAsClass:[NSString class]]; NSString *string = @”Test”; [string stringByReplacingOccurrencesOfString:@”a” withString:@”c”]; [pool drain]; return 0; } Now when we compile and run the program in a older Mac OS X (V_10.5 or earlier), we will get the following result. 2013-09-22 21:23:46.829 Posing[372:303] The Target string is a 2013-09-22 21:23:46.830 Posing[372:303] The Replacement string is c In the above example, we just polluted the original method with our implementation and this will get affected throughout all the NSString operations with the above method. Print Page Previous Next Advertisements ”;
Objective-C – Extensions
Objective-C Extensions ”; Previous Next 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 class is compiled at the same time as the class extension). The methods declared by a class extension are implemented in the implementation block for the original class, so you can”t, for example, declare a class extension on a framework class, such as a Cocoa or Cocoa Touch class like NSString. Extensions are actually categories without the category name. It”s often referred as anonymous categories. The syntax to declare a extension uses the @interface keyword, just like a standard Objective-C class description, but does not indicate any inheritance from a subclass. Instead, it just adds parentheses, as shown below − @interface ClassName () @end Characteristics of Extensions An extension cannot be declared for any class, only for the classes that we have original implementation of source code. An extension is adding private methods and private variables that are only specific to the class. Any method or variable declared inside the extensions is not accessible even to the inherited classes. Extensions Example Let”s create a class SampleClass that has an extension. In the extension, let”s have a private variable internalID. Then, let”s have a method getExternalID that returns the externalID after processing the internalID. The example is shown below and this wont work on online compiler. #import <Foundation/Foundation.h> @interface SampleClass : NSObject { NSString *name; } – (void)setInternalID; – (NSString *)getExternalID; @end @interface SampleClass() { NSString *internalID; } @end @implementation SampleClass – (void)setInternalID { internalID = [NSString stringWithFormat: @”UNIQUEINTERNALKEY%dUNIQUEINTERNALKEY”,arc4random()%100]; } – (NSString *)getExternalID { return [internalID stringByReplacingOccurrencesOfString: @”UNIQUEINTERNALKEY” withString:@””]; } @end int main(int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; SampleClass *sampleClass = [[SampleClass alloc]init]; [sampleClass setInternalID]; NSLog(@”ExternalID: %@”,[sampleClass getExternalID]); [pool drain]; return 0; } Now when we compile and run the program, we will get the following result. 2013-09-22 21:18:31.754 Extensions[331:303] ExternalID: 51 In the above example, we can see that the internalID is not returned directly. We here remove the UNIQUEINTERNALKEY and only make the remaining value available to the method getExternalID. The above example just uses a string operation, but it can have many features like encryption/decryption and so on. Print Page Previous Next Advertisements ”;