Saturday, September 1, 2012

Debugging: unrecognized selector sent to instance

If you are a cocoa developer, you must be familiar with  "unrecognized selector sent to instance". And many number of times, it may have increased your caffeine intake :) . But in this post, we are going to see an elegant solution to pin point to the root cause of this message.

Suppose your console shows you the message:
-[MoneyWellAppDelegate doThatThingYouDo]: unrecognized selector sent to instance 0xa275230

Looking at the Xcode backtrace doesn't seem to help either, since it most likely looks like so:





At this point you start to hunt through your code, looking to see, who sent the -doThatThingYouDo message. You may find the answer right away or you may spend the next hour trying to figure out where that call is coming from.

The Elegant Way

The better way of finding out where the things have gone wrong is to pop over to the breakpoint navigator, click the + button at the bottom and choose Add Symbolic Breakpoint .

In the symbol field enter this symbol:

-[NSObject (NSObject) doesNotRecognizeSelector:]

Now when any instance of any object within your program is sent a message to which it does not respond, you will be presented with a backtrace that takes you right to the point where that message was sent.



So you see, easy peasy japanesey :)

CREDITS:

The original source of this blog post is here. The contents of this blog post have been published by the permission of the original author Michael Fey. Many thanks to Michael Fey for this wonderful post.

Sunday, August 5, 2012

Cocoa: Creating your own frameworks

This tutorial is about reusing your code by means of a framework. In this tutorial, we are going to learn, how to create frameworks in cocoa using Xcode and how can we use these frameworks in our applications.

All you need to know before going through this post is just the basic knowledge of objective - C and Xcode.

So, lets begin.

Creating a Framework

  1. Create a new project in Xcode using the Cocoa Framework template.


  2. Create a class which will contain your implementation

  3. Implement your methods in the yourClass.m file and declare them as well in the yourClass.h file as shown below:

    TestClass.h
    #import <Cocoa/Cocoa.h>

    @interface TestClass : NSObject
    +(void)showMessage;
    @end

    TestClass.m
    #import "TestClass.h"

    @implementation TestClass
    +(void)showMessage
    {
        NSLog(@"This is the MESSAGE");
    }
    @end

  4. To make the headers of yourClass available to the application developer, you need to mark the yourClass.h  file as public (which is specified as project by default) as shown in image below:

  5. Now, you need to set the Installation Directory  for your framework ( you can set it to any location you please but I prefer @executable_path/../Frameworks )

  6. Build your framework and you are good to go.

Using your framework in an Application

Now, lets see how we can use our framework in an application. For this purpose we will create a sample test application.

  1. Create an application using the cocoa application  template.

  2. Add the framework you just created in your application.

  3. Add a new Copy Files build phase.



  4. Use your framework's classes like any other class as shown below:

    AppDelegate.h
    #import <Cocoa/Cocoa.h>

    @interface AppDelegate : NSObject <NSApplicationDelegate>

    @property (assign) IBOutlet NSWindow *window;

    @end

    AppDelegate.m
    #import "AppDelegate.h"
    #import "TestFramework/TestClass.h"

    @implementation AppDelegate
    @synthesize window = _window;
    - (void)dealloc
    {
        [super dealloc];
    }

    - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
    {
        // Insert code here to initialize your application
        [TestClass showMessage];
    }

    @end


    And VOILA......


Please do leave your comments behind.

Wednesday, July 18, 2012

Cocoa memory management: Tips and Tricks

This post covers some tips for novice programmers that can be helpful if you are not using ARC and are managing the memory yourself. For this post, I assume, that you are familiar with memory management and related methods ( retain, alloc, release ... etc ). So lets begin:

Using Anonymous Objects

It is pretty common for the developers to use anonymous objects and a newbie programmer can unknowingly leak memory while using them as shown in the example below:

[[NSMenuItem alloc]initWithTitle:[[NSString alloc] initWithString:@"xyz"] action:@selector(selector:) keyEquivalent:@""];

In the code above, we are trying to create a new menu item, which requires a NSString as one of its arguments and we are creating the string there and then. As we can see that we are using alloc to create the
string, the retain count of this string is being incremented from 0 to 1. But we wont be able to release it because we have no reference to it. Hence, this statement is leaking memory.

So, lets rectify this statement:

[[NSMenuItem alloc]initWithTitle:[[[NSString alloc] initWithString:@"xyz"]autorelease] action:@selector(selector:) keyEquivalent:@""];

By using autorelease while creating a string, the autorelease pool will make sure that this string won't be released for a minimum of 1 event loop cycle (so we can use it without worrying) and after that, autorelease pool will also make sure that this string is released in the near future.

Using Notifications

Although using notifications is not directly related to memory management, but I feel it is worth mentioning.
When you register to receive a  notification, the notification center creates a weak reference to your object. Now suppose, you have registered an object as observer with the notification center to receive a notification and at some point of time, the observer has been released and ceases to exist, the notification center will be unaware of this release as it holds only a weak reference of the object. So, the notification center will keep on sending notifications to that object even if does not exist. So, we should notify the notification center that the object no longer exists.

So, ideally when you register for a notification, you must un-register for that notification in -(void)dealloc; or at some other appropriate place.

Thursday, April 5, 2012

Building a COCOA application: The Basics

In this tutorial we are going to learn building a basic application in cocoa. Before building the application I assume that the reader is familiar with the following:

Prerequisites

  • Familiarity with XCode.
  • Basic knowledge of Objective-C (Data Types, messages, properties etc..)
  • Introductory knowledge of cocoa ( XIB/NIB Files, Outlets, Actions etc.. )
  • Knowledge of MVC (Mode-View-Controller) architecture ( You can get familiar with MVC here )
Setting Up The Development Environment

Here is what we are going to use for this tutorial:
  • Operating System:  Mac OS X ( Lion - Version 10.7.3 )
  • XCode: XCode 4.2
  • GCC: GCC 4.2

Lets Begin
Before starting with the development lets see what are we going to build today and the major steps that we are going to perform during the whole development process. Below is the goal we want to achieve today.


We would be creating and application "USD Converter". The user will provide the exchange rate for USD and the number or dollars to convert. As the user press "Convert" button, the application would multiply the exchange rate with number of dollars to provide the amount in other currency in the third text box.

The major steps we are going to follow are:

  1. Create the View for the application.
  2. Implement the Model (business logic) for our application.
  3. Create a Controller class.
  4. Connect Controller and View.


Create View for the Application

So lets begin by creating a new XCode project as shown below:


We will be selecting to create a Cocoa Application. Once we have created the project we will have to open the Xib file.




Now Xib file will be containing the view of our application. Below is the step by step procedure to create the View for our application:

Steps:



  1. Open the xib file using Xcode 4.2
  2. Click on the "Window" object so as to display the window as it would look in our application.
        
  3. Drag a new "Label" object from the object library and place it at appropriate position in the window.
            
  4. Drag a "Text Field" object from the object library and position it in front of the label applied in step 3.
        
  5. As shown in steps 3 and 4,  add another pair of label and text field object as shown in image below
       
  6. Add a "Horizontal Line" object so as to separate out the upper and lower region of the window (just for the sake of beautification)
     
  7. Add another set of label and text field object below the horizontal line similar to step 5.
      
  8. Add a "Push Button" object from object library to be used as the "Convert" button.
     
  9. Set the initialFirstResponder outlet of the window. The initialFirstResponder outlet defines on which  control the cursor will be when the application loads initially.
  10. Set "nextKeyView" outlet for each of the Text Field. The "nextKeyView" outlet defines on which control the cursor move next, when the user presses the <TAB> key.
  11. Similarly set the nextKeyView of the 2nd text field to the 3rd text field.

AND.....

Now we have the view for our application.

Implementing the Model

Now we have the view but we still need to write the business logic behind our application. We will write this business logic in the model class. So now lets begin with the implementing the model class:

  • Add new Objective-C class to your project and name it as modelClass. This will add two files, modelClass.h and  modelClass.m file.
  • Now lets analyze what do we need in our modelClass: When the "Convert" button is pressed we would want our model class to get two float values corresponding to "Exchange Rate per USD" and "Dollars to convert"and return a float value containing the value corresponding to "Amount in other currency".
  • So below is the code for modelClass.h file:

    #import <Foundation/Foundation.h>

    @interface modelClass : NSObject{
        float convertedAmount;  //variable to hold the converted amount
    }
    @property (readonly) float convertedAmount;
    //method to convert USD to other currency
    -(float)convertCurrency:(float)USD:(float)exchangeRate; 
    @end


  • We have declared a method "convertCurrency" which would take the number of dollars to convert and the exchange rate as arguments and return the float value of the converted amount.
  • Now lets see the implementation file modelClass.m : 

    #import "modelClass.h"

    @implementation modelClass
    @synthesize convertedAmount;
    -(float)convertCurrency:(float)USD:(float)exchangeRate{
        convertedAmount = USD * exchangeRate;
        return convertedAmount;
    }
    @end

  • Above is the implementation of the convertCurrency method. As we can see, this method calculates the converted value by multiplying its arguments and sets the result in variable convertedAmount and returns the same.
So, now we have the view as well as the model for our application. Now all we need to complete our application is the controller, which we will come to know below.

Creating the Controller Class

Once we have the view and the model, they must be connected, and this connection is taken care by the controller class. We will add a new class to our project namely "controllerClass"whose code is shown below:

controllerClass.h


#import <Foundation/Foundation.h>

#import "modelClass.h"



@interface controllerClass : NSObject{

    modelClass *modelObject;

    IBOutlet NSTextField *exchangeRateField;

    IBOutlet NSTextField *dollarsToConvertField;

    IBOutlet NSTextField *finalAmountField;

}

-(id)init;

-(IBAction)convertAction:(id)sender;

@end


controllerClass.m

#import "controllerClass.h"



@implementation controllerClass

-(id)init{

    self = [super init];

    modelObject = [[modelClass alloc]init];

    return self;

}

-(IBAction)convertAction:(id)sender{

    float exchangeRate,dollars,finalAmount;

    exchangeRate = [exchangeRateField floatValue]; //Get value from text field

    dollars = [dollarsToConvertField floatValue];  //Get value from text field



    //call method from modelClass to calculate final amount
    finalAmount = [modelObject convertCurrency:dollars :exchangeRate]; 
    [finalAmountField setFloatValue:finalAmount];  //Set the final amount in text field
}
@end




  • As we can see above in the controllerClass.h file, we will need to have 3 outlets -  each corresponding to a text field in view and we would need 1 action corresponding to the convert button.
  • When the user presses the Convert button, it would call the -(IBAction)convertAction:(id)sender action, which will read values from text fields and call the method of "modelClass" so as to convert the value into the other currency. So, the controllerClass would need an object of modelClass (as can be seen in the code above).
Connect the View with the Controller

Now lets see how will we connect the view with the controller. To accomplish this follow the below mentioned steps:
  1. Open the Xib file with Xcode 4.2.
  2. Drag-Drop the "Object" from the object library to the left pane of the interface builder as shown in the image below.

  3. Select the newly added object from the left pane and click on the  "Identity Inspector" on the right top and change the "Class" of the object to "controllerClass" as shown in image below. Now, the object you added in step 2 belongs to the class controllerClass.

  4. Right Click on the object of controllerClass, it will show the outlets and actions you defined in controllerClass.

  5. Connect the outlets to corresponding text fields and the action to the Convert button.









    And now your application is all set to go. 
    Build and Run it and have fun with your first cocoa creation.


    Friday, January 6, 2012

    Automate tasks in Selenium using Python: Setting Up the Environment

    This post demonstrates setting up the environment to use Selenium as automation tool via python. I will be demonstrating the whole process on Windows 7.

    Steps:

    1. Install JDK: We would need to install jdk as a prerequisite to the eclipse IDE which we would be using to write the python code. You can find jdk here
    2. Install Eclipse: I would prefer to use the Eclipse Helios. You can find the installer here.
    3. Install Python: We would be using python-2.7 for this tutorial. However you are free to use any version. You can find the python installer here.
    4. Install SetupTools: This will provide you with EasyInstall which would be useful later on. You can find SetupTools corresponding to your python version at this location
    5. Create a new Environment Variable in your system with Name "EASY_INSTALL" and value "<install_path_for_python>\Scripts".  You can find out how to create an environment variable here CREATING ENVIRONMENT VARIABLES.
    6. Add this newly created environment variable to your PATH environment variable by appending "%EASY_INSTALL%" (without inverted commas :) ) to it.
    7. Open Command Prompt and type the command

                         C:\> easy_install pip
    8. Then run the command below at command prompt:

                        C:\> pip install selenium
    9. Setup Eclipse for Python: Now we need to setup our eclipse so that we can use it to code in python. You can set up your eclipse as shown in this blog post Setting Up Eclipse.

      WARNING: In the blog post  Setting Up Eclipse  mentioned above. You would need to slightly modify the instructions in STEP-2(c) . The modification will be:

      In the field "Work with:" you should use the URL:  http://update-production-pydev.s3.amazonaws.com/pydev/updates/site.xml instead of the URL shown ( http://pydev.org/updates/)
    10. Download Selenium Server:  You can download the selenium server form the official website here.
    11. Run the Selenium Server: You can run the selenium server jar at command prompt using the command:

                       C:\> java -jar <path_to_jar_file>
    AND YOU ARE GOOD TO GO..................!!!!!! Now you have the environment to automate your tasks in selenium using python. Enjoy!! :)