I'm a beginner at iOS development and I'm working on a side project for my school. What I would like to do is have a small image where the user can drag out more images from. Essentially I have an app where I'm generating squares and I need to have a set square where the user can touch the square and drag out new squares onto a board. I have achieved this to a certain point but it's not the desired behavior yet. Currently the user has to touch the button and then release before they can interact with the new square to drag it off of the button. What i would like is to have the touch event somehow passed over to the new UIImageView object that is created so it is seamless dragging out a new square. Below is my current code.
//UIViewController
#import <UIKit/UIKit.h>
#import "Tile.h"
#interface MenuViewController : UIViewController
{
Tile *tileObject;
}
#end
#import "MenuViewController.h"
#implementation MenuViewController
- (IBAction)createTile:(UIButton *)sender {
CGFloat tileX = sender.center.x;
CGFloat tileY = sender.center.y;
tileObject = [[Tile alloc]initWithX:tileX andY:tileY];
[self.view addSubview:tileObject];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return YES;
}
#end
//Custom Tile Class
#import <UIKit/UIKit.h>
#interface Tile : UIImageView
{
CGPoint startLocation;
}
- (id)init; //Default Initialization
- (id)initWithX:(CGFloat)x andY:(CGFloat)y; //Initialization with coordinate points from single screen tap
#end
#import "Tile.h"
#implementation Tile
//Default initialization
-(id) init
{
self = [self initWithX:0 andY:0];
return self;
}
//Initialization with coordinate points from single screen tap
- (id)initWithX:(CGFloat)centerX andY:(CGFloat)centerY
{
//Creates a UIImageView object from an image file
UIImage *image = [UIImage imageNamed:#"redblock.png"];
self = [super initWithImage:image];
//Used to center the image under the single screen tap
centerX -= (image.size.height/2);
centerY -= (image.size.height/2);
//Sets the position of the image
self.frame = CGRectMake(centerX, centerY, image.size.width, image.size.height);
self.userInteractionEnabled = YES; //required for interacting with UIImageViews
return self;
}
/* Methods from Stack Overflow
http://stackoverflow.com/questions/1991899/uiimage-detecting-touch-and-dragging
Referenced from http://www.iphoneexamples.com/
*/
- (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
// Retrieve the touch point
CGPoint point = [[touches anyObject] locationInView:self];
startLocation = point;
[[self superview] bringSubviewToFront:self];
}
- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event {
// Move relative to the original touch point
CGPoint point = [[touches anyObject] locationInView:self];
CGRect frame = [self frame];
frame.origin.x += point.x - startLocation.x;
frame.origin.y += point.y - startLocation.y;
[self setFrame:frame];
}
/*
end of methods from Stack Overflow
*/
#end
If the initial touch down point can be an image view with the image you want to drag as its image, then you can do it like this:
In your menuViewController class, put this in the viewDidLoad (and delete the button and its method):
- (void)viewDidLoad
{
[super viewDidLoad];
tileObject = [[Tile alloc]initWithX:160 andY:200];
[self.view addSubview:tileObject];
}
Then in your Tile class, in the touchesBegan:withEvent: method you create a new tile, and carry out the drag as you did before:
- (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
Tile *newTile = [[Tile alloc]initWithX:160 andY:200];
[self.superview addSubview:newTile];
// Retrieve the touch point
CGPoint point = [[touches anyObject] locationInView:self];
startLocation = point;
[[self superview] bringSubviewToFront:self];
}
Instead of using a button with touchDown event, you need to:
1) Detect touchesBegan and create your tile
2) Detect touchesMoved and move your tile
Related
I am developing a very simple application in Objective-c.
In the app, the user can change a position of the label by dragging the screen.
Tap & drag the screen, the label moves up and down to match the position of the finger.
When you release your finger, the coordinates information of the label is set to its text.
But the label position is reset at the moment its text is changed.
// IBOutlet UILabel *label
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
CGPoint touch = [[touches anyObject] locationInView:self.view];
label.center = CGPointMake(label.center.x, touch.y);
}
- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
CGPoint touch = [[touches anyObject] locationInView:self.view];
label.center = CGPointMake(label.center.x, touch.y);
}
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
CGPoint touch = [[touches anyObject] locationInView:self.view];
label.text = [NSString stringWithFormat:#"y = %f", touch.y];
}
In touchesEnded event, just only change the text of the label,
but the position of it has reset.
I tried to change touchesEnded event like following but it haven't solved the problem.
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
CGPoint touch = [[touches anyObject] locationInView:self.view];
label.text = [NSString stringWithFormat:#"y = %f", touch.y];
label.center = CGPointMake(label.center.x, touch.y); // add this line
}
I want to resolve this weird behavior without uncheck "Use auto layout".
I'd like to keep using auto layout.
I have 4 screenshots for my app.
4 Screenshots
The first image is a Storyboard.
I have a label with auto layout constraints.
The second image is a screenshot right after launching app.
The third image is when a user drag the screen,
and the label move down to match the finger.
The forth image is right after release your finger
and the label text has changed.
You cannot use auto layout and change the center / frame of things; those are opposites. Do one or the other - not both.
So, you don't have to turn off auto layout, but if you don't, then you must use auto layout, and auto layout only, to position things.
When you move the label, do not change its center - change its constraints. Or at least, having changed its center, change its constraints to match.
Otherwise, when layout occurs, the constraints will put it back where you have told them to put it. And layout does occur when you change the text, and at many other times.
Solution by OP.
Constraint can be treated as an IBOutlet on Storyboard:
Associating constraints as well as label or other IBOutlet.
// ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController {
IBOutlet UILabel *label;
IBOutlet NSLayoutConstraint *lcLabelTop;
}
#end
// ViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(panAction:)];
[self.view addGestureRecognizer:pan];
}
- (void)panAction : (UIPanGestureRecognizer *)sender
{
CGPoint pan = [sender translationInView:self.view];
lcLabelTop.constant += pan.y;
if (sender.state == UIGestureRecognizerStateEnded) {
label.text = [NSString stringWithFormat:#"y = %f", lcLabelTop.constant];
}
[sender setTranslation:CGPointZero inView:self.view];
}
I have the following use case:
a view controller (RotationVC) that contains a bit of logic, among others, rotating one of the subviews (by setting its transform to CGAffineTransformMakeRotation)
this RotationVC overrides the viewDidLayoutSubviews method to set its subviews to be as big as the parent view (self.view)
(creating the view controllers and its views is all done programmatically and it has to stay this way; I tried using autoresizingMask with flexible width and flexible height on the subviews but it didn't work)
another view controller (ParentVC) adds the RotationVC as its child, adds its view as its subview and sets its frame at some point to be square - the idea is that when the frame is set, RotationVC viewDidLayoutSubviews will be called and set the subviews to correct sizes (which actually works fine), and then all works fine
(the RotationVC will be used in other view controllers as well and will have different sized, that's the reason it has been extracted to a 'child' view controller and its size should be flexible)
Well, it doesn't work correctly. The problem is that after each rotation, RotationVC viewDidLayoutSubviews method is called, which sets the rotated views frame. This is wrong, as according to Apple's documentation, using the frame property is wrong when the view's transform is anything else than identity (as is in this case). As a result, the rotated view is 'skewed'. Here is the source code down to the delegate, you should be able to paste it to a single file and run. In case you do, what I'm trying to achieve is for the rotated subview to preserve its shape (in this example it's a rectangle):
#import "AppDelegate.h"
#interface RotationVC : UIViewController
#property (nonatomic, weak) UIView *background;
#property (nonatomic, weak) UIView *foreground;
#property (nonatomic) int degrees;
#end
static const double DURATION = 0.5;
#implementation RotationVC
- (void)viewDidLoad {
[super viewDidLoad];
UIView *tmp = [UIView new];
self.background = tmp;
self.background.layer.borderWidth = 2;
self.background.layer.borderColor = [UIColor redColor].CGColor;
[self.view addSubview:self.background];
tmp = [UIView new];
self.foreground = tmp;
self.foreground.layer.borderWidth = 2;
self.foreground.layer.borderColor = [UIColor blueColor].CGColor;
[self.view addSubview:self.foreground];
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
self.background.frame = self.view.bounds;
CGAffineTransform tmp = self.foreground.transform;
self.foreground.transform = CGAffineTransformIdentity;
self.foreground.frame = self.view.bounds;
self.foreground.transform = tmp;
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self performSelector:#selector(rotate) withObject:self];
}
- (void)rotate {
self.degrees = (self.degrees + 15) % 360;
[UIView animateWithDuration:DURATION
delay:0
options:UIViewAnimationOptionCurveLinear|UIViewAnimationOptionBeginFromCurrentState
animations:^{
self.foreground.transform = CGAffineTransformMakeRotation(self.degrees * M_PI/180);
}
completion:^(BOOL finished) {
[self performSelector:_cmd withObject:self afterDelay:0];
}];
}
#end
#interface ParentVC : UIViewController
#property (nonatomic, weak) RotationVC *rotationVC;
#end
#implementation ParentVC
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
RotationVC *tmp = [RotationVC new];
self.rotationVC = tmp;
[self addChildViewController:self.rotationVC];
[self.rotationVC didMoveToParentViewController:self];
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.rotationVC.view];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.rotationVC.view.bounds = CGRectMake(0, 0, 100, 100);
self.rotationVC.view.center = self.view.center;
}
#end
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
UINavigationController *navi = [[UINavigationController alloc] initWithRootViewController:[ParentVC new]];
navi.navigationBarHidden = YES;
self.window.rootViewController = navi;
[self.window makeKeyAndVisible];
return YES;
}
#end
There is a hack that works - in the viewDidLayoutSubviews method, store the rotated view's transform to a temp variable, set the view's transform to identity, set the frame, and set it to rotation again - this is ugly as hell and I bet there has to be a better way. I was also able to devise a few other workarounds, but each one was uglier than the previous one...
Would anybody have a hint as to what to do in this case?
I was able to solve the issue. Just use the following code:
self.foreground.bounds = self.view.bounds;
self.foreground.center = self.background.center;
instead of setting the frame.
This is explained in https://developer.apple.com/library/ios/documentation/windowsviews/conceptual/viewpg_iphoneos/WindowsandViews/WindowsandViews.html#//apple_ref/doc/uid/TP40009503-CH2-SW7:
Important: If a view’s transform property is not the identity transform, the value of that view’s frame property is undefined and must be ignored. When applying transforms to a view, you must use the view’s bounds and center properties to get the size and position of the view. The frame rectangles of any subviews are still valid because they are relative to the view’s bounds.
I always thought that setting the frame is setting the bounds and the center at the same time, but apparently this is very untrue.
I am having some troubles understanding how to wire a custom NSView for an NSMenuItem to support both animation and dragging and dropping. I have the following subclass of NSView handling the bulk of the job. It draws my icon when the application launches correctly, but I have been unable to correctly setup the subview to change when I invoke the setIcon function from another caller. Is there some element of the design that I am missing?
TrayIconView.m
#import "TrayIconView.h"
#implementation TrayIconView
#synthesize statusItem;
static NSImageView *_imageView;
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self) {
statusItem = nil;
isMenuVisible = NO;
_imageView = [[NSImageView alloc] initWithFrame:[self bounds]];
[self addSubview:_imageView];
}
return self;
}
- (void)drawRect:(NSRect)dirtyRect
{
// Draw status bar background, highlighted if menu is showing
[statusItem drawStatusBarBackgroundInRect:[self bounds]
withHighlight:isMenuVisible];
}
- (void)mouseDown:(NSEvent *)event {
[[self menu] setDelegate:self];
[statusItem popUpStatusItemMenu:[self menu]];
[self setNeedsDisplay:YES];
}
- (void)rightMouseDown:(NSEvent *)event {
// Treat right-click just like left-click
[self mouseDown:event];
}
- (void)menuWillOpen:(NSMenu *)menu {
isMenuVisible = YES;
[self setNeedsDisplay:YES];
}
- (void)menuDidClose:(NSMenu *)menu {
isMenuVisible = NO;
[menu setDelegate:nil];
[self setNeedsDisplay:YES];
}
- (void)setIcon:(NSImage *)icon {
[_imageView setImage:icon];
}
TrayIconView.h
#import <Cocoa/Cocoa.h>
#interface TrayIconView : NSView
{
BOOL isMenuVisible;
}
#property (retain, nonatomic) NSStatusItem *statusItem;
- (void)setIcon:(NSImage *)icon;
#end
The solution to this problem was actually outside of the view detailed here. The caller of the interface was being double instantiated on accident, thus nulling out the reference to the previously created NSView. After correcting that concern the app draws and works just fine.
With regard to dragging, I just implemented a subclass of NSView that implemented the Cocoa draggable protocol and added it as a subview to this parent class. That allows dragging onto the currently established NSRect that contains the menubar icon.
I'm making an iPad project in which a class named "Car" (this is a separate file from the view controller) is supposed to be dragged around the main view.
I setup the class as I saw in an Apple example and I'm able to view my image when I run the application but it's like my class doesn't respond to my touches event and I can't solve the problem.
Here is my class code:
Car.h
#import <UIKit/UIKit.h>
#interface Car : UIView {
UIImageView *firstPieceView;
CGPoint startTouchPosition;
}
-(void)animateFirstTouchAtPoint:(CGPoint)touchPoint forView:(UIImageView *)theView;
-(void)animateView:(UIView *)theView toPosition:(CGPoint) thePosition;
-(void)dispatchFirstTouchAtPoint:(CGPoint)touchPoint forEvent:(UIEvent *)event;
-(void)dispatchTouchEvent:(UIView *)theView toPosition:(CGPoint)position;
-(void)dispatchTouchEndEvent:(UIView *)theView toPosition:(CGPoint)position;
#property (nonatomic, retain) IBOutlet UIImageView *firstPieceView;
#end
and this is my other class code: Car.m
#import "Car.h"
#implementation Car
#synthesize firstPieceView;
#define GROW_ANIMATION_DURATION_SECONDS 0.15 // Determines how fast a piece size grows when it is moved.
#define SHRINK_ANIMATION_DURATION_SECONDS 0.15 // Determines how fast a piece size shrinks when a piece stops moving.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// Enumerate through all the touch objects.
NSUInteger touchCount = 0;
for (UITouch *touch in touches) {
// Send to the dispatch method, which will make sure the appropriate subview is acted upon
[self dispatchFirstTouchAtPoint:[touch locationInView:self] forEvent:nil];
touchCount++;
}
}
// Checks to see which view, or views, the point is in and then calls a method to perform the opening animation,
// which makes the piece slightly larger, as if it is being picked up by the user.
-(void)dispatchFirstTouchAtPoint:(CGPoint)touchPoint forEvent:(UIEvent *)event
{
if (CGRectContainsPoint([firstPieceView frame], touchPoint)) {
[self animateFirstTouchAtPoint:touchPoint forView:firstPieceView];
}
}
// Handles the continuation of a touch.
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
NSUInteger touchCount = 0;
// Enumerates through all touch objects
for (UITouch *touch in touches) {
// Send to the dispatch method, which will make sure the appropriate subview is acted upon
[self dispatchTouchEvent:[touch view] toPosition:[touch locationInView:self]];
touchCount++;
}
}
// Checks to see which view, or views, the point is in and then sets the center of each moved view to the new postion.
// If views are directly on top of each other, they move together.
-(void)dispatchTouchEvent:(UIView *)theView toPosition:(CGPoint)position
{
// Check to see which view, or views, the point is in and then move to that position.
if (CGRectContainsPoint([firstPieceView frame], position)) {
firstPieceView.center = position;
}
}
// Handles the end of a touch event.
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
// Enumerates through all touch object
for (UITouch *touch in touches) {
// Sends to the dispatch method, which will make sure the appropriate subview is acted upon
[self dispatchTouchEndEvent:[touch view] toPosition:[touch locationInView:self]];
}
}
// Checks to see which view, or views, the point is in and then calls a method to perform the closing animation,
// which is to return the piece to its original size, as if it is being put down by the user.
-(void)dispatchTouchEndEvent:(UIView *)theView toPosition:(CGPoint)position
{
// Check to see which view, or views, the point is in and then animate to that position.
if (CGRectContainsPoint([firstPieceView frame], position)) {
[self animateView:firstPieceView toPosition: position];
}
}
-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
// Enumerates through all touch object
for (UITouch *touch in touches) {
// Sends to the dispatch method, which will make sure the appropriate subview is acted upon
[self dispatchTouchEndEvent:[touch view] toPosition:[touch locationInView:self]];
}
}
#pragma mark -
#pragma mark === Animating subviews ===
#pragma mark
// Scales up a view slightly which makes the piece slightly larger, as if it is being picked up by the user.
-(void)animateFirstTouchAtPoint:(CGPoint)touchPoint forView:(UIImageView *)theView
{
// Pulse the view by scaling up, then move the view to under the finger.
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:GROW_ANIMATION_DURATION_SECONDS];
theView.transform = CGAffineTransformMakeScale(1.2, 1.2);
[UIView commitAnimations];
}
// Scales down the view and moves it to the new position.
-(void)animateView:(UIView *)theView toPosition:(CGPoint)thePosition
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:SHRINK_ANIMATION_DURATION_SECONDS];
// Set the center to the final postion
theView.center = thePosition;
// Set the transform back to the identity, thus undoing the previous scaling effect.
theView.transform = CGAffineTransformIdentity;
[UIView commitAnimations];
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
UIImage *img = [ UIImage imageNamed: #"CyanSquare.png" ];
firstPieceView = [[UIImageView alloc] initWithImage: img];
//[img release];
[super addSubview:firstPieceView];
[firstPieceView release];
}
return self;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
- (void)dealloc
{
[firstPieceView release];
[super dealloc];
}
#end
And here is my code for the view controller: (ParkingviewController.h)
#import <UIKit/UIKit.h>
#import "Car.h"
#interface ParkingViewController : UIViewController {
}
#end
and last but not least the ParkingViewController.m
#import "ParkingViewController.h"
#implementation ParkingViewController
- (void)dealloc
{
[super dealloc];
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
Car *car1 = [[Car alloc] init];
[self.view addSubview:car1];
[car1 release];
[super viewDidLoad];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return YES;
}
#end
Please forgive me if I've posted all the code but I want to be clear in every aspect of my project so that anyone can have the whole situation to be clear.
You need to set a frame for Car object that you are creating for touches to be processed. You are able to see the image as the clipsToBounds property of the view is set to NO by default.
I'm trying to add scrollbars to an IKImageView. Basically at the moment, I need some examples of a program that loads an image into a view, and if the window is too small, sets up scrollbars that do the right things...
Why can I not find these examples on the apple dev site?
Added info:
After looking at ImagekitDemo I see that evidently I DO need to embed the IKIMageView in a ScrollView. (and somehow that makes the has___Scroller properties of the IKImageView YES...)
However, now (And this is true in ImageKitDemo as well) The scroll bars are fine as long as only one (or neither) is needed. However, as soon as both are needed, and either dimension of the window is smaller than the image, BOTH scrollbars disappear.
Mouse scrolling still works.
ZoomViewController.h
#interface ZoomViewController : UIViewController <UIScrollViewDelegate>
{
ForecastImage* detailImage; // wrapper class around UIImage (optional - could just be UIImage)
IBOutlet UIImageView* imageView;
IBOutlet DoubleTapScrollView* zoomableScrollView;
}
#property (readwrite, nonatomic, retain) ForecastImage* detailImage;
- (IBAction) dismissZoomViewController;
- (UIView *) viewForZoomingInScrollView:(UIScrollView *)scrollView;
- (void) scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale;
#end
ZoomViewController.m
#implementation ZoomViewController
#synthesize detailImage;
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)viewWillAppear:(BOOL)animated
{
[imageView setImage:[self.detailImage renderedImage]];
[zoomableScrollView setContentSize:[[imageView image] size]];
[zoomableScrollView setMaximumZoomScale:5.0];
[zoomableScrollView setMinimumZoomScale:0.25];
}
- (void) viewDidAppear:(BOOL)animated
{
self.navigationItem.title = [SearchService getDisplayName:[self.detailImage forecastArea]];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
// Release anything that's not essential, such as cached data
}
- (void)dealloc
{
imageView.image = nil;
self.detailImage = nil;
[super dealloc];
}
- (IBAction) dismissZoomViewController
{
[self dismissModalViewControllerAnimated:YES];
}
#pragma mark Pinch-n-Zoom
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return imageView;
}
- (void) scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale
{
CGSize newSize = CGSizeMake(imageView.image.size.width * scale, imageView.image.size.height * scale);
[scrollView setContentSize:newSize];
}
#end
The best place to start is the Scroll View Programming Guide. Basically, you need to put the IKImageView inside a NSScrollView. If the IKImageView size exceeds the visible rectangle of the NSScrollView, then scrollbars will appears.
The following sample uses IKImageView to perform various zoom and resizing operations.