PDF and zoom - CATiledLayer - iphone

I have a problem, I'm not a programmer but I try to do some app for fun.
I try to create a pdf viewer, I create a UIView class like this:
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:(CGRect)frame];
if (self) {
self.backgroundColor = [UIColor clearColor];
NSString *pathToPdfDoc = [[NSBundle mainBundle] pathForResource:#"myPDF" ofType:#"pdf"];
NSURL *pdfUrl = [NSURL fileURLWithPath:pathToPdfDoc];
document = CGPDFDocumentCreateWithURL((CFURLRef)pdfUrl);
currentPage = 1;
}
return self;
}
-(void)drawRect:(CGRect)inRect{
if(document) {
CGPDFPageRef page = CGPDFDocumentGetPage(document, currentPage);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSaveGState(ctx);
CGContextTranslateCTM(ctx, 0.0, [self bounds].size.height);
CGContextScaleCTM(ctx, 1.0, -1.0);
CGContextConcatCTM(ctx, CGPDFPageGetDrawingTransform(page, kCGPDFCropBox, [self bounds], 0, true));
CGContextDrawPDFPage(ctx, page);
CGContextRestoreGState(ctx);
}
}
-(void)increasePageNumber {
size_t pageCount = CGPDFDocumentGetNumberOfPages(document);
if (currentPage == pageCount) {
// do nothing
}
else {
currentPage++;
[self setNeedsDisplay];
}
}
-(void)decreasePageNumber {
if (currentPage == 1) {
// do nothing
}
else {
currentPage--;
[self setNeedsDisplay];
}
}
now I try to add zoom but without luck, fro zoom I create a layer:
-(void)viewDidLoad {
CGRect frame;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
frame = CGRectMake(0, 0, 960, 1024);
}
else{
frame = CGRectMake(0, 0, 320, 460);
}
tiledLayer = [CATiledLayer layer];
tiledLayer.delegate = self;
tiledLayer.tileSize = CGSizeMake(1024, 1024);
tiledLayer.levelsOfDetail = 200;
tiledLayer.levelsOfDetailBias = 200;
tiledLayer.frame = frame;
myPDFView = [[viewPDF alloc] initWithFrame:frame];
//[self.view addSubview:myPDFView];
[myPDFView.layer addSublayer:tiledLayer];
CGRect viewFrame = self.view.frame;
viewFrame.origin = CGPointZero;
scrollView = [[UIScrollView alloc] initWithFrame:viewFrame];
scrollView.delegate = self;
scrollView.contentSize = frame.size;
scrollView.maximumZoomScale = 5;
[scrollView addSubview:myPDFView];
[self.view addSubview:scrollView];
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return myPDFView;
}
EDIT: the zoom work, I use shouldAutorotateToInterfaceOrientation that was the problem (I need to rewrite some code), now it work BUT when I zoom quality worsens. :(

Related

drawRect inverts imageView in iPhone (Simulator)

I have seen this and this but it doesn't clear my doubt.
I have a custom imageView class, a subclass basically. where I need to add sub image views on a UIView at particular pixel values. When I draw these images using custom imageview (draw rect) my images are inverted.
Please help as to what is the change I need to do in my frame so that image is not inverted.
Below is the image.
CustomImageView.m
#implementation CustomImageView
#synthesize customImage;
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor clearColor];
// Initialization code.
}
return self;
}
- (void)drawRect:(CGRect)rect{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextDrawImage(context, rect, customImage.CGImage);
[super drawRect:rect];
}
- (void)dealloc {
[customImage release];
[super dealloc];
}
#end
CustomImageView.h
#interface CustomImageView : UIView
{
}
#property(nonatomic,retain)UIImage *customImage;
#end
I am using this as below
-(void)drawArrowImagewithStartX:(CGFloat)X1 startY:(CGFloat)Y1 andEndX:(CGFloat)X2 endY:(CGFloat)Y2
{
CustomImageView *arrowImageView = [[CustomImageView alloc] initWithFrame:CGRectZero];
CGRect startPointFrame = CGRectZero;
CGRect endPointFrame = CGRectZero;
CGFloat arrowWidth = 0.0;
CGFloat arrowHeight = 0.0;
CGFloat y1 = -(Y1+194.0);
CGFloat y2 = -(Y1+194.0);
if (isMapZoomed) {
startPointFrame = CGRectMake(X1, Y1, 16.0, 16.0);
endPointFrame = CGRectMake(X2, Y2, 16.0, 16.0);
arrowWidth = 5.0;
arrowHeight = 25.0;
}
else {
startPointFrame = CGRectMake(X1, y1, 8.0, 8.0);
endPointFrame = CGRectMake(X2, y2, 8.0, 8.0);
arrowWidth = 10.0;
arrowHeight = 50.0;
}
CustomImageView *startImageView = [[CustomImageView alloc] initWithFrame:CGRectZero];
startImageView.frame = startPointFrame;
if (stepNo == 0)
startImageView.customImage = [UIImage imageNamed:KStartFlag];
else
startImageView.customImage = [UIImage imageNamed:KStartPoint];
CustomImageView *endImageView = [[CustomImageView alloc] initWithFrame:CGRectZero];
endImageView.frame = endPointFrame;
if (stepNo == ([self.allPOIDetailsArray count]-1))
endImageView.customImage = [UIImage imageNamed:KEndFlag];
else
endImageView.customImage = [UIImage imageNamed:KEndPoint];
if(X1 == X2){
if (y1 > y2){
arrowImageView.frame = CGRectMake(X2, (y1-(y1-y2)/2), arrowWidth, arrowHeight);
arrowImageView.customImage =[UIImage imageNamed:KArrowUp];
}
else{
arrowImageView.frame = CGRectMake(X1, (y1+(y2-y1)/2), 5.0, 25.0);
arrowImageView.customImage =[UIImage imageNamed:KArrowDown];
}
}
else {
if (X1 > X2) {
arrowImageView.frame = CGRectMake((X1-(X1-X2)/2), y2, 25.0, 5.0);
arrowImageView.customImage = [UIImage imageNamed:KArrowLeft];
}
else{
arrowImageView.frame = CGRectMake((X1+(X2-X1)/2), y1, 25.0, 5.0);
arrowImageView.customImage = [UIImage imageNamed:KArrowRight];
}
}
for(UIView *subvw in self.zoomingView.subviews)
if ([subvw isKindOfClass:[UIImageView class]]) {
for (UIView *subview in subvw.subviews)
[subview removeFromSuperview];
[subvw addSubview:startImageView];
[subvw addSubview:endImageView];
[subvw addSubview:arrowImageView];
NSLog(#"Subview frame %#",NSStringFromCGRect(subvw.frame));
NSLog(#"\n\nImage frame %# %#",NSStringFromCGRect(arrowImageView.frame),NSStringFromCGRect(startImageView.frame));
}
[arrowImageView release];
[startImageView release];
[endImageView release];
}
yes it is the normal behavior.
Uikit topleft corner coordinate (0,0)
OpenGL/CoreGraphics bottomleft coordinate (0,0)
and hence ur image appear to be inverted.
you can fix this by:
Moving origin up by the view's height.
Negate (multiply by -1)
the y axis.
Best of both worlds, use UIImage's drawAtPoint: or drawInRect: while still specifying your custom context:
UIGraphicsPushContext(context);
[image drawAtPoint:CGPointZero];
UIGraphicsPopContext();
Also you void modifying your context with CGContextTranslateCTM or CGContextScaleCTM.

Show multiple photos in scroller

In the app, I need to show no. of images (count- unknown) in scroller. I put all the images in scroller directly. But start receiving the memory warning level 2. Please suggest me how to do so. Is there any other way to do that?
You can also refer to following link to have better understanding of the problem.
https://www.dropbox.com/sh/h0vwnhhx1acfcb5/W2TQ638udh
-(void) getPortraitScrollReady
{
UIImageView *imageView;
NSString *imageName;
int x=0;
for (NSNumber *numberObject in tagList)
{
imageName = [[NSString alloc] initWithFormat: #"%#", [self getImage:[numberObject intValue]]];
imageView = [[UIImageView alloc ] initWithFrame: CGRectMake(x, 0, 320, 320)];
imageView.image = [self thumbWithSideOfLength:320 pathForMain:imageName]; // a function that returns an image;
[scrollPortrait addSubview:imageView];
[imageName release];
[imageView release];
x+=320;
}
scrollPortrait.contentSize = CGSizeMake(x, 320);
int pageNo =[self indexofObject:imageNo inArray:tagList];
[scrollPortrait setContentOffset:CGPointMake(pageNo*320, 0) animated:NO];
}
Keep all images in an Array/MutableArray as per convenience.
Take Scrollview, In scroll view take 5-UIImageViews to display images from array. Match the length of that UIScrollView with 5-UIImageViews.
When scrolling is done in any of the direction, then 'release' the UIImageView in opposite direction & 'allocate' a new UIImageVIew in scrolled direction.
This is what I did in my project.
.h file contents
IBOutlet UIScrollView *scrlView;
UIImageView *imgView1;
UIImageView *imgView2;
UIImageView *imgView3;
UIImageView *imgView4;
UIImageView *imgView5;
NSMutableArray *imgGallery;
NSInteger mCount;
NSInteger centerImg;
CGFloat imgFrameHeight;
CGFloat imgView1X;
CGFloat imgView2X;
CGFloat imgView3X;
CGFloat imgView4X;
CGFloat imgView5X;
CGFloat previousOffsetX;
CGFloat currentOffsetX;
.m file contents
- (void)photoGallery
{
imgGallery = [[NSMutableArray alloc] initWithCapacity:10];
[imgGallery addObject:[UIImage imageNamed:#"1.png"]];
[imgGallery addObject:[UIImage imageNamed:#"2.png"]];
[imgGallery addObject:[UIImage imageNamed:#"3.png"]];
[imgGallery addObject:[UIImage imageNamed:#"4.png"]];
[imgGallery addObject:[UIImage imageNamed:#"5.png"]];
[imgGallery addObject:[UIImage imageNamed:#"6.png"]];
[imgGallery addObject:[UIImage imageNamed:#"7.png"]];
[imgGallery addObject:[UIImage imageNamed:#"8.png"]];
[imgGallery addObject:[UIImage imageNamed:#"9.png"]];
}
- (void)photoScroller
{
CGFloat appFrameHeight = self.view.frame.size.height;
CGFloat navFrameHeight = self.navigationController.navigationBar.frame.size.height;
CGFloat tabFrameHeight = self.tabBarController.tabBar.frame.size.height;
imgFrameHeight = appFrameHeight - (navFrameHeight+tabFrameHeight);
mCount = [imgGallery count];
[scrlView setContentSize:CGSizeMake(320 * mCount, imgFrameHeight)];
CGFloat offsetX = ((320 * mCount)/2) - 160;
[scrlView setContentOffset:CGPointMake(offsetX, 0)];
imgView1 = [[UIImageView alloc] initWithFrame:CGRectMake(offsetX - (320*2), 0, 320, imgFrameHeight)];
imgView2 = [[UIImageView alloc] initWithFrame:CGRectMake(offsetX - 320, 0, 320, imgFrameHeight)];
imgView3 = [[UIImageView alloc] initWithFrame:CGRectMake(offsetX, 0, 320, imgFrameHeight)];
imgView4 = [[UIImageView alloc] initWithFrame:CGRectMake(offsetX + 320, 0, 320, imgFrameHeight)];
imgView5 = [[UIImageView alloc] initWithFrame:CGRectMake(offsetX + (320*2), 0, 320, imgFrameHeight)];
int center = mCount/2;
int tmp = center * 2;
int remainder = mCount - tmp;
if (remainder != 0) {
centerImg = center;
} else {
centerImg = center - remainder;
}
imgView1.image = [imgGallery objectAtIndex:(centerImg-2)];
imgView2.image = [imgGallery objectAtIndex:(centerImg-1)];
imgView3.image = [imgGallery objectAtIndex:centerImg];
imgView4.image = [imgGallery objectAtIndex:(centerImg+1)];
imgView5.image = [imgGallery objectAtIndex:(centerImg+2)];
[scrlView addSubview:imgView1];
[scrlView addSubview:imgView2];
[scrlView addSubview:imgView3];
[scrlView addSubview:imgView4];
[scrlView addSubview:imgView5];
}
Below is the code where UIImageViews are adjusted
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
imgView1X = imgView1.frame.origin.x;
imgView2X = imgView2.frame.origin.x;
imgView3X = imgView3.frame.origin.x;
imgView4X = imgView4.frame.origin.x;
imgView5X = imgView5.frame.origin.x;
CGPoint previousOffset = [scrlView contentOffset];
previousOffsetX = previousOffset.x;
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
//get the current offset
CGPoint currentOffset = [scrollView contentOffset];
currentOffsetX = currentOffset.x;
//NSLog(NSStringFromCGPoint(currentOffset));
//calculate offset X of RIGHT ImageView to be shifted
CGFloat identifyRightIV = previousOffsetX +640;
//calcualte new LEFT offset X for shifting the previously calcualted RIGHT ImageView
CGFloat newLX = identifyRightIV - (320*5);
//calculate offset X of LEFT ImageView to be shifted
CGFloat identifyLeftIV = previousOffsetX -640;
//calcualte new RIGHT offset X for shifting the previously calcualted LEFT ImageView
CGFloat newRX = identifyLeftIV + (320*5);
//index of new LEFT Image in an array imgGallery
int newImageL = newLX / 320;
//index of new RIGHT Image in an array imgGallery
int newImageR = newRX / 320;
//if scrolled to left
if (newLX >= 0) // Is shifting is necessary? i.e. if new LEFT offsetX is greater than lowest offsetX(0) of scrollview
{
if (currentOffsetX == (previousOffsetX-320))
{
if (imgView1X == identifyRightIV) {
imgView1.frame = CGRectMake(newLX, 0, 320, imgFrameHeight);
imgView1.image = [imgGallery objectAtIndex:newImageL];
}
else if (imgView2X == identifyRightIV) {
imgView2.frame = CGRectMake(newLX, 0, 320, imgFrameHeight);
imgView2.image = [imgGallery objectAtIndex:newImageL];
}
else if (imgView3X == identifyRightIV) {
imgView3.frame = CGRectMake(newLX, 0, 320, imgFrameHeight);
imgView3.image = [imgGallery objectAtIndex:newImageL];
}
else if (imgView4X == identifyRightIV) {
imgView4.frame = CGRectMake(newLX, 0, 320, imgFrameHeight);
imgView4.image = [imgGallery objectAtIndex:newImageL];
}
else if (imgView5X == identifyRightIV) {
imgView5.frame = CGRectMake(newLX, 0, 320, imgFrameHeight);
imgView5.image = [imgGallery objectAtIndex:newImageL];
}
}
}
//if scrolled to right
if (newRX < (mCount*320)) // Is shifting is necessary? i.e. if new RIGHT offsetX is less than highest offsetX of scrollview
{
if (currentOffsetX == (previousOffsetX+320))
{
if (imgView1X == identifyLeftIV) {
imgView1.frame = CGRectMake(newRX, 0, 320, imgFrameHeight);
imgView1.image = [imgGallery objectAtIndex:newImageR];
}
else if (imgView2X == identifyLeftIV) {
imgView2.frame = CGRectMake(newRX, 0, 320, imgFrameHeight);
imgView2.image = [imgGallery objectAtIndex:newImageR];
}
else if (imgView3X == identifyLeftIV) {
imgView3.frame = CGRectMake(newRX, 0, 320, imgFrameHeight);
imgView3.image = [imgGallery objectAtIndex:newImageR];
}
else if (imgView4X == identifyLeftIV) {
imgView4.frame = CGRectMake(newRX, 0, 320, imgFrameHeight);
imgView4.image = [imgGallery objectAtIndex:newImageR];
}
else if (imgView5X == identifyLeftIV) {
imgView5.frame = CGRectMake(newRX, 0, 320, imgFrameHeight);
imgView5.image = [imgGallery objectAtIndex:newImageR];
}
}
}
}
Due to this in entire life cycle only 5-UIImageViews will be in App & all images will be safe in array.
try this code for 1st question:
scrl=[[UIScrollView alloc]initWithFrame:CGRectMake(10, 92, 300, 370)];
//scrl.backgroundColor=[UIColor blackColor];
scrl.delegate=self;
scrl.showsHorizontalScrollIndicator=NO;
scrl.showsVerticalScrollIndicator=NO;
scrl.pagingEnabled=YES;
scrl.layer.cornerRadius = 5.0f;
scrl.layer.masksToBounds = YES;
scrl.layer.borderWidth = 5;
scrl.layer.borderColor = [UIColor blackColor].CGColor;
int i, x=0,y=0;
for (i=0; i<[imageName count]; i++)
{
imagBack=[[UIImageView alloc] initWithFrame:CGRectMake(x,y,300, 370)];
imagBack.image=[UIImage imageNamed:[imageName objectAtIndex:i]];
[scrl addSubview:imagBack];
x =x+300;
}
scrl.contentSize=CGSizeMake(x,370);
[self.view addSubview:scrl];
-> 2nd issue,you use the image to be compressed (.png format) image is ,try this:
[self imageWithImage:image CovertToSize:CGSizeMake(46, 44)];
NSData* imageData = UIImageJPEGRepresentation(image, 1.0f);//10 % quality compressed
call this method when save the image:
-(UIImage *)imageWithImage:(UIImage *)image CovertToSize:(CGSize)size {
UIGraphicsBeginImageContext(size);
[image drawInRect:CGRectMake(0, 0, size.width, size.height)];
destImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return destImage;
}

CGContextDrawPDFPage is drawing the page on the wrong origin point

Edit: It seems that the origin point's components are been multiplied by 2 when drawing the PDF page. Is something I'm doing causing this?
I have a UIViewController that displays a PDF page on a UIScrollView. the PDF page itself is drawn on a CATiledLayer, however, when my view controller draws the layer there is a considerable offset between the layer's bounds and the drawn PDF. As you can see in the picture, the page should have been drawn on the yellow view:
Here is the relevant code that draws the page:
- (void)refreshPage
{
if(contentView) {
for(UIView *v in self.view.subviews) {
[v removeFromSuperview];
[v release];
}
}
CGRect pageRect = CGRectIntegral(CGPDFPageGetBoxRect(self._document.page, kCGPDFCropBox));
pageRect.origin.x = ((self.view.frame.size.width / 2) - (pageRect.size.width / 2));
CATiledLayer *tiledLayer = [CATiledLayer layer];
tiledLayer.delegate = self;
tiledLayer.tileSize = CGSizeMake(1024.0, 1024.0);
tiledLayer.levelsOfDetail = 1000;
tiledLayer.levelsOfDetailBias = 1000;
tiledLayer.frame = pageRect;
contentView = [[UIView alloc] initWithFrame:pageRect];
[contentView.layer addSublayer:tiledLayer];
CGRect viewFrame = self.view.frame;
viewFrame.origin = CGPointZero;
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:viewFrame];
//[scrollView setBackgroundColor:[UIColor cyanColor]];
//[contentView setBackgroundColor:[UIColor yellowColor]];
scrollView.delegate = self;
scrollView.contentSize = pageRect.size;
scrollView.maximumZoomScale = 1000;
[scrollView addSubview:contentView];
[self.view addSubview:scrollView];
pagingViewController = [[PDFPagingViewController alloc] initWithDocument:self._document AndObserver:self];
[self.view addSubview:pagingViewController.view];
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return contentView;
}
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
if(self._document) {
[layer setBackgroundColor:(CGColorRef)[UIColor redColor]];
CGRect drawingRect = CGContextGetClipBoundingBox(ctx);
CGContextSetRGBFillColor(ctx, 1.0, 1.0, 1.0, 1.0);
CGContextFillRect(ctx, drawingRect);
CGContextTranslateCTM(ctx, 0.0, layer.bounds.size.height);
CGContextScaleCTM(ctx, 1.0, -1.0);
CGContextConcatCTM(ctx, CGPDFPageGetDrawingTransform(self._document.page, kCGPDFCropBox, layer.bounds, 0, true));
CGContextDrawPDFPage(ctx, self._document.page);
}
}
You need to change when you set the pageRect's origin (which I assume you do to center in the view). You are setting both the layer's frame and the contentView's frame to the offset pageRect when you really intend to offset only one.
-(void)refreshPage {
//...
CGRect pageRect = CGRectIntegral(CGPDFPageGetBoxRect(self._document.page, kCGPDFCropBox));
CATiledLayer *tiledLayer = [CATiledLayer layer];
//...
tiledLayer.frame = pageRect;
// set the pageRect origin now to center the contentView, not the layer
pageRect.origin.x = ((self.view.frame.size.width / 2) - (pageRect.size.width / 2));
contentView = [[UIView alloc] initWithFrame:pageRect];
[contentView.layer addSublayer:tiledLayer];
//...
}

iPhone - My new view is blocking my toolbar

I have a problem with my app. With help by a tutorial I've created a slideshow with pictures. I've added a toolbar so it's possible to go back. The problem is that when the pictures are showing, the toolbar disappear. I've been trying to google the problem and so on, but I can't solve it. In a "previous" class I create SlideShowViewController, and inside that class I have another one called SlideShowView. I hope this ain't to messy or stupid, cause I really need help.
Here is the code:
#import "SlideShowViewController.h"
#import "Pictures.h"
#interface SlideShowView : UIView
{
NSArray * mImages;
UIImageView * mLeftImageView;
UIImageView * mCurrentImageView;
UIImageView * mRightImageView;
NSUInteger mCurrentImage;
Pictures *picRef;
SlideShowViewController *slideRef;
BOOL mSwiping;
CGFloat mSwipeStart;
}
- (id)initWithImages:(NSArray *)inImages;
#end // SlideShowView
#pragma mark -
//#import "SlideShowViewController.h"
#implementation SlideShowView
- (UIImageView *)createImageView:(NSUInteger)inImageIndex
{
if (inImageIndex >= [mImages count])
{
return nil;
}
UIImageView * result = [[UIImageView alloc] initWithImage:[mImages objectAtIndex:inImageIndex]];
result.opaque = YES;
result.userInteractionEnabled = NO;
result.backgroundColor = [UIColor whiteColor];
result.contentMode = UIViewContentModeScaleAspectFit;
result.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
return result;
}
- (id)initWithImages:(NSArray *)inImages
{
if (self = [super initWithFrame:CGRectZero])
{
mImages = [inImages retain];
NSUInteger imageCount = [inImages count];
if (imageCount > 0)
{
mCurrentImageView = [self createImageView:0];
[self addSubview:mCurrentImageView];
if (imageCount > 1)
{
mRightImageView = [self createImageView:1];
[self addSubview:mRightImageView];
}
}
self.opaque = YES;
self.backgroundColor = [UIColor whiteColor];
self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
}
return self;
}
- (void)dealloc
{
[mImages release];
[super dealloc];
}
- (void)layoutSubviews
{
if (mSwiping)
return;
CGSize contentSize = self.frame.size;
mLeftImageView.frame = CGRectMake(-contentSize.width, 0.0f, contentSize.width, contentSize.height);
mCurrentImageView.frame = CGRectMake(0.0f, 0.0f, contentSize.width, contentSize.height);
mRightImageView.frame = CGRectMake(contentSize.width, 0.0f, contentSize.width, contentSize.height);
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if ([touches count] != 1){
return;
}
mSwipeStart = [[touches anyObject] locationInView:self].x;
mSwiping = YES;
mLeftImageView.hidden = NO;
mCurrentImageView.hidden = NO;
mRightImageView.hidden = NO;
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
if (! mSwiping || [touches count] != 1)
return;
CGFloat swipeDistance = [[touches anyObject] locationInView:self].x - mSwipeStart;
CGSize contentSize = self.frame.size;
mLeftImageView.frame = CGRectMake(swipeDistance - contentSize.width, 0.0f, contentSize.width, contentSize.height);
mCurrentImageView.frame = CGRectMake(swipeDistance, 0.0f, contentSize.width, contentSize.height);
mRightImageView.frame = CGRectMake(swipeDistance + contentSize.width, 0.0f, contentSize.width, contentSize.height);
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
if (! mSwiping)
return;
CGSize contentSize = self.frame.size;
NSUInteger count = [mImages count];
CGFloat swipeDistance = [[touches anyObject] locationInView:self].x - mSwipeStart;
if (mCurrentImage > 0 && swipeDistance > 50.0f)
{
[mRightImageView removeFromSuperview];
[mRightImageView release];
mRightImageView = mCurrentImageView;
mCurrentImageView = mLeftImageView;
mCurrentImage--;
if (mCurrentImage > 0)
{
mLeftImageView = [self createImageView:mCurrentImage - 1];
mLeftImageView.hidden = YES;
[self addSubview:mLeftImageView];
}
else
{
mLeftImageView = nil;
}
}
else if (mCurrentImage < count - 1 && swipeDistance < -50.0f)
{
[mLeftImageView removeFromSuperview];
[mLeftImageView release];
mLeftImageView = mCurrentImageView;
mCurrentImageView = mRightImageView;
mCurrentImage++;
if (mCurrentImage < count - 1)
{
mRightImageView = [self createImageView:mCurrentImage + 1];
mRightImageView.hidden = YES;
[self addSubview:mRightImageView];
}
else
{
mRightImageView = nil;
}
}
[UIView beginAnimations:#"swipe" context:NULL];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[UIView setAnimationDuration:0.3f];
mLeftImageView.frame = CGRectMake(-contentSize.width, 0.0f, contentSize.width, contentSize.height);
mCurrentImageView.frame = CGRectMake(0.0f, 0.0f, contentSize.width, contentSize.height);
mRightImageView.frame = CGRectMake(contentSize.width, 0.0f, contentSize.width, contentSize.height);
[UIView commitAnimations];
mSwiping = NO;
}
#end // SlideShowView
#pragma mark -
#implementation SlideShowViewController
#synthesize toolbar;
-(IBAction) goBack:(id) sender{
[self.parentViewController dismissModalViewControllerAnimated:YES];
}
- (id)init
{
if (self = [super initWithNibName:nil bundle:nil])
{
NSArray * images = [NSArray arrayWithObjects:[UIImage imageNamed:#"bifColor.png"],
[UIImage imageNamed:#"DSCF1600.jpg"],
[UIImage imageNamed:#"refresh.png"],
[UIImage imageNamed:#"DSCF1601.jpg"], nil];
self.view = [[[SlideShowView alloc] initWithImages:images] autorelease];
}
return self;
}
#end
Instead of this:
self.view = [[[SlideShowView alloc] initWithImages:images] autorelease];
do that:
UIView* slideShowView = [[[SlideShowView alloc] initWithImages:images] autorelease];
[self.view addSubview:slideShowView];
EDIT: Also don't forget to set the frame of slideShowView!

Xcode: UIScrollView image gallery, having memory problems

I'm Trying to develop an UIScrollView Based Image gallery.
So let me explain what i'm trying to achieve here:
I want to a sliding presentation, that can show upto 140 image. ( You can swipe back and forth )
I've found information on the web, and i've been told the best way to do this is with a UIScrollview which has 3 UIImageViews which you create and remove from superview.
So i managed to create such a "sliding image gallery" with some help from a few tutorials :).
I've managed to upload the application to the ipad, start up the application and run it.
after i viewed about 50-70 slides the app crashes ( out of memory). My knowledge of Obj. C isn't that great .
You'll find the code below: it Prob. has something to do with releasing the images.
Improvements to the code would be really helpful
#import "ParatelPresentationViewController.h"
//Define the UIView ( we need 3 Image Views left, mid right);
#interface SlideShowView : UIView
{
NSArray * mImages;
UIImageView * mLeftImageView;
UIImageView * mCurrentImageView;
UIImageView * mRightImageView;
NSUInteger mCurrentImage;
BOOL mSwiping;
CGFloat mSwipeStart;
}
- (id)initWithImages:(NSArray *)inImages;
#end // SlideShowView
#pragma mark -
#implementation SlideShowView
- (UIImageView *)createImageView:(NSUInteger)inImageIndex
{
if (inImageIndex >= [mImages count])
{
return nil;
}
UIImageView * result = [[UIImageView alloc] initWithImage:[mImages objectAtIndex:inImageIndex]];
result.opaque = YES;
result.userInteractionEnabled = NO;
result.backgroundColor = [UIColor blackColor];
result.contentMode = UIViewContentModeScaleAspectFit;
result.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight ;
return result;
}
- (id)initWithImages:(NSArray *)inImages
{
if (self = [super initWithFrame:CGRectZero])
{
mImages = [inImages retain];
NSUInteger imageCount = [inImages count];
NSLog(#"hoeveel foto's: %i");
if (imageCount > 0)
{
mCurrentImageView = [self createImageView:0];
[self addSubview:mCurrentImageView];
if (imageCount > 1)
{
mRightImageView = [self createImageView:1];
[self addSubview:mRightImageView];
}
}
self.opaque = YES;
self.backgroundColor = [UIColor blueColor];
self.contentMode = UIViewContentModeScaleAspectFit;
self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
}
return self;
}
- (void)dealloc
{
[mImages release];
[super dealloc];
}
- (void)layoutSubviews
{
if (mSwiping)
return;
//CGSize contentSize = self.frame.size; // Enable when you use content.width/height
//self.backgroundColor = [UIColor redColor];
mLeftImageView.frame = CGRectMake(-1024, 0.0f, 1024, 748);// (-1024, 0.0f, 1024, 748) can be replaced by (-contentSize.width, 0.0f, contentSize.width, contentSize.height);
mCurrentImageView.frame = CGRectMake(0.0f, 0.0f, 1024, 748);
mRightImageView.frame = CGRectMake(1024, 0.0f, 1024, 748);
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if ([touches count] != 1)
return;
mSwipeStart = [[touches anyObject] locationInView:self].x;
mSwiping = YES;
mLeftImageView.hidden = NO;
mCurrentImageView.hidden = NO;
mRightImageView.hidden = NO;
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
if (! mSwiping || [touches count] != 1)
return;
CGFloat swipeDistance = [[touches anyObject] locationInView:self].x - mSwipeStart;
//CGSize contentSize = self.frame.size;
mLeftImageView.frame = CGRectMake(swipeDistance - 1024, 0.0f, 1024, 748);
mCurrentImageView.frame = CGRectMake(swipeDistance, 0.0f, 1024, 748);
mRightImageView.frame = CGRectMake(swipeDistance + 1024, 0.0f, 1024, 748);
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
if (! mSwiping)
return;
//CGSize contentSize = self.frame.size;
NSUInteger count = [mImages count];
CGFloat swipeDistance = [[touches anyObject] locationInView:self].x - mSwipeStart;
if (mCurrentImage > 0 && swipeDistance > 50.0f)
{
mRightImageView.image = nil;
//[mRightImageView.image release];
[mRightImageView removeFromSuperview];
[mRightImageView release];
//mRightImageView = nil;
//NSLog(#"Count of mRight : %i",[mRightImageView retainCount]);
mRightImageView = mCurrentImageView;
mCurrentImageView = mLeftImageView;
mCurrentImage--;
if (mCurrentImage > 0)
{
mLeftImageView = [self createImageView:mCurrentImage - 1];
mLeftImageView.hidden = YES;
[self addSubview:mLeftImageView];
}
else
{
mLeftImageView = nil;
}
}
else if (mCurrentImage < count - 1 && swipeDistance < -50.0f)
{
mLeftImageView.image = nil;
//[mLeftImageView.image release];
[mLeftImageView removeFromSuperview];
[mLeftImageView release];
//mLeftImageView = nil;
mLeftImageView = mCurrentImageView;
mCurrentImageView = mRightImageView;
mCurrentImage++;
if (mCurrentImage < count - 1)
{
mRightImageView = [self createImageView:mCurrentImage + 1];
mRightImageView.hidden = YES;
[self addSubview:mRightImageView];
NSLog(#"Count of mRight : %i",[mRightImageView.image retainCount]);
}
else
{
mRightImageView = nil;
}
}
[UIView beginAnimations:#"swipe" context:NULL];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[UIView setAnimationDuration:0.3f];
mLeftImageView.frame = CGRectMake(-1024, 0.0f, 1024, 748);
mCurrentImageView.frame = CGRectMake(0.0f, 0.0f, 1024, 748);
mRightImageView.frame = CGRectMake(1024, 0.0f, 1024, 748);
[UIView commitAnimations];
mSwiping = NO;
}
#end // SlideShowView
#pragma mark -
#implementation ParatelPresentationViewController
- (id)init
{
if (self = [super initWithNibName:nil bundle:nil])
{
NSMutableArray *Displayimages = [[NSMutableArray alloc]init];
int i;
for(i=0 ; i<139 ; i++) {
NSString *tempString = [NSString stringWithFormat:#"Dia%d", i+1];
NSLog(#"Dia%d.jpg", i+1);
NSString *imageFile = [[NSBundle mainBundle] pathForResource:tempString ofType:#"JPG"];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:imageFile];
if (fileExists){
[Displayimages addObject:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:tempString ofType:#"JPG"]]];
NSLog(#"img");
}else {
break;
}
}
//NSArray * images = [NSArray arrayWithObjects:[UIImage imageNamed:#"1.jpg"], [UIImage imageNamed:#"2.jpg"], [UIImage imageNamed:#"3.jpg"], [UIImage imageNamed:#"4.jpg"], [UIImage imageNamed:#"5.jpg"], nil];
//NSLog(#"Objects Img = %#", images);
NSLog(#"Images %#",Displayimages);
self.view = [[[SlideShowView alloc] initWithImages:Displayimages] autorelease];
[Displayimages release];
}
return self;
}
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
//return YES;
return UIInterfaceOrientationIsLandscape (interfaceOrientation);
}
#end
If you would find a solution or tips, all are welcome !
Thanks in advance
kind regards Bart !
You definitely have a memory leak in createImageView:. You will have to change
return result;
to
return [result autorelease];
There might be more leaks, but that's an obvious one.
Johannes