Mathieu Tozer's Dev Blog

Cocoa, the development of Words, and other software projects (including those dang assessment tasks).




Cocoa Workshop Day 1


E-mail this post



Remember me (?)



All personal information that you provide here will be governed by the Privacy Policy of Blogger.com. More...



Here's today's source code. It's full of comments that note what was said about each topic.
At a higher level, we learnt about creating custom classes and about using them with Foundation.
We covered memory management.

Steps to create a class:
1. Instance Variable declarations
2. getters, setters
3. description method (Use auto scripts)
4. pragma marks
5. initialiser methods
6. class methods too for initialisation
7. deallocate
8. Add things that represent the class' data in different ways.

#import

#import "PointData.h"
#import "Person.h"
//we couldn't use @class here because you need the method names.
//we use this instead of include. This means it's only included once. gives us all those things that make programming easier.


int main (int argc, const char * argv[]) { //standard c entry point.


/*this is where it starts looking different!*/
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; //this is required for mem managemnt in the command line project

//Lesson 4
// Person *p = [[Person alloc] initWithFirstName: @"Mathieu" surname:@"Tozer"];
Person *p = [[Person personWithFirstName:@"Mary" surname:@"Janes"] retain]; //Person is now effectively like a factory object. RETAIN it so that we're sure it will stick around until we conciously release it. That little doggy will wantder away - out of the autorelease pool if we don't put a leash on it!

[p setEmailAddress:@"email@mathieutozer.com"];

NSString *fullName = [p fullName];

NSLog(@"Full Name: %@", fullName);

NSLog(@"name = %@", p);

[p release];
// [fullName release]; We don't need this because an we used stringWith... in the fullName method - it implements autorelease. We would have ended up with 'double free' error from malloc.

// //creates the actual memory with alloc, and then creates the actual instance with init. This is then assigned to an
//
// // Lesson 1
// NSString * myName = @"Mathieu";
// int count =1234;
// NSLog(@"Hello, World!"); //the @ sign refers to a literal string. It's NSString short hand @"" We use it sometimes for psuedo debugging.
// NSLog(@" My Name is %@, %d", myName, count);
//
// //Lesson 2 - Strings and formatters.
// NSString * formattedString = [NSString stringWithFormat:@"%@ %d", myName, count];
// //You can create strings with a format, which is very handy for constructing strings.
// NSLog(@"%@", formattedString);
//
// //Lesson 3 - Classes and objects
// PointData * pd = [[PointData alloc] init];
// [pd setX: 1.2];
// [pd setY: 4.5];
// NSLog(@"(x,y) = (%f, %f)", [pd x], [pd y]);
// NSLog(@"%@", pd); //because we have implemented 'descriptoin' this will print something meaningful, not just a memory address.
//
// [pd release];
// pd = nil; //this is to stop the object pointing to deallocated memory so we don't blow the computer up later down the track
[pool release]; //release the pool. We've created memory, and now we're releas123ing it.
return 0;
}



/* Notes
Objective-C doesn't have a garbage collector.
build containts the bilds and the executable for the project

drwxr-xr-x 4 cocoa06 cocoa06 4096 Jul 5 09:21 build
-rw-r--r-- 1 cocoa06 cocoa06 3132 Jul 5 09:21 firstProject2.1
-rw-r--r-- 1 cocoa06 cocoa06 801 Jul 5 09:30 firstProject2.m
drwxr-xr-x 2 cocoa06 cocoa06 4096 Jul 5 09:22 firstProject2.xcodeproj <- This is actually a DIRECTORY!
-rw-r--r-- 1 cocoa06 cocoa06 168 Jul 5 09:21 firstProject2_Prefix.pch

You can have documents that are in fact folders in the Mac environment. Things can be hidden behind a document facade. Quite handy really.

The executable file is in debug!
As opposed to release.
We can have different settings for the debug and release.
Choose release and hit buld and it will be built in a release folder. There will be some warnings that we'll discuss later.

Objective-C is designed for you to be a bit more verbose than you usually might be.
you put the label right beside the variable.
You write the method name in a way to describe the first varable.

To make things a bit more confusing, you can just call C functions too.
That's the interesting thing about having a language that is a superset of another language.

Language additions:
id
This is similar to a void* We can let it be assigned to any object. A very dynamic language, and it encourages that.
self
This is an OO concept.
@interface and @inplementation are like block indicators. Used when defining a class.
@protocol allows you to define a series of methods that you would like an interface to adopt.
You can use this to say something like "This class MUST implement mouseDown.

@class
You use this to tell a class that there will be an object of this kind somewhere at runtime - then you can use them and their methods.
These cannot access instance variables.
+(id)createNewObject:
+(id)createObjectOfSize:(int)size;
These are class methods that cannot access instance varables. You'd use these when you're creating factory objects.

In fact, IBAction and IBOutlet aren't part of Objective-C. They're used by interface builder to figure out what goes where.

We can turn on warnings. gcc is very much in the background of Xcode.
We can also look at the actual textual input output of gcc from within the application (the little texty looking button).

NSString *list = @"wrenches, hammers, saws";
NSArray *listItems = [list componentsSeparatedByString:@", "];

This method is handy for parsing!!!

What we've learnt today....
alloc -> rc = 1
release => rc= rc+1
retain => rc = rc +1
autorelease => rc = rc -1 disposed of "later" NSAutoreleasePool

You have to match these up
alloc copy retain
----
release autorelease
*/

//
// PointData.h
// firstProject2
//
// Created by , on 5/07/06.
// Copyright 2006 __MyCompanyName__. All rights reserved.
//

#import
/*!
@class
@abstract Stores a point
@discussion A point contains an x y value
*/ //This is a script to auto generate documentation

//single inheritance - one class only!!
@interface PointData : NSObject {
//member variables
float x;
float y;
}
//methods - in order to get access to x and y.
//so we have this concept called accessors, these give us the ability to get and set the variable.

//the convention is to just ask for the variable name. This is also to enable some of Apple's automatic stuff. Handy.
-(float)x;
-(void)setX:(float)value;
-(float)y;
-(void)setY:(float)value;

//returns a string that contains a description Good practice to define them here so that your code is readable.
- (NSString *) description; //Pretty print!

//There, now we have an interface that gives us access our variables.


@end

//Use split views to have imp and inter in the same window.
//Command / comments whole highlighed blocks
//K for compile!


//Sometimes you can't see the warnings, like incomplete implementation of a method. You should check the Errors and Warnings section of Xcode for these.

//
// PointData.m
// firstProject2
//
// Created by , on 5/07/06.
// Copyright 2006 __MyCompanyName__. All rights reserved.
//

#import "PointData.h"

#pragma mark Accessors
@implementation PointData

-(float)x{
return x;
}
-(void)setX:(float)value{
x = value;
}
-(float)y{
return y;
}
-(void)setY:(float)value{
y = value;
}

//returns a string that contains a description
- (NSString *) description{
return [NSString stringWithFormat: @"(%f, %f)", [self x], [self y]]; //this returns an object which is a string. It is an autorelease object
}
@end


//
// Person.h
// firstProject2
//
// Created by , on 5/07/06.
// Copyright 2006 __MyCompanyName__. All rights reserved.
//

#import


@interface Person : NSObject {
NSString *first;
NSString *surname;
NSString *emailAddress;

}
+ (Person *) personWithFirstName: (NSString *) aFirstName surname:(NSString *)aSurname;
- (id)initWithFirstName: (NSString *) aFirstName surname:(NSString *)aSurname;
- (NSString *)firstName;
- (void)setFirstName:(NSString *)aName;
- (NSString *)surname;
- (void)setSurname:(NSString *)aName;
- (NSString *)emailAddress;
- (void)setEmailAddress:(NSString *)aEmailAddress;

-(NSString *)fullName;

@end

//
// Person.m
// firstProject2
//
// Created by , on 5/07/06.
// Copyright 2006 __MyCompanyName__. All rights reserved.
//

#import "Person.h"


@implementation Person

#pragma mark Class Methods
//Lesson 5 This is the neatest way of initialising objects.
+ (Person *) personWithFirstName: (NSString *) aFirstName surname:(NSString *)aSurname {
Person * p;
p = [[Person alloc] initWithFirstName:aFirstName surname:aSurname];
return [p autorelease]; //we want to release it, but we want it to stick around for a bit!
}

#pragma mark Initialisers
// designated initialiser
- (id)initWithFirstName: (NSString *) aFirstName surname:(NSString *)aSurname{
self = [super init];
if(nil!= self){
[self setFirstName:aFirstName];
[self setSurname:aSurname];
}
return self;
}

- (id) init {
self = [super init];
if (nil != self) {
[self setFirstName:@""];
[self setSurname:@""];
[self setEmailAddress:@""];
}
return self;
}
#pragma mark Dealloc
- (void) dealloc {
[first release];
[surname release];
[emailAddress release];
[super dealloc]; //not super release!! You'd release NSOject!!
}

#pragma mark Accessors
- (NSString *)firstName{
return [[first retain] autorelease];
}
- (void)setFirstName:(NSString *)aName{
if (first != aName){
[first release];
first = [aName copy]; //see notes in moleskein about why this is so. You need to make a copy, rather than pointing to the original object
}
}
- (NSString *)surname{
return [[surname retain] autorelease]; //retain youself! But autorelease yourself later ;-) There's a balance here - we're not actually changing the net value of it's retain count at all! Up one, then a little later down one. The reciever can do what he wants with it (usually retain).
}
- (void)setSurname:(NSString *)aName{
//what if aName and surname are actually pointing to the same object?? Then we have to check
if (surname != aName){
[surname release];
surname = [aName copy]; //see notes in moleskein about why this is so. You need to make a copy, rather than pointing to the original object
}
}

- (NSString *)emailAddress{
return [[emailAddress retain] autorelease];
}
- (void)setEmailAddress:(NSString *)aEmailAddress{
if(emailAddress != aEmailAddress){
[emailAddress release];
emailAddress = [aEmailAddress copy];
}
}

#pragma mark String Operations
-(NSString *)fullName{
return [NSString stringWithFormat:@"%@ %@", [self firstName], [self surname]]; //we're taking advantage of the fact that this is already autoreleased.
}

- (NSString *)description{
return [NSString stringWithFormat: @"first=%@ surname=%@ emailAddress=%@",
[self firstName],
[self surname],
[self emailAddress]];
}


@end


#import
#import "Person.h"

int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];


//NSArray *myArray = [[NSArray arrayWithObjects:@"One", @"Two", @"Three", nil] retain]; //we're passing arbitary objects into the array. Just string 'em up!
//when an object is passed to an array, NSArray is retaining the object
//If you want programattic control, then you can use an NSMutableArray
NSMutableArray * myMutableArray = [NSMutableArray array];
//NSDictionary *fontAttributes = [NSDictionary dictionaryWithObject:[NSNumber numberWithDouble:12.0] forKey:@"MyNumber"];//when we want to write pretty strings to the screen, we need to pass font attributes


int i;
Person *p = [Person personWithFirstName:@"Mathieu" surname:@"Tozer"];
Person *q = [[Person alloc] initWithFirstName:@"Carlo" surname:@"Marasea"];
for(i=0; i<10; i++){
NSString *str = [NSString stringWithFormat: @"cocoa %d", i];
[myMutableArray addObject:str];
if (i == 5){
[myMutableArray addObject:p];
[myMutableArray addObject:q];
[q release];
q =nil;
}
// [myMutableArray addObject:[[str copy] autorelease]]; if you want to put a copy in - otherwise ARRAYS ARE RETAINING.
}
[myMutableArray addObject:[NSNumber numberWithFloat:3.7348]]; //we need a wrapper to store the data. Seems like baggage, but when we come to things like saving, this will make our lives a whole lot easier.

NSEnumerator *e = [myMutableArray objectEnumerator]; //so now there is an object that will allow us to enumerate the array
id obj;
while(obj = [e nextObject]) { //we are deliberately assigning the objects of the array to obj
if([obj isKindOfClass:[NSNumber class]]){
NSLog(@"number found >>>>>> %@", obj);
}
else{
NSLog(@"%@", obj);
}
}

// insert code here...

[pool release];
return 0;
}


//leart how to do auto code completion which reduces errors, and also allows me to think at a conceptually higher level than was previously possible.


0 Responses to “Cocoa Workshop Day 1”

Leave a Reply

      Convert to boldConvert to italicConvert to link

 


+RSS | dev blog | Portfolio

About me

My status

Previous posts

  • my del.icio.us
  • my flickr