Posts Tagged ‘objective-c’

iPhone Development and Code Reuse

Saturday, January 9th, 2010

Software development is a passion of mine. My honours thesis was on Software Reuse, something that all software developers should strive to do. During me research I was led down the path of many different technologies to do with software reuse. One of those particular technologies was Software Libraries.

My pain today has been trying to work out a software reuse procedure for iPhone development. In some ways I have been very unsuccessful, but un the end I believe I have worked out a reasonable way to do it. Note that I have googled many different searches and have usually come up with no help. There were a few good tutorials which have been useful, and I have derived my procedure based on these posts…

Library

Step One: Create the library project

For simplicity I will keep out the SVN related stuff. I am in the process of creating my post on Subversion integration with my projects, stay tuned.

Jump into xcode and create a new window based application, call it MyLibrary for example. This is actually useful as we can use the project to test our library code as well.

Step Two: Create the static library target

Right click on the “Targets” node in the xcode project list. Select “add -> New Target…”.

Choose the “Cocoa Touch” option on the right, and the “Static Library” icon in the left pane. Call it “libMyLibrary”. When the information screen comes up, change the “Product Name” to “MyLibrary”. (note this can be changed later by right clicking the target and choosing “get info”.)

Step Three: Create some classes

To test the library lets create a new class (in the Classes directory). Select the NSObject as the super class, call it “MyClass.m”, and add it to the new target (by clicking the check box next to the “libMyLibrary” target).

Add some simple code, first the header…

#import <Foundation/Foundation.h>
@interface MyClass : NSObject
{
}
+(void)hello;
@end
And of course the implementation...
#import "MyClass.h"
@implementation MyClass
+(void)hello
{
	NSLog(@"Hello");
}
@end

Save the files.

Step Four: export the header as public

In the “Targets” node in the right hand list, click the “libMyLibrary” node. The filelist will now have your MyClass.h and MyClass.m files. You need to change the “project” role next to the MyClass.h file to say “public”.

Step Five: done with the library

For the moment…

Client

Step One: Create the project

Call it “MyApp”. Any more need to be said?

Step Two: Create a reference in the application to your library

This is a slightly tricky step. Basically all you need to do is in your library project there is a list on the right hand side showing up the top your library (MyLibrary) and nodes beneth it with classes, resources etc. Click and drag the “MyLibrary” icon (right up the top) over to your new project, drop it at the same place (where it says MyApp). Make sure the “copy” checkbox is not checked (you do not want to copy it, you just want it referenced). Click Add.

You may notice that underneath the reference you just created there are two items, MyLibrary.app and libMyLibrary.a.

  • MyLibrary.app is your actual app. You can safely ignore this for the imported project
  • libMyLibrary.a is the static library.

You will notice these correspond to the targets in the MyLibrary app.

Step Three: Tell your code where the header files are (this is for code completion to work)

  • Right click the “MyApp” icon at the top of that right hand list, go down to “Get Info”.
  • Click the “Build” section. This will show all the build settings defined for your project. The list is very long, so we’ll use the search box to narrow down what we see. Type in “header search” in the search box.
  • The field we are looking to change is the “User Header Search Paths” option. Double click the blank area next to it (which will enable you to edit the paths).
  • Click the [+] button to add another path
  • Double click the new path blank area to type in the path you want

This is where you need to reference the actual path of your “MyLibrary” project. In my case I have used the same directory for both the MyApp and MyLibrary projects, so I can simply type into this field…

../MyLibrary/

Out of interest I also select the Recursive checkbox as well.

  • Close that window

Step Four: Start Coding

Open up the “MyAppAppDelgate.m” file. If you have added the header include path correctly you should be able to add the following at the top of the file (just under the #import “MyAppAppDelegate.h” statement)…

#import “MyC

… and you should now see the auto completion kick in and see the remainder of the line…

#import “MyClass.h

… Of course you should now complete the line (#import “MyClass.h”)

Next you can add the following line of code in the applicationDidFinishLoading function (which is created for you). Modify it to say this…

- (void)applicationDidFinishLaunching:(UIApplication *)application 
{    
    [MyClass hello];
    // Override point for customization after application launch
    [window makeKeyAndVisible];
}

Build and run. You should see “hello” on the console. That was from our original library code.

Step Five: Add a linker reference and build dependancy on the library

For those that are following step by step and are a little savy may notice that…

a) the items under the MyLibrary.xcodeproj (which are the targets for the MyLibrary project) are both red. And…

b) we haven’t built the library yet.

This was done on purpose as we want the library to be built as a dependency on the current project. Of course you may not want this as part of your build process, but I like to keep my code sane, so rebuilding often means I need to check and fix bugs often. Not a bad thing. But before we add this dependancy lets tell the linker to link against our static library, then we can add the build dependency.

  • open up the “Targets” node in the list in xcode
  • You will see the Link Binary with Libraries node.
  • Drag the “libMyLibrary.a” from our imported project into this node.

Now we are ready to add the build dependency.

  • Right-click the “Targets -> My App” node and go down to “Get Info”
  • Click on the General button, up the top of that screen you should see the option “Direct Dependencies” box.
  • Click the [+] button
  • Click the libMyLibrary target
  • Click the “Add Target” button
  • Close the window.

Step Six: Build and run the project

Try building the project now.

The simulator should run, and the words “Hello” should be written in the debug console. Success :)

You will also notice the “libMyLibrary.a” target in our imported project is now black – hence its been built.

Changes to the Library

You can now add another method to your MyClass, get it to do something else. Save it.

Head back to your client project, use the new method, build and run. The library should now be rebuilt and the new method available immediately for use.

Conclusion

This is about the easiest method I have found through my research today to create a library of reusable code for the iPhone. Why I am unable to create a framework to be used in an iPhone app is a bit of a loss to me (thank you Apple for making this so hard). In my opinion, to foster reuse of code, the ability to create a framework and add it to a project far outweighs the eleven steps outlined above. C’mon Apple.

Object Orientation, Objective-C Primer/Basics

Saturday, December 12th, 2009

Not that I am in any way an expert in Objective-C, but from the last week of looking at the language I think it would be beneficial to throw some thoughts I have on the language, and provide some technical information I have come across. My main reason for purchasing a Mac was to do iPhone development, but before I can dive into that I have to get familiar with Objective-C and a few other things.

The first thing I needed was the development kit available for free from the Apple website. Just register as a developer (for free of course) and download the tool. Included in this download is XCode (which is an IDE, the place that holds all your code and resources together), Interface Builder (click and drag for building GUI’s), and the standard frameworks (including COCOA, the framework we need to know).

I just mentioned the COCOA framework. I’ll be up front and say that I’m probably not technically correct calling COCOA a framework. In reality it is a group of frameworks, the major ones being the Foundation Framework, AppKit Framework and Core Data Framework. There are more, but these are the three main ones. This collection of frameworks provide all the useful classes you need to build Apple Mac/iPhone software.

  • Foundation Framework for providing base functionality.
  • AppKit Framework provides the user interface classes
  • Core Data Framework is essentially a persistance framework.

Although I cannot recommend the entire book yet, but so far I have been progressing through COCOA Programming For MAC OS X by Aaron Hillegass. So far I have found this to be an excellent read. Usually with technical books I end up skipping the first few chapters to get to the good stuff, but even from chapter one of this book I have been enthralled. The first chapter provides a very quick but amazingly informative overview of where the MAC OS and the COCOA framework have evolved from.

Coming from an Object-Oriented perspective I have found Objective-C to be quite easy to pickup, and so far I would have to say I am quite impressed with the language. I wish I had found this a long time ago! My background of Object-Oriented programming includes C++, Java, PHP, Python and JavaScript. Objective-C claims to be a mixture of pure C and SmallTalk.

What is this Object-Oriented programming I hear you ask? Basically it is a programming paradigm that models the creation of software on (real-life?) objects. For example, if you were to build an accounting system you may identify the following objects…

  • Documents
  • Journals
  • Ledgers
  • and of course… Accounts

These are of course a very high level of abstraction, they can all then be broken down into what is known as Sub-classes, a less abstract view of the system…

  • Documents can be specialised as…
    • Memos
    • Invoices
    • Purchases
    • Receipts
    • Cheques
    • etc
  • Journals can be specialised as…
    • Purchase Journal
    • Sales Journal
    • Cash Receipt Journal
    • General Journal
    • etc
  • Accounts can be specialised as …
    • Liabilities
    • Assets
    • Owner Equity
    • Revenue
    • Expense

And so on.

Each of these classifications (classes for short) can specify certain data and code that work together to define the class. The way of reaching the code in an object is usually described as calling a method or function on that object. Once the class is defined, then a software program can instantiate that class into an “Object”. Yes, we have gone the scenic route to get to this point :)

One of the neat things about Object-Orientation as a software paradigm is that you can put very general code into a Base class, and then create a specific class that extends from the base class, inheriting all the code and data that was in the base class, and then add more specialty code and data to it. Then you can specialise that code further but extending that class again and again until you have the most specialised class that is practical.

For example, following our Accounting example above, we may have a base class Document. The Document class will more than likely have an amount attached to it that is added to the system as a journal entry. But for record keeping we need to know more information. My design of such a system would include a class “Document”. It would have a piece of data attached to it which I would name “totalAmount”, which would be of type currency. I would probably have a method or to that could fetch and/or set that field, and another one which would fetch a description or summary of the document. I would probably write a method that returned “Generic Document” as the description of this class. As the Document class is very generic, I would decide to extend that class with different specialities of that base Document class, to provide more functionality, depending on the type of document that has been entered into the system.

The next class I would define would be the Receipt class. A receipt would extend the Document class, and in effect enable a receipt to also have a totalAmount available for an instance of this class. As this class inherits everything of its base class, if a piece of code asks for the objects description it will return “Generic Document”. Not a great idea, as we know it is a Receipt, so what we do is “Override” the description method to return a different message, “Receipt” for example. We may also add other data to this class if we wish, it might specify who the reciept was issued to, what products/services was involved etc.

Ok. Object-Orientation 101 completed. Although all the above is not 100% accurate for every language and system, the basic ideas are there. All we need now is away to get these idea’s into a software program. Enter Objective-C.

Objective-C uses “messages” to communicate between objects. So if you have an object, call it “weatherStationGoldCoast” and it has a method on it called “whatIsTheWeatherLike”. Say you also have another object, “airportSydney”. Somewhere, somehow in your software the AirportSydney object is executing code and needs to schedule a flight to the Gold Coast. Before it does this it would be a great idea to check to see what the weather is like at the Gold Coast to know if it will be safe to land the plane there. Easy! Simply ask the WeatherStationGoldCoast object by sending a message to the whatIsTheWeatherLike method. Finally some code…

// file: WeatherStation.h
#import 
@interface WeatherStation : NSObject
{
        // define data here
        (NSString *) stationName;
}
// define methods here
- (WeatherStation*) init : (NSString*) stationName;
- (NSString *) whatIsTheWeatherLike : (int)futureMintutes;
@end
// file: WeatherStation.m
#import "WeatherStation.h"
@implementation WeatherStation
- (WeatherStation*) init : (NSString*) stationName
{
	// do something useful here, like load up the station data for the stationName
}
-(NSString*)whatIsTheWeatherLike : (int)futureMintutes
{
	// this would normall go and get some real data, say from the BOM for a point of time in the future
	// lets just say the weather is always fair on the coast (one day soon I'm sure it will rain, but not yet)
	return @"fair";
}
@end
// file: Airport.h
#import 
@interface Airport : NSObject
{
}
-(BOOL) scheduleFlightTo: (NSString *)where
					when:(int)when; // how many minutes in the future to schedule the flight
-(void) scheduleFlight: (NSString* )where when:(int)when;
@end
// file: Airport.m
#import "Airport.h"
#import "WeatherStation.h"
@implementation Airport
-(BOOL) scheduleFlightTo: (NSString *)where when:(int)when
{
	// first we need to get the gold coast object - lets make one now
	WeatherStation* gcWeatherStation = [[WeatherStation alloc] init: @"GoldCoast"]; // first allocate memory, and then run the init method on that allocated object - two calls in one :)
	NSString* weather = [gcWeatherStation whatIsTheWeatherLike:when];
	if ([@"fair" isEqualToString:weather] == NO) return NO;
	[self scheduleFlight:where when:when]; // all is good, actually schedule it
	return YES;
}
-(void) scheduleFlight: (NSString *)where when:(int)when
{
}
@end
// file: main.m
#import 
#import "Airport.h"
int main(int argc, char *argv[])
{
	Airport* sydneyAirport = [[Airport alloc] init];
	BOOL result = [sydneyAirport scheduleFlightTo:@"GoldCoast" when:60]; // schedule flight in an hour
	if (result == YES) NSLog(@"Scheduled flight to the GoldCoast in 1 hour successfully");
	else NSLog(@"Flight cancelled - weather is no good");
	return 1;
}

Some important notes for this code…

Header files define the template, or the interface of your class (wrapped with @interface and @end). Identifies starting with the ampersat symbol (@) are Objective-C identifiers. Firstly your data is defined between braces, and then your methods are defined after that. The minus symbol (-) before the method name indicates it is an object instance method, where a plus symbol (+) indicates its a static class method. The type is then defined between parenthesis, followed by the method name and then the parameter list. The first parameter in the list only requires a type and a variable name, and may be followed by a space and further variables. The rest of the variables defines a message parameter name, followed by a colon (:) followed by the type in parenthesis and finally the variable name. The variable name is what we use in our method to reference that parameter. The message parameter name is what the caller uses to reference that variable. I see some similarities with Python in this respect (warning, subjective statement ahead…). I like it! Just like C this is followed by the semi-colon to say this is the end of the statement. Remember this is just the interface, the implementation will be in the .m file.

The .m files indicate Objective-C Files. They can be a mixture of Objective-C and straight C, in fact, Objective-C is a superset of C. All valid C code is valid Objective-C code. In this file the implementation of the class template in the header file is filled out between the @implementation and @end tags. The method header is exactly the same as in the .h files, without the semi-colon at the end, and with code beween following braces.

Objective-C code works by sending messages between objects. What is slightly different about Objective-C is that the messages may or may not get responded to. This is different to languages like Java for instance where if you call a method on an object, the compiler enforces that the method must exist, and return a correct data type. In Objective-C you can send any message you like, but if the method doesn’t exist, you wont get a response. This is very cool (note I come from using dynamically typed langages lately, python specifically). You will note that messages are sent to objects using brackets. For instance if I wish to allocate memory for an Airport object, then I can send the alloc message to it, hence [Airport alloc]. Once the memory is allocated we can then initialise the object, by sending it the init message. We can also roll it all into one, as you can see above. Note that its not considered good practice to nest more than two sets of brackets, it just gets messy (my argument with Scheme like languages is the same by the way). Calling a method with multiple parameters is almost as easy, just follow the message name with a colon and the list of parameters (separated by spaces). The first parameter isn’t named, but the other ones you use the name and value separated by colon’s. E.g. [{object} {message} : {firstparamter} {paramname}:{paramvalue} {paramname}:{paramvalue}].

Another couple of notes. NSString objects can be created easily by sitting the ampersat symbol in front of it, hence @”this is a NSString”. You will also notice i’ve used the NSLog statement to print it out to the screen. You can use printf() type statements if you wish, you just need to convert the NSString object into a cstring (look for the cStringUsingEncoding method on the NSString class).

I have no doubt left out some things, possibly even vital things. I am only just learning this myself and all the views expressed are my interpretation of things etc etc etc. I hope this is useful for someone, somewhere at some time.

#import
@interface Foo : NSObject
{
IBOutlet NSTextField *text;
}
- (IBAction) seed : (id) sender;
- (IBAction) generate : (id) sender;
- (void) doSeed;
- (int) doGenerate;
@end