0% found this document useful (0 votes)
275 views45 pages

Introduction To Cocoa Programming For Macosx: Arthur Clemens

This document provides an introduction to Cocoa programming for Mac OS X. It will cover Xcode tools, Interface Builder, Objective-C, opening and processing files, extending classes, messaging, saving files, and more. The presentation will demonstrate creating a simple Cocoa application to open, display, and resize images using Xcode, Interface Builder, and Objective-C. It will also cover memory management, drag and drop functionality, and subclassing NSImageView.
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
275 views45 pages

Introduction To Cocoa Programming For Macosx: Arthur Clemens

This document provides an introduction to Cocoa programming for Mac OS X. It will cover Xcode tools, Interface Builder, Objective-C, opening and processing files, extending classes, messaging, saving files, and more. The presentation will demonstrate creating a simple Cocoa application to open, display, and resize images using Xcode, Interface Builder, and Objective-C. It will also cover memory management, drag and drop functionality, and subclassing NSImageView.
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 45

Introduction to

Cocoa
Programming for
Mac OS X
Arthur Clemens
27 May 2008 - Amsterdam
What we are going to create
What are
we going
to make?
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


XCode Tools

 http://developer.apple.com/

27 May 2008 | Introduction to Cocoa | 4


New application

27 May 2008 | Introduction to Cocoa | 5


XCode interface

27 May 2008 | Introduction to Cocoa | 6


Interface builder

27 May 2008 | Introduction to Cocoa | 7


Drag and drop the interface

27 May 2008 | Introduction to Cocoa | 8


Create AppController class

“AppController”

27 May 2008 | Introduction to Cocoa | 9


Instantiate AppController

27 May 2008 | Introduction to Cocoa | 10


Adding outlets

27 May 2008 | Introduction to Cocoa | 11


Adding actions

27 May 2008 | Introduction to Cocoa | 12


Setting properties

27 May 2008 | Introduction to Cocoa | 13


Make connections

27 May 2008 | Introduction to Cocoa | 14


Creating files

ctrl-drag

27 May 2008 | Introduction to Cocoa | 15


Testing UI output

AppController.m

- (IBAction)exportImage:(id)sender
{
NSLog(@"export:%@", sender);
}

- (IBAction)updateSliderValue:(id)sender
{
NSLog(@"updateSliderValue:%f", [sender floatValue]);
}

27 May 2008 | Introduction to Cocoa | 16


Availability of UI objects

AppController.m

- (id)init
{
self = [super init];
if (self) {
NSLog(@"exportButton=%@", exportButton);
}
return self;
}

- (void)awakeFromNib
{
NSLog(@"exportButton=%@", exportButton);
}

27 May 2008 | Introduction to Cocoa | 17


Selectors: setting the size textfield

AppController.m

- (void)awakeFromNib
{
[imageSizeText setStringValue:@""];
}

- (IBAction)updateSliderValue:(id)sender
{
[imageSizeText setStringValue:[sender
stringValue]];
}

27 May 2008 | Introduction to Cocoa | 18


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


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


Memory management with reference counting
-alloc allocates memory and returns object with retain count of 1
at 0 the object is deallocated and the memory freed
-copy makes a copy of an object, and returns it with retain count of 1

-retain retain count ++

-release retain count --


retain count = number of references to the object
-autorelease decreases the reference count of an object by 1 at some stage in the future

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


Member variables: storing the image file path
AppController.h

@interface AppController : NSObject{


IBOutlet NSTextField *imageSizeText;
IBOutlet NSImageView *imageView;
IBOutlet NSButton *exportButton;
IBOutlet NSSlider *slider;
NSString* imageFilePath;
}
- (void)setImageFilePath:(NSString*)newFilePath;

AppController.m

- (void)setImageFilePath:(NSString*)newFilePath
{
[newFilePath retain];
[imageFilePath release];
imageFilePath = newFilePath;
}
- (NSString*)imageFilePath
{
return imageFilePath;
}
- (void)dealloc
{
[self setImageFilePath:nil];
[super dealloc];
}
Very simple rules for memory management in Cocoa
http://www.stepwise.com/Articles/Technical/2001-03-11.01.html
27 May 2008 | Introduction to Cocoa | 22
Opening an image file in a dialog window
AppController.m

- (IBAction)showOpenPanel:(id)sender
{
NSOpenPanel *op = [NSOpenPanel openPanel];
[op beginSheetForDirectory:nil
file:nil
types:[NSImage imageFileTypes]
modalForWindow:[NSApp mainWindow]
modalDelegate:self
didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:)
contextInfo:nil];
}
- (void)openPanelDidEnd:(NSOpenPanel *)op only PNG:
returnCode:(int)returnCode
[NSArray arrayWithObject:@"png"]
contextInfo:(void *)ci
PNG and GIF:
{
[NSArray
if (returnCode != NSOKButton) return;
arrayWithObjects:@"png",@"gif",nil]
NSString *path = [op filename];
}

AppController.h

- (IBAction)showOpenPanel:(id)sender; ... and update the NIB file

27 May 2008 | Introduction to Cocoa | 23


Connecting the menu in IB

27 May 2008 | Introduction to Cocoa | 24


Putting the image into the view
AppController.m

- (BOOL)importImageFromPath:(NSString*)path
{
NSImage *image = [[[NSImage alloc] initWithContentsOfFile:path] autorelease];
if (!image) return NO;
[imageView setImage:image];
return YES;
}

Update:

- (void)openPanelDidEnd:(NSOpenPanel *)op
returnCode:(int)returnCode
contextInfo:(void *)ci
{
if (returnCode != NSOKButton) return;
NSString *path = [op filename];
[self importImageFromPath:path];
[self setImageFilePath:path];
}

27 May 2008 | Introduction to Cocoa | 25


Opening the image file when dragging on app icon
Step 1: add code

AppController.m

- (BOOL)application:(NSApplication *)theApplication
openFile:(NSString *)path
{
// do a check on filetype here...
BOOL result = [self importImageFromPath:path];
if (!result) return NO;
[self setImageFilePath:path];
return YES;
}

Step 2: edit app document types...

Step 3: set the File’s Owner delegate...

27 May 2008 | Introduction to Cocoa | 26


Opening target info

Command-i

27 May 2008 | Introduction to Cocoa | 27


Set the app delegate in IB

27 May 2008 | Introduction to Cocoa | 28


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


Set image view to new subclass in IB

27 May 2008 | Introduction to Cocoa | 30


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
{
return YES;
}
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
{
return YES;
}
- (void)concludeDragOperation:(id <NSDraggingInfo>)sender
{
[super concludeDragOperation:sender];
}

@end

27 May 2008 | Introduction to Cocoa | 31


Testing: loading an image from the app bundle
Drag image on XCode: Resources

AppController.m

- (void)awakeFromNib
{
[imageSizeText setStringValue:@""];
NSString* path = [[NSBundle mainBundle]
pathForImageResource:@"anteprima.com.png"];
[self importImageFromPath:path];
}

27 May 2008 | Introduction to Cocoa | 32


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


Orient to top left
Flip coordinate system:

ImageView.m

- (BOOL)isFlipped
{
return YES;
}

27 May 2008 | Introduction to Cocoa | 34


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


Store zoom factor in image view
ImageView.h

@interface ImageView : NSImageView {


NSNumber* zoomFactor;
}

ImageView.m

- (void)setZoomFactor:(NSNumber*)newZoomFactor
{
[newZoomFactor retain];
[zoomFactor release];
zoomFactor = newZoomFactor;
[self setNeedsDisplay:YES];
}
- (void)dealloc
{
[self setZoomFactor:nil];
[super dealloc];
}
- (id)initWithFrame:(NSRect)frame {
if (![super initWithFrame:frame]) {
return nil;
}
[self setZoomFactor:[NSNumber numberWithFloat:1]];
return self;
}

27 May 2008 | Introduction to Cocoa | 36


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


Getting the image size
Using NSNotification messages

ImageView.m

- (void)notifyImageUpdated
{
[[NSNotificationCenter defaultCenter] postNotificationName:@"imageUpdated"
object:[self
imageSize]];
}
- (NSValue*)imageSize
{
NSSize imageSize = [[self image] size];
imageSize.width *= [zoomFactor floatValue];
imageSize.height *= [zoomFactor floatValue];
return [NSValue valueWithSize:imageSize];
}

Add to setZoomFactor:

[self notifyImageUpdated];

27 May 2008 | Introduction to Cocoa | 38


Receiving the notification
Add to awakeFromNib in AppController.m
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleImageUpdated:)
name:@"imageUpdated"
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:@"%.0f x %.0f",
size.width, size.height]];
}

27 May 2008 | Introduction to Cocoa | 39


Update the text field when the image is loaded
Override to setImage in ImageView.m
- (void)setImage:(NSImage *)image
{
[super setImage:image];
[self notifyImageUpdated];
}

27 May 2008 | Introduction to Cocoa | 40


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:@"imageDragged"
object:draggedFilePath];
}

Register for notifications in AppController.m


[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleImageDragged:)
name:@"imageDragged"
object:nil];

- (void)handleImageDragged:(NSNotification*)note
{
NSString* imagePath = [note object];
[self setImageFilePath:imagePath];
}

27 May 2008 | Introduction to Cocoa | 41


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 "PrettyPrintCategory.h"

@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


A category on NSImageView
ImageViewAdditions.h

@interface NSImageView (ImageViewAdditions)


- (NSImage*)imageOfSize:(NSSize)size;
@end

ImageViewAdditions.m

@implementation NSImageView (ImageViewAdditions)

- (NSImage*)imageOfSize:(NSSize)size
{
NSImage* sourceImage = [self image];
NSRect scaledRect;
scaledRect.origin = NSZeroPoint;
scaledRect.size.width = size.width;
scaledRect.size.height = size.height;
NSImage* copyOfImage = [[[NSImage alloc] initWithSize:size] autorelease];
[copyOfImage lockFocus];
[[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];
[sourceImage drawInRect:scaledRect
fromRect:NSZeroRect
operation:NSCompositeSourceOver
fraction:1.0];
[copyOfImage unlockFocus];
return copyOfImage;
}

@end

27 May 2008 | Introduction to Cocoa | 43


Export the image
In AppController.m:
- (IBAction)exportImage:(id)sender
{
NSSize size = [[imageView imageSize] sizeValue];
NSString* path = [self createFilePath:imageFilePath
size:size];
NSImage* imageCopy = [imageView imageOfSize:size];
[self saveImage:imageCopy
toPath:path];
}

- (NSString*)createFilePath:(NSString*)imageFilePath size:(NSSize)size
{
NSString *pathExtension = [imageFilePath pathExtension];
NSString* barePath = [imageFilePath stringByDeletingPathExtension];
return [NSString stringWithFormat:@"%@_%.0fx%.0f.png", barePath, size.width, size.height];
}

- (BOOL)saveImage:(NSImage*)image toPath:(NSString*)path
{
NSData *imageAsData = [image TIFFRepresentation];
NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithData:imageAsData];
NSData* fileData = [imageRep representationUsingType:NSPNGFileType properties:nil];
NSString* filePath = [path stringByExpandingTildeInPath];
BOOL success = [fileData writeToFile:[path stringByExpandingTildeInPath] atomically:YES];
return YES;
}

27 May 2008 | Introduction to Cocoa | 44


Result

27 May 2008 | Introduction to Cocoa | 45

You might also like