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, ...
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...
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(@quot;export:%@quot;, sender);
}

- (...
Availability of UI objects

AppController.m

- (id)init
{
       self = [super init];
if (self) {
       NSLog(@quot;expor...
Selectors: setting the size textfield

AppController.m

- (void)awakeFromNib
{
[imageSizeText setStringValue:@quot;quot;];...
Objective-C is C with extensions
object instance:
[NSMutableArray alloc]

pointer to object:
NSMutableArray* list;
list = ...
Methods
method that takes an argument:
selector =addObject:
[list addObject:foo];

multiple arguments:
[list insertObject:...
Memory management with reference counting
                       allocates memory and returns object with retain count of ...
Member variables: storing the image file path
AppController.h

@interface AppController : NSObject{
   IBOutlet NSTextFiel...
Opening an image file in a dialog window
AppController.m

- (IBAction)showOpenPanel:(id)sender
{
    NSOpenPanel *op = [NS...
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 = [[[NS...
Opening the image file when dragging on app icon
Step 1: add code

AppController.m

- (BOOL)application:(NSApplication *)t...
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: ImageV...
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)draggingEnter...
Testing: loading an image from the app bundle
Drag image on XCode: Resources




AppController.m

- (void)awakeFromNib
{
 ...
Show image in real size
Override NSImageView’s drawRect:

ImageView.m

- (void)drawRect:(NSRect)rect
{
   if ([self image]...
Orient to top left
Flip coordinate system:

ImageView.m

- (BOOL)isFlipped
{
return YES;
}




27 May 2008 | Introduction ...
Use a transformation to flip the image
Update drawRect in ImageView.m
- (void)drawRect:(NSRect)rect
{
if ([self image]) {
...
Store zoom factor in image view
ImageView.h

@interface ImageView : NSImageView {
  NSNumber* zoomFactor;
}

ImageView.m

...
Connect the slider value to
the image size

Replace updateSliderValue in AppController.m

- (IBAction)updateSliderValue:(i...
Getting the image size
Using NSNotification messages

ImageView.m

- (void)notifyImageUpdated
{
   [[NSNotificationCenter ...
Receiving the notification
Add toawakeFromNib inAppController.m
[[NSNotificationCenter defaultCenter] addObserver:self
   ...
Update the text field when the image is loaded
Override tosetImage inImageView.m
- (void)setImage:(NSImage *)image
{
   [s...
Update the file path when the image is dragged
Update concludeDragOperation in ImageView.m
- (void)concludeDragOperation:(...
Export the image: Categories
Categories are the prototypes of Cocoa.

Extend a class without subclassing
PrettyPrintCatego...
A category on NSImageView
ImageViewAdditions.h

@interface NSImageView (ImageViewAdditions)
- (NSImage*)imageOfSize:(NSSiz...
Export the image
In AppController.m:
- (IBAction)exportImage:(id)sender
{
    NSSize size = [[imageView imageSize] sizeVal...
Result




27 May 2008 | Introduction to Cocoa | 45
Upcoming SlideShare
Loading in...5
×

Introduction To Cocoa

5,767

Published on

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

Published in: Technology
1 Comment
6 Likes
Statistics
Notes
No Downloads
Views
Total Views
5,767
On Slideshare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
142
Comments
1
Likes
6
Embeds 0
No embeds

No notes for slide

Introduction To Cocoa

  1. 1. Introduction to Cocoa Programming for Mac OS X Arthur Clemens 27 May 2008 - Amsterdam
  2. 2. What we are going to create What are we going to make?
  3. 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
  4. 4. XCode Tools  http://developer.apple.com/ 27 May 2008 | Introduction to Cocoa | 4
  5. 5. New application 27 May 2008 | Introduction to Cocoa | 5
  6. 6. XCode interface 27 May 2008 | Introduction to Cocoa | 6
  7. 7. Interface builder 27 May 2008 | Introduction to Cocoa | 7
  8. 8. Drag and drop the interface 27 May 2008 | Introduction to Cocoa | 8
  9. 9. Create AppController class “AppController” 27 May 2008 | Introduction to Cocoa | 9
  10. 10. Instantiate AppController 27 May 2008 | Introduction to Cocoa | 10
  11. 11. Adding outlets 27 May 2008 | Introduction to Cocoa | 11
  12. 12. Adding actions 27 May 2008 | Introduction to Cocoa | 12
  13. 13. Setting properties 27 May 2008 | Introduction to Cocoa | 13
  14. 14. Make connections 27 May 2008 | Introduction to Cocoa | 14
  15. 15. Creating files ctrl-drag 27 May 2008 | Introduction to Cocoa | 15
  16. 16. Testing UI output AppController.m - (IBAction)exportImage:(id)sender { NSLog(@quot;export:%@quot;, sender); } - (IBAction)updateSliderValue:(id)sender { NSLog(@quot;updateSliderValue:%fquot;, [sender floatValue]); } 27 May 2008 | Introduction to Cocoa | 16
  17. 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. 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. 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. 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. 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
  22. 22. 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
  23. 23. 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:@quot;pngquot;] contextInfo:(void *)ci PNG and GIF: { [NSArray arrayWithObjects:@quot;pngquot;,@quot;gifquot;,nil] if (returnCode != NSOKButton) return; NSString *path = [op filename]; } AppController.h ... and update the NIB file - (IBAction)showOpenPanel:(id)sender; 27 May 2008 | Introduction to Cocoa | 23
  24. 24. Connecting the menu in IB 27 May 2008 | Introduction to Cocoa | 24
  25. 25. 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
  26. 26. 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
  27. 27. Opening target info Command-i 27 May 2008 | Introduction to Cocoa | 27
  28. 28. Set the app delegate in IB 27 May 2008 | Introduction to Cocoa | 28
  29. 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. 30. Set image view to new subclass in IB 27 May 2008 | Introduction to Cocoa | 30
  31. 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. 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. 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. 34. Orient to top left Flip coordinate system: ImageView.m - (BOOL)isFlipped { return YES; } 27 May 2008 | Introduction to Cocoa | 34
  35. 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
  36. 36. 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
  37. 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
  38. 38. Getting the image size Using NSNotification messages ImageView.m - (void)notifyImageUpdated { [[NSNotificationCenter defaultCenter] postNotificationName:@quot;imageUpdatedquot; 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
  39. 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. 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. 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. 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
  43. 43. 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
  44. 44. 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:@quot;%@_%.0fx%.0f.pngquot;, 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
  45. 45. Result 27 May 2008 | Introduction to Cocoa | 45
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×