This tutorial walks you through the fundamentals of Cocoa: XCode Tools, Interface Builder, Objective-C (variables, methods and memory management), and goes on to explain useful Cocoa principles for building an Image Resizer application: how to open and process files (using both a dialog screen and drag and drop), NSImage, messaging and saving.
Get the source code at http://visiblearea.com/blog/bin/view/VisibleArea/Image_Resizer_a_Cocoa_Tutorial
2. What we are going to create
What are
we going to
make?
3. What will you learn?
XCode Tools
Interface Builder
Objective-C
How to open and process files:
open dialog, drag on icon, drag on app
Extending classes
Image resizing
Messaging
Saving
27 May 2008 | Introduction to Cocoa | 3
17. Availability of UI objects
AppController.m
- (id)init
{
self = [super init];
if (self) {
NSLog(@quot;exportButton=%@quot;, exportButton);
}
returnself;
}
- (void)awakeFromNib
{
NSLog(@quot;exportButton=%@quot;, exportButton);
}
27 May 2008 | Introduction to Cocoa | 17
18. Selectors: setting the size textfield
AppController.m
- (void)awakeFromNib
{
[imageSizeText setStringValue:@quot;quot;];
}
- (IBAction)updateSliderValue:(id)sender
{
[imageSizeText setStringValue:[sender stringValue]];
}
27 May 2008 | Introduction to Cocoa | 18
19. Objective-C is C with extensions
object instance:
[NSMutableArray alloc]
pointer to object:
NSMutableArray* list;
list = [NSMutableArray alloc];
initialize object:
NSMutableArray* list;
list = [NSMutableArray alloc];
[list init];
shorthand:
NSMutableArray* list = [[NSMutableArray alloc] init];
destroy:
[list release];
27 May 2008 | Introduction to Cocoa | 19
20. Methods
method that takes an argument:
selector =addObject:
[list addObject:foo];
multiple arguments:
[list insertObject:foo atIndex:5];
selector =insertObject:atIndex:
return values:
int x = [list count];
27 May 2008 | Introduction to Cocoa | 20
21. Memory management with reference counting
allocates memory and returns object with retain count of 1
-alloc
at 0 the object is deallocated and the memory freed
makes a copy of an object, and returns it with retain count of 1
-copy
retain count ++
-retain
retain count --
-release
retain count = number of references to the object
decreases the reference count of an object by 1 at some stage in the future
-autorelease
NSMutableArray* list =
[[[NSMutableArray alloc] init] autorelease];
or:
[NSNumber numberWithInt:5];
convenience constructor, see:
+ (NSNumber *)numberWithInt:(int)value
Cocoa class methods return autoreleased objects
27 May 2008 | Introduction to Cocoa | 21
28. Set the app delegate in IB
27 May 2008 | Introduction to Cocoa | 28
29. Drag and drop onto the app window
We need to extend the image view.
Step 1: create a new subclass for
NSImageView: ImageView
Step 2: edit the code
@interface ImageView : NSImageView
{
}
Step 3: drag new .h file onto IB and set view to new subclass...
Step 4: add drag and drop methods...
27 May 2008 | Introduction to Cocoa | 29
30. Set image view to new subclass in IB
27 May 2008 | Introduction to Cocoa | 30
31. Drag and drop methods
ImageView.m
@implementation ImageView
#pragma mark Drag and drop
- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender
{
return NSDragOperationLink;
}
- (BOOL)prepareForDragOperation:(id<NSDraggingInfo>)sender
{
returnYES;
}
- (BOOL)performDragOperation:(id<NSDraggingInfo>)sender
{
return YES;
}
- (void)concludeDragOperation:(id<NSDraggingInfo>)sender
{
[super concludeDragOperation:sender];
}
@end
27 May 2008 | Introduction to Cocoa | 31
32. Testing: loading an image from the app bundle
Drag image on XCode: Resources
AppController.m
- (void)awakeFromNib
{
[imageSizeText setStringValue:@quot;quot;];
NSString* path = [[NSBundle mainBundle] pathForImageResource:@quot;anteprima.com.pngquot;];
[self importImageFromPath:path];
}
27 May 2008 | Introduction to Cocoa | 32
33. Show image in real size
Override NSImageView’s drawRect:
ImageView.m
- (void)drawRect:(NSRect)rect
{
if ([self image]) {
NSRect imageRect;
imageRect.origin = NSZeroPoint;
imageRect.size = [[self image] size];
NSRect drawRect = imageRect;
[[self image] drawInRect:drawRect
fromRect:imageRect
operation:NSCompositeSourceOver
fraction:1.0];
}
}
The image is now oriented bottom left.
27 May 2008 | Introduction to Cocoa | 33
34. Orient to top left
Flip coordinate system:
ImageView.m
- (BOOL)isFlipped
{
return YES;
}
27 May 2008 | Introduction to Cocoa | 34
35. Use a transformation to flip the image
Update drawRect in ImageView.m
- (void)drawRect:(NSRect)rect
{
if ([self image]) {
NSRect imageRect;
imageRect.origin = NSZeroPoint;
imageRect.size = [[self image] size];
NSAffineTransform* transform = [NSAffineTransform transform];
[transform translateXBy:0.0
yBy:1.0 * imageRect.size.height];
[transform scaleXBy:[zoomFactor floatValue]
yBy:-[zoomFactor floatValue]];
[transform concat];
NSRect drawRect = imageRect;
[[self image] drawInRect:drawRect
fromRect:imageRect
operation:NSCompositeSourceOver
fraction:1.0];
}
}
27 May 2008 | Introduction to Cocoa | 35
37. Connect the slider value to
the image size
Replace updateSliderValue in AppController.m
- (IBAction)updateSliderValue:(id)sender
{
[imageView setZoomFactor:[sender objectValue]];
}
Update drawRect in ImageView.m
[transform translateXBy:0.0
yBy:[zoomFactor floatValue] * imageRect.size.height];
27 May 2008 | Introduction to Cocoa | 37
39. Receiving the notification
Add toawakeFromNib inAppController.m
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleImageUpdated:)
name:@quot;imageUpdatedquot;
object:nil];
Unsubscribe before AppController is destroyed:
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[self setImageFilePath:nil];
[super dealloc];
}
Update the text field
- (void)handleImageUpdated:(NSNotification*)note
{
NSSize size = [[note object] sizeValue];
[imageSizeText setStringValue:[NSString stringWithFormat:@quot;%.0f x %.0fquot;, size.width, size.height]];
}
27 May 2008 | Introduction to Cocoa | 39
40. Update the text field when the image is loaded
Override tosetImage inImageView.m
- (void)setImage:(NSImage *)image
{
[super setImage:image];
[self notifyImageUpdated];
}
27 May 2008 | Introduction to Cocoa | 40
41. Update the file path when the image is dragged
Update concludeDragOperation in ImageView.m
- (void)concludeDragOperation:(id <NSDraggingInfo>)sender
{
[super concludeDragOperation:sender];
NSPasteboard *pboard = [sender draggingPasteboard];
NSString* draggedFilePath = nil;
if ( [[pboard types] containsObject:NSFilenamesPboardType] ) {
NSArray *files = [pboard propertyListForType:NSFilenamesPboardType];
draggedFilePath = [files objectAtIndex:0];
}
[[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];
[[NSNotificationCenter defaultCenter] postNotificationName:@quot;imageDraggedquot; object:draggedFilePath];
}
Register for notifications inAppController.m
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleImageDragged:)
name:@quot;imageDraggedquot;
object:nil];
- (void)handleImageDragged:(NSNotification*)note
{
NSString* imagePath = [note object];
[self setImageFilePath:imagePath];
}
27 May 2008 | Introduction to Cocoa | 41
42. Export the image: Categories
Categories are the prototypes of Cocoa.
Extend a class without subclassing
PrettyPrintCategory.h
@interface NSArray (PrettyPrintElements)
- (NSString *)prettyPrintDescription;
@end
PrettyPrintCategory.m
#import quot;PrettyPrintCategory.hquot;
@implementation NSArray (PrettyPrintElements)
- (NSString *)prettyPrintDescription {
// implementation code here...
}
@end
Create new Cocoa class ImageViewAdditions (m and h files)
27 May 2008 | Introduction to Cocoa | 42