Channels ▼
RSS

Embedded Systems

Java Meets Objective-C


I recently made the transition from writing enterprise Java applications to using Objective-C. I found that the transition would have been a lot easier had I the benefit of being able to find an article like this one.

So here I aim to help Java programmers quickly grasp the main features of Objective–C development. I will use a social networking application as an example to illustrate setting up a development environment for both languages. I’ll cover creating basic objects, comparing how the MVC design pattern works in both languages, and show you how data is stored and accessed in both languages.

iPhone Development: Where to Begin

To start developing iPhone apps, a Mac computer is required. The latest Mac OS X version 10.6 typically includes a copy of the Xcode IDE and suite of tools for developing iPhone software using Objective-C (see Figure 1).

[Click image to view at full size]
Figure 1: Xcode Development Environment, Project View.

In November 2010. Apple released the long-awaited SDK 4.2, which included a rich set of frameworks and features to build interactive iPhone apps. Xcode also contains a Simulator, which allows you to run your program and see how it would look on the device.

Objective-C is the main development language for iPhone apps. Luckily for Java developers, it is fully object-oriented and utilizes the same concepts as all other OO languages — inheritance, polymorphism, and encapsulation. To define a class (called "module" or .m file in Objective-C), you first have to define an interface (that is a header or .h file), and include it in your class implementation.

As an example, let’s look at a social networking application, which would allow you to stay in touch with your friends. A friend’s profile will be stored in memory as FriendProfile object. It’ll contain four fields: your friend’s name, city, country, and contact number; as in Listing One.

Listing One
//  FriendProfile.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface FriendProfile : NSObject {
}
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSString * country;
@property (nonatomic, retain) NSString * city;
@property (nonatomic, retain) NSString * phoneNbr;
@end
//FriendProfile.m
#import "FriendProfile.h"

@implementation FriendProfile
@synthesize name; 
@synthesize country; 
@synthesize city; 
@synthesize phoneNbr;
@end

In this example, interface FriendProfile : NSObject means that we define an interface called FriendProfile. It inherits its functionality from the base class called NSObject (colon notation specifies super class). NSObject is a root class that most Objective-C classes inherit from, similar to the Object class in Java. Next, we allocate in memory necessary variables of NSString type (equivalent to Java’s String class type) to store our friend’s data fields. The implementation class will then use @synthesize keyword to automatically create getter and setter methods. You can create the FriendProfile object as follows:

FriendProfile * profile = [[FriendProfile alloc] init];

Here, alloc and init act like the new keyword in Java, allocating FriendProfile object in memory. Next, you can assign some values to object fields.

[profile setName:@"Albert"];
[profile setCountry:@"USA"];
[profile setCity:@"Houston"];
[profile setPhoneNbr:@"123-456-789"];
Or, you can simply write:

profile.name = @"Albert";
profile.country = @"USA";
profile.city = @"Houston;
profile.phoneNbr = @"123-456-789";

To fully understand Objective-C syntax and features, read the excellent language reference on Apple’s developer site.

From Java

In Java, the FriendProfile class would be very similar to its Objective-C counterpart, see Listing Two:

Listing Two
package com.vo;

public class FriendProfile {
   private String name;
   private String country;
   private String city;
   private String phoneNbr;

   public String getName() {
      return name;
   }

   public void setName(String name) {
     this.name = name;
   }

   public String getCountry() {
      return country;
   }

   public void setCountry(String country) {
      this.country = country;
   }

   public String getCity() {
      return city;
   }

   public void setCity(String city) {
      this.city = city;
   }

   public String getPhoneNbr() {
      return phoneNbr;
   }

   public void setPhoneNbr(String phoneNbr) {
      this.phoneNbr = phoneNbr;
   }
}

Listing Two provides analogous fields, but getters and setters must be written out explicitly. Now let us see how we would add a new friend to our contact list (see Listing Three).

Listing Three 
public class FriendlyServletController extends HttpServlet {

	private static final long serialVersionUID = 1L;

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, 
	 * HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, 
                         HttpServletResponse response) 
              throws ServletException, IOException {
        doPost(request, response);
	}

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, 
     * HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, 
                          HttpServletResponse response) 
              throws ServletException, IOException {
		response.setContentType("text/html");
		PrintWriter out = response.getWriter();		

		final String action = 
		        request.getParameter("requestedAction"); 

		if (action==null || action.trim().length()==0){
			out.println("invalid action requested");
			return;
		}
		else 
		if (action.equalsIgnoreCase("addToContacts")){
			
		      	String name = request.getParameter("name");
			String country = request.getParameter("country");
			String city = request.getParameter("city");
			String phoneNbr = request.getParameter("phoneNbr");			
			//normally you have to validate browser-originated requests
			boolean validParameters = 
			        validateParameters(name, country, city, phoneNbr);
			if (validParameters==false){
				out.println(
				   "please verify and submit correct information");
				return;
			}
			
			FriendProfile newProfile = new FriendProfile();
			newProfile.setName(name);
			newProfile.setCountry(country);
			newProfile.setCity(city);
			newProfile.setPhoneNbr(phoneNbr);

			ProfileManager.getInstance().addToContacts(newProfile);
			out.println("Your friend is added to contacts");
			return;
		}
		else{
			out.println("invalid action requested");
			return;
		}		
	}
}

In this example, the FriendlyServletController class extends behavior from HTTPServlet, which is the Java server-side component class that processes requests coming from the browser. When a user logs in to your website and decides to add a friend, he would specify the data from the friend in HTML form fields. When a user submits the form, the Servlet receives and validates the request parameters and creates an object of FriendProfile type to store the data in memory. The ProfileManager class stores your FriendProfile object in the database.

MVC on the iPhone

The Model-View-Controller (MVC) design pattern frequently used in Java Web apps is present in iPhone development as well. If you look up the UIViewController class definition in the iOS Reference Library, you will see this: "UIViewController class provides the fundamental view-management model for iPhone applications…You use each instance of UIViewController to manage a view hierarchy." UIViewController is essentially a controller component that invokes business logic and updates a client’s view.

[Click image to view at full size]
Figure 2: Model-View-Controller Design Pattern.

When you create an object of UIViewController type in Xcode, you can choose to create it with an XIB file. This is a special type of Xcode file that defines the graphical user interface, or view, which can contain various controls such as buttons, table views, labels, etc.

Going back to our social networking example, suppose you have added several of your friends to the contact list. Now you would like to tap on a specific friend entry and see his detailed information. This functionality is achieved by defining our controller class as in Listing Four.

Listing Four
//  FriendProfileViewController.h

#import <UIKit/UIKit.h>

@class FriendProfile;
@class DatabaseController;
@class MFriendProfile;

// define our custom controller to inherit from
// the UIViewController class
@interface FriendProfileViewController : UIViewController {
	FriendProfile * profile;
	MFriendProfile * mprofile;
	DatabaseController *dbController;
}
@property(nonatomic, retain) IBOutlet UILabel *lname;
@property(nonatomic, retain) IBOutlet UILabel *lcountry;
@property(nonatomic, retain) IBOutlet UILabel *lcity;
@property(nonatomic, retain) IBOutlet UILabel *lphoneNbr;

-(IBAction)buttonPressed:(id)sender;
@end

#import "FriendProfileViewController.h"
#import "FriendProfile.h"
#import "DatabaseController.h"
#import "MFriendProfile.h"
@implementation FriendProfileViewController
...

// Implement viewDidLoad to do additional setup after 
// loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];	

	//create sample profile
	profile = [[FriendProfile alloc] init];
	profile.name = @"Albert"; 
	profile.country = @"USA"; 
	profile.city = @"Houston"; 
	profile.phoneNbr = @"123-456-789";

	//show profile on a screen
	lname.text = profile.name;
	lcountry.text = profile.country;
	lcity.text = profile.city;
	lphoneNbr.text = profile.phoneNbr;	

}

//call the model to bring friend information from database
-(IBAction)buttonPressed:(id)sender{
	NSLog(@"fetching friend profile by name.");
	// name is hardcoded for demo purposes. 
// Usually entered by user.
mprofile = (MFriendProfile*)
       [dbController getFriendProfileObjectbyName:@"Albert"]; 

	lname.text = mprofile.name;
	lcountry.text = mprofile.country;
	lcity.text = mprofile.city;
	lphoneNbr.text = mprofile.phoneNbr;
}

In this code, we create an instance of FriendProfileViewController and initialize it with our custom View Bundle, which is responsible for showing friend’s information.

Alloc and initWithNibName are methods used to instantiate the controller class. They are equivalent to Java's new keyword.

The Model kicks in when the view is actually loaded. Every controller has a few lifecycle methods inherited from the parent class. UIViewController. ViewdidLoad method is one of them. It's responsible for additional setup, after the view is loaded. It calls model to bring a friend’s information from the database and update the view. In the simplest case, our view will contain a series of labels, or objects of UILabel type, which can be set to any text (such as a friend’s name or phone number) at application runtime. The user immediately sees the friend's information updated.

MVC in Java

Next, I will illustrate how to show a friend’s details on a browser's screen using Java on the backend. Let's slightly modify our FriendlyServletController, which, in fact, is our Controller; see Listing Five:

Listing Five
import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.model.ProfileManager;
import com.vo.FriendProfile;

/**
 * Servlet implementation class FriendlyServletController
 */
public class FriendlyServletController extends HttpServlet {

   private static final long serialVersionUID = 1L;

   /**
    * @see HttpServlet#doGet(HttpServletRequest request, 
    * HttpServletResponse response)
    */
   protected void doGet(HttpServletRequest request, 
                        HttpServletResponse response) 
             throws ServletException, IOException {
      doPost(request, response);
   }

   /**
    * @see HttpServlet#doPost(HttpServletRequest request, 
	*      HttpServletResponse response)
    */
   protected void doPost(HttpServletRequest request, 
                         HttpServletResponse response) 
             throws ServletException, IOException {
      response.setContentType("text/html");
      PrintWriter out = response.getWriter();

      final String action = request.getParameter("requestedAction"); 

      if (action==null || action.trim().length()==0){
         out.println("invalid action requested");
         return;
      }
	  else if(action.equalsIgnoreCase("showFriendProfile")){
         String name = request.getParameter("name");
         FriendProfile existProfile = new FriendProfile();
         existProfile.setName(name);
         existProfile = 
		    ProfileManager.getInstance().lookupContact(existProfile);
         if (existProfile==null){
             out.println("profile was not found");
         }else{
             out.println("here is your contact information:" + 
			 existProfile.getName() + " from " + 
			 existProfile.getCity() + " in " + 
			 existProfile.getCountry() + " at " + 
			 existProfile.getPhoneNbr());
         }
         return;			
      }
      else if (action.equalsIgnoreCase("addToContacts")){
         String name = request.getParameter("name");
         String country = request.getParameter("country");
         String city = request.getParameter("city");
         String phoneNbr = request.getParameter("phoneNbr");

         //normally you have to validate browser-originated requests
         boolean validParameters = 
		    validateParameters(name, country, city, phoneNbr);
         if (validParameters==false){
            out.println("please verify and submit correct information");
            return;
         }

         FriendProfile newProfile = new FriendProfile();
         newProfile.setName(name);
         newProfile.setCountry(country);
         newProfile.setCity(city);
         newProfile.setPhoneNbr(phoneNbr);

         ProfileManager.getInstance().addToContacts(newProfile);
         out.println("Your friend is added to contacts");
         return;
      }
      else{
         out.println("invalid action requested");
         return;
      }
   }

   //basic parameter validation routine
   private boolean validateParameters(String name, String country, 
                                      String city, String phoneNbr){
      /basic validation to check if all parameters are sent
      if (name==null || name.trim().length()==0 || 
         country==null || country.trim().length()==0 || 
         city ==null || city.trim().length()==0 || 
         phoneNbr == null || phoneNbr.trim().length()==0){
         return false;
      }
      return true;
   }
}

In this example, FriendlyServletController receives the HTTP form-originated request for specific action called "showFriendProfile." Our model is a ProfileManager object that is responsible for looking up specific records from the database by friend name. A database record comes back to the Controller in the form of a FriendProfile object that contains friend-specific information. This information forms the View, which displays in the browser window.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video