Got Code To View Next Image, How to Change To View Previous? - iphone

I have the code below and this allows me to click a button and it switches to the next image, how to I make this so that when I click another button it goes to the previous image?
- (IBAction)next {
static int index = 0; // <-- here
index++;
// Set imageCount to as many images as are available
int imageCount=31;
if (index<=imageCount) {
NSString* imageName=[NSString stringWithFormat:#"img%i.jpg", index];
[picture setImage: [UIImage imageNamed: imageName]];
}
}
Thanks.
I now have this code:
- (IBAction)prev {
// <-- here
index--;
// Set imageCount to as many images as are available
int imageCount=3;
if (index<=0) {
NSString* imageName=[NSString stringWithFormat:#"img%i.jpg", index];
[picture setImage: [UIImage imageNamed: imageName]];
}
}
but it doesn't work, it just changes the imageview to a blank one :'(
It also returns a warning: unused variable imageCount.
I have implemented a ivar now.
Please help thanks

I think you need to make index either a global var or an ivar of the view:
Create an Ivar:
#interface MyView : UIView {
int index;
}
#property (nonatomic) int index;
#implementation MyView {
#synthesize index;
}

I think the problem is due to the if statement, which checks for index <=0 instead of >=0.
Try this
- (IBAction)prev {
// <-- here
index--;
// Set imageCount to as many images as are available
int imageCount = 30;
if (index>=0)
{
NSString* imageName=[NSString stringWithFormat:#"img%i.jpg", index];
[picture setImage: [UIImage imageNamed: imageName]];
}
}
Note: index has to be a ivar or global variable

Related

NSBlockOperation or NSOperation with ALAsset Block to display photo-library images using ALAsset URL

I am asking this question regarding my questions Display photolibrary images in an effectual way iPhone and Highly efficient UITableView "cellForRowIndexPath" method to bind the PhotoLibrary images.
So I would like to request that answers are not duplicated to this one without reading the below details :)
Let's come to the issue,
I have researched detailed about my above mentioned issue, and I have found the document about operation queues from here.
So I have created one sample application to display seven photo-library images using operation queues through ALAsset blocks.
Here are the sample application details.
Step 1:
In the NSOperationalQueueViewController viewDidLoad method, I have retrieved all the photo-gallery ALAsset URLs in to an array named urlArray.
Step 2:
After all the URLs are added to the urlArray, the if(group != nil) condition will be false in assetGroupEnumerator, so I have created a NSOperationQueue, and then created seven UIImageView's through a for loop and created my NSOperation subclass object with the corresponding image-view and URL for each one and added them in to the NSOperationQueue.
See my NSOperation subclass here.
See my implementation (VierwController) class here.
Let's come to the issue.
It not displaying all the seven images consistently. Some of the images are missing. The missing order is changing multiple times (one time it doesn't display the sixth and seventh, and another time it doesn't display only the second and third). The console log displays Could not find photo pic number. However, the URLs are logged properly.
You can see the log details here.
Are there any mistakes in my classes?
Also, when I go through the above mentioned operational queue documentation, I have read about NSBlockOperation. Do I need to implement NSBlockOperation instead of NSOperation while dealing with ALAsset blocks?
The NSBlockOperation description says
A class you use as-is to execute one or more block objects
concurrently. Because it can execute more than one block, a block
operation object operates using a group semantic; only when all of the
associated blocks have finished executing is the operation itself
considered finished.
How can I implement the NSBlockOperation with ALAsset block regarding my sample application?
I have gone through Stack Overflow question Learning NSBlockOperation. However, I didn't get any idea to implement the NSBlockOperation with ALAsset block!!
This is the tutorial about "How to access all images from iPhonePhoto Library using ALAsset Library and show them on UIScrollView like iPhoneSimulator" .
First of all add AssetsLibrary.framework to your project.
Then in your viewController.h file import #import <AssetsLibrary/AssetsLibrary.h> header file.
This is your viewController.h file
#import <UIKit/UIKit.h>
#import <AssetsLibrary/AssetsLibrary.h>
#import "AppDelegate.h"
#interface ViewController : UIViewController <UIScrollViewDelegate>
{
ALAssetsLibrary *assetsLibrary;
NSMutableArray *groups;
ALAssetsGroup *assetsGroup;
// I will show all images on `UIScrollView`
UIScrollView *myScrollView;
UIActivityIndicatorView *activityIndicator;
NSMutableArray *assetsArray;
// Will handle thumbnail of images
NSMutableArray *imageThumbnailArray;
// Will handle original images
NSMutableArray *imageOriginalArray;
UIButton *buttonImage;
}
-(void)displayImages;
-(void)loadScrollView;
#end
And this is your viewController.m file -
viewWillAppear:
#import "ViewController.h"
#import <QuartzCore/QuartzCore.h>
#implementation ViewController
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
assetsArray = [[NSMutableArray alloc]init];
imageThumbnailArray = [[NSMutableArray alloc]init];
imageOriginalArray = [[NSMutableArray alloc]init];
myScrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(0.0, 0.0, 320.0, 416.0)];
myScrollView.delegate = self;
myScrollView.contentSize = CGSizeMake(320.0, 416.0);
myScrollView.backgroundColor = [UIColor whiteColor];
activityIndicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
activityIndicator.center = myScrollView.center;
[myScrollView addSubview:activityIndicator];
[self.view addSubview:myScrollView];
[activityIndicator startAnimating];
}
viewDidAppear:
-(void)viewDidAppear:(BOOL)animated
{
if (!assetsLibrary) {
assetsLibrary = [[ALAssetsLibrary alloc] init];
}
if (!groups) {
groups = [[NSMutableArray alloc] init];
}
else {
[groups removeAllObjects];
}
ALAssetsLibraryGroupsEnumerationResultsBlock listGroupBlock = ^(ALAssetsGroup *group, BOOL *stop) {
//NSLog(#"group %#",group);
if (group) {
[groups addObject:group];
//NSLog(#"groups %#",groups);
} else {
//Call display Images method here.
[self displayImages];
}
};
ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError *error) {
NSString *errorMessage = nil;
switch ([error code]) {
case ALAssetsLibraryAccessUserDeniedError:
case ALAssetsLibraryAccessGloballyDeniedError:
errorMessage = #"The user has declined access to it.";
break;
default:
errorMessage = #"Reason unknown.";
break;
}
};
[assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:listGroupBlock failureBlock:failureBlock];
}
And this is displayImages: method body
-(void)displayImages
{
// NSLog(#"groups %d",[groups count]);
for (int i = 0 ; i< [groups count]; i++) {
assetsGroup = [groups objectAtIndex:i];
if (!assetsArray) {
assetsArray = [[NSMutableArray alloc] init];
}
else {
[assetsArray removeAllObjects];
}
ALAssetsGroupEnumerationResultsBlock assetsEnumerationBlock = ^(ALAsset *result, NSUInteger index, BOOL *stop) {
if (result) {
[assetsArray addObject:result];
}
};
ALAssetsFilter *onlyPhotosFilter = [ALAssetsFilter allPhotos];
[assetsGroup setAssetsFilter:onlyPhotosFilter];
[assetsGroup enumerateAssetsUsingBlock:assetsEnumerationBlock];
}
//Seprate the thumbnail and original images
for(int i=0;i<[assetsArray count]; i++)
{
ALAsset *asset = [assetsArray objectAtIndex:i];
CGImageRef thumbnailImageRef = [asset thumbnail];
UIImage *thumbnail = [UIImage imageWithCGImage:thumbnailImageRef];
[imageThumbnailArray addObject:thumbnail];
ALAssetRepresentation *representation = [asset defaultRepresentation];
CGImageRef originalImage = [representation fullResolutionImage];
UIImage *original = [UIImage imageWithCGImage:originalImage];
[imageOriginalArray addObject:original];
}
[self loadScrollView];
}
Now you have two array one is imageThumbnailArray and another is imageOriginalArray.
Use imageThumbnailArray for showing on UIScrollView for which your scrolling will not be slow.... And use imageOriginalArray for an enlarged preview of image.
'loadScrollView:' method, This is how to images on UIScrollView like iPhoneSimulator
#pragma mark - LoadImages on UIScrollView
-(void)loadScrollView
{
float horizontal = 8.0;
float vertical = 8.0;
for(int i=0; i<[imageThumbnailArray count]; i++)
{
if((i%4) == 0 && i!=0)
{
horizontal = 8.0;
vertical = vertical + 70.0 + 8.0;
}
buttonImage = [UIButton buttonWithType:UIButtonTypeCustom];
[buttonImage setFrame:CGRectMake(horizontal, vertical, 70.0, 70.0)];
[buttonImage setTag:i];
[ buttonImage setImage:[imageThumbnailArray objectAtIndex:i] forState:UIControlStateNormal];
[buttonImage addTarget:self action:#selector(buttonImagePressed:) forControlEvents:UIControlEventTouchUpInside];
[myScrollView addSubview:buttonImage];
horizontal = horizontal + 70.0 + 8.0;
}
[myScrollView setContentSize:CGSizeMake(320.0, vertical + 78.0)];
[activityIndicator stopAnimating];
[activityIndicator removeFromSuperview];
}
And here you can find which image button has been clicked -
#pragma mark - Button Pressed method
-(void)buttonImagePressed:(id)sender
{
NSLog(#"you have pressed : %d button",[sender tag]);
}
Hope this tutorial will help you and many users who search for the same.. Thank you!
You have a line in your DisplayImages NSOperation subclass where you update the UI (DisplayImages.m line 54):
self.imageView.image = topicImage;
This operation queue is running on a background thread, and we know that you should only update the state of the UI on the main thread. Since updating the view of an image view is definitely updating the UI, this can be simply fixed by wrapping the call with:
dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image = topicImage;
});
This puts an asynchronous call on the main queue to update the UIImageView with the image. It's asynchronous so your other tasks can be scheduled in the background, and it's safe as it is running on the main queue - which is the main thread.

Tapping button to go through each frame of animation

I am trying to create an app where when you tap a button it will go to the next frame in an animation.
I have 8 image files, and when I press the button I want the 1st image to display, and when i press the button again, I want the 2nd image to replace the 1st image and so on.
I was thinking something like:
-(IBAction)buttonPressDoStuff:(id)sender {
imageThing.image = [UIImage imageNamed:#"image1.png"];
imageThing.image = [UIImage imageNamed:#"image2.png"];
imageThing.image = [UIImage imageNamed:#"image3.png"];
imageThing.image = [UIImage imageNamed:#"image4.png"];
}
and somehow making this all work consecutively with each press.
I am fairly new at objective c, so any help would be much appreciated.
Can anyone throw up some sample code to do this?
Let's think about this. If you want to do something sequentially, that sounds like the job of an array. So what do you think about this:
In your .h file, add these instance variables:
NSMutableArray* picturesArray;
NSInteger counter;
And now in your .m file, in your class' init method:
//this loop will fill your array with the pictures
for(int idx = 0; idx < NUMBER_OF_PICTURES; idx++) {
//IMPORTANT: this assumes that your pictures' names start with
//'image0.png` for the first image, then 'image1.png`, and so on
//if your images' names start with 'image1.png' and then go up, then you
//should change the 'int idx = 0' declaration in the for loop to 'int idx = 1'
//so the loop will start at 0. You will then need to change the condition
//to 'idx < (NUMBER_OF_PICTURES + 1)' to accomodate the last image
NSString* temp = [NSString stringWithFormat:#"image%i.png", idx];
UIImage* tempImage = [UIImage imageNamed:temp];
[picturesArray addObject:tempImage];
}
and in your buttonPressDoStuff: method:
//this method will move to the next picture in the array each time it is pressed
-(IBAction)buttonPressDoStuff:(id)sender {
if(counter < [pictureArray count]) {
imageThing.image = [picturesArray objectAtIndex:counter];
counter++;
}
}
Your init method should look something like this:
- (id)initWithNibName:(NSString*)nibNameOrNil bundle:(NSBundle*)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if(self) {
//do setup here
for(int idx = 0; idx < NUMBER_OF_PICTURES; idx++) {
NSString* temp = [NSString stringWithFormat:#"image%i.png", idx];
UIImage* tempImage = [UIImage imageNamed:temp];
[picturesArray addObject:tempImage];
}
}
//it is important that you return 'self' no matter what- if you don't,
//you will get the 'control reached end of non-void method' warning
return self;
}

how to change image in imageView on button click

I want to change the image in image view on button click but it does not changing. I am using JPG image to load in image View
- (IBAction) changeImage:(id)sender
{
UIButton *tappedButton = (UIButton*) sender;
NSInteger selectedIndex = [tappedButton tag];
if (selectedIndex==0)
{
UIImage *modelimage = [UIImage imageNamed:#"compositone.jpg"];
modelImagewView.image=modelimage;
}
else
{
UIImage *modelimage = [UIImage imageNamed:#"composittwo.jpg"];
modelImagewView.image=modelimage;
}
}
Try this format - modelImagewView.image = [UIImage imageNamed:#"composittwo.jpg"];
Also, make sure you have set tag numbers properly so that selectedIndex is not always 0. At the same time check if you have linked this IBAction to the appropriate button.
Try This Code
- (IBAction) changeImage:(id)sender
{
UIButton *tappedButton = (UIButton*) sender;
if (tappedButton.tag==0)
{
modelImageView.image=[UIImage imageNamed:#"compositone.jpg"];
}
else
{
modelImageView.image=[UIImage imageNamed:#"composittwo.jpg"];
}
}

how to handle tiling of images on the fly

I am writing an app which would tile the images 256 * 256 and write those tile files back in the directory. I am updating my URL each time if there are any updates and tile those images back and store in the iphone folder. I am worried about two main things :
1) Memory consumption -- will the memory consumption for 5 images of size 200 KB a lot ?
2) How fast I can process my app if I have to tile 5 different URL with images at the same time ?
I have written a code to tile and save in the directory for one URL and would like to do the same for 5 URLs. Is it recommended to go with this approach or if anyone has a different approach?
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *URLString = #"http://www.abc.com/abc.html?event=123";
NSURL *url = [[NSURL alloc] initWithString:URLString];
NSData * dataImage = [NSData dataWithContentsOfURL:url];
NSString *directoryPath = [[NSBundle mainBundle] bundlePath];
UIImage *big = [UIImage imageWithData:dataImage];
[self saveTilesOfSize:(CGSize){256,256} forImage:big toDirectory:directoryPath usingPrefix:#"image_124_"];
TileView *tv = [[TileView alloc] initWithFrame:(CGRect){{0,0}, (CGSize){5000,5000}}];
[tv setTileTag:#"image_110_"];
[tv setTileDirectory:directoryPath];
[scrollView addSubview:tv];
[scrollView setContentSize:(CGSize){5000,5000}];
}
- (void)saveTilesOfSize:(CGSize)size
forImage:(UIImage*)image
toDirectory:(NSString*)directoryPath
usingPrefix:(NSString*)prefix
{
CGFloat cols = [image size].width / size.width;
CGFloat rows = [image size].height / size.height;
int fullColumns = floorf(cols);
int fullRows = floorf(rows);
CGFloat remainderWidth = [image size].width -
(fullColumns * size.width);
CGFloat remainderHeight = [image size].height -
(fullRows * size.height);
if (cols > fullColumns) fullColumns++;
if (rows > fullRows) fullRows++;
CGImageRef fullImage = [image CGImage];
for (int y = 0; y < fullRows; ++y) {
for (int x = 0; x < fullColumns; ++x) {
CGSize tileSize = size;
if (x + 1 == fullColumns && remainderWidth > 0) {
// Last column
tileSize.width = remainderWidth;
}
if (y + 1 == fullRows && remainderHeight > 0) {
// Last row
tileSize.height = remainderHeight;
}
CGImageRef tileImage = CGImageCreateWithImageInRect(fullImage,
(CGRect){{x*size.width, y*size.height},
tileSize});
NSData *imageData = UIImagePNGRepresentation([UIImage imageWithCGImage:tileImage]);
NSString *path = [NSString stringWithFormat:#"%#/%d.png",
directoryPath, prefix];
[imageData writeToFile:path atomically:NO];
}
}
}
I have implemented solution for the similar problem(the difference is, I was not saving them in directory, those were for display purpose only.), with different approach.
In my problem, I have 84 images of 250x250 dimension with size 8KB each( I added them on scrollView and on scrolling I load them, a bit similar to google maps, but more smooth). At first I was using the same approach as yours, but performance was problem. So, I used asynchornous loading concept. I wrote an UIImageView subclass with connectiond delegates, so the UIImageView subclass was responsible for loading it's image. And as loading is asynchronous so performance is far better.
As you asked
1) Memory consumption -- will the memory consumption for 5 images of size 200 KB a lot?
Ans : 5x200KB = 1MB ~ 1.2MB or so(so you will need that much memory for displaying, if you have that much amount of memory then you should not worry.).. in my case 84x8KB = 672 ~ 900KB(as I was using some additional things like activity indicator for each imageview).
2) How fast I can process my app if I have to tile 5 different URL with images at the same time ?
Ans : As you are loading it in viewDidLoad ... or in main thread then performance will be an issue(blocking may happen, as I am not completely sure whether you are using threads or not).
Quick suggestion:
1. write an UIImageView subclass which has connection delegate methods.
2. have some method that you can call from outside to message this imageView to start loading.(give the url)
3. do proper deallocation of resources like responseData and connection object, once the downloading is complete.
4. when you move from this view to other view do proper deallocation and removal of all these imageviews.
5. use intruments to look for the allocations by this.
CODE :
TileImageView.h
#interface TileImageView : UIImageView
{
NSURLConnection *serverConnection;
BOOL isImageRequested;
NSMutableData *responseData;
}
-(void) startImageDownloading:(NSString *)pRequestURL
-(void) deallocateResources;
-(BOOL) isImageRequested;
-(void)cancelConnectionRequest;
-(void) addActivityIndicator;
-(void) removeActivityIndicator;
#end
TileImageView.m
#implementation TileImageView
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self)
{
// Initialization code.
isImageRequested = NO;
}
return self;
}
-(BOOL) isImageRequested
{
return isImageRequested;
}
-(void) startImageDownloading:(NSString *)pRequestURL
{
if (!isImageRequested)
{
NSURL *pServerURL = [[NSURL alloc] initWithString:pRequestURL];
if (pServerURL != nil)
{
isImageRequested = YES;
[self addActivityIndicator];
[self setBackgroundColor:[UIColor lightGrayColor]];
NSURLRequest *pServerRequest = [[NSURLRequest alloc]initWithURL:pServerURL];
serverConnection = [[NSURLConnection alloc] initWithRequest:pServerRequest delegate:self];
if(serverConnection)
{
responseData = [[NSMutableData alloc] init];
}
[pServerURL release];
[pServerRequest release];
}
}
}
-(void) addActivityIndicator
{
UIActivityIndicatorView *tempActivityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
CGFloat size = self.frame.size.width*0.12;
[tempActivityIndicator setFrame:CGRectMake(0, 0, size, size)];
[tempActivityIndicator setCenter:CGPointMake(self.frame.size.width/2, self.frame.size.height/2)];
[tempActivityIndicator setTag:1000];
[tempActivityIndicator setHidesWhenStopped:YES];
[tempActivityIndicator startAnimating];
[self addSubview:tempActivityIndicator];
[tempActivityIndicator release];
}
-(void) removeActivityIndicator
{
UIActivityIndicatorView *tempActivityIndicator = (UIActivityIndicatorView *)[self viewWithTag:1000];
if (tempActivityIndicator != nil)
{
[tempActivityIndicator stopAnimating];
[tempActivityIndicator removeFromSuperview];
}
}
-(void)cancelConnectionRequest
{
if (isImageRequested && serverConnection != nil)
{
[serverConnection cancel];
[self removeActivityIndicator];
[self deallocateResources];
isImageRequested = NO;
}
}
// Name : connection: didReceiveAuthenticationChallenge:
// Description : NSURLConnectionDelegate method. Method that gets called when server sends an authentication challenge.
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
{
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
}
[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}
// Name : connection: didReceiveResponse:
// Description : NSURLConnectionDelegate method. Method that gets called when response for the launched URL is received..
-(void) connection:(NSURLConnection *) connection didReceiveResponse:(NSURLResponse *) response
{
[responseData setLength:0];
}
// Name : connection: didReceiveData:
// Description : NSURLConnectionDelegate method. Method that gets called when data for the launched URL is received..
-(void) connection:(NSURLConnection *) connection didReceiveData:(NSData *) data
{
[responseData appendData:data];
}
// Name : connection: didFailWithError:
// Description : NSURLConnectionDelegate method. Method that gets called when an error for the launched URL is received..
-(void) connection:(NSURLConnection *) connection didFailWithError:(NSError *) error
{
NSLog(#"Error occured while loading image : %#",error);
[self removeActivityIndicator];
[self deallocateResources];
UILabel *tempLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 150, 30)];
[tempLabel setBackgroundColor:[UIColor clearColor]];
[tempLabel setFont:[UIFont systemFontOfSize:11.0f]];
[tempLabel setCenter:CGPointMake(self.frame.size.width/2, self.frame.size.height/2)];
[tempLabel setText:#"Image not available."];
[self addSubview:tempLabel];
[tempLabel release];
}
// Name : connectionDidFinishLoading
// Description : NSURLConnectionDelegate method. Method that gets called when connection loading gets finished.
-(void) connectionDidFinishLoading:(NSURLConnection *) connection
{
[self removeActivityIndicator];
UIImage *tempImage = [[UIImage alloc] initWithData:responseData];
self.image = tempImage;
[tempImage release];
[self deallocateResources];
}
-(void) deallocateResources
{
if (serverConnection != nil)
{
[serverConnection release];
serverConnection = nil;
}
if (responseData != nil)
{
[responseData release];
responseData = nil;
}
}
- (void)dealloc {
[super dealloc];
}
#end
So, If you use above code then only thing you have to do is to add the object of TileImageView and just call method -(void) startImageDownloading:(NSString *)pRequestURL.
Please use instruments to track allocations.
Update :
**How do I add TileImageView on scrollView ? :**
//like this I add 84 images in a 2D shape( 12 x 7) grid ... and once Images are added I set scrollView's contentSize as per complete grid size.
TileImageView *tileImageView = [[TileImageView alloc]initWithFrame:<myFrameAsPerMyNeeds>];
[tileImageView setTag:<this is the identifier I use for recognizing the image>];
[myImageScrollView addSubView:tileImageView];
[tileImageView release];
..later in code when user scroll's and other imageviews come in visibility.I use following code...
TileImageView *loadableImageView = (TileImageView *)[myImageScrollView viewWithTag:];
[loadableImageView startImageDownloading:];
I do not need to do anything in drawRect: , as I have no need to do custome drawing.
For Image names you can use tag property from imageView, but if you need some different name that are more like string then you can put another property in imageView for image name and set it while adding the image view. for saving data you can call your method once the image is downloaded in didFinishLoading method of TileImageView, where you can use that name.
SECODN UPDATE
How I add TileImageView on ScrollView
gridCount = 0;
rows = 7;
columns = 12;
totalGrids = rows*columns;
//*above : all are NSInteger type variable declared at class level
chunkWidth = 250;
chunkHeight = 250;
contentWidth = 0.0;
contentHeight = 0.0;
//*above : all are CGFloat type variable declared at class level
for (int i=0; i<rows; i++)
{
contentWidth = 0.0;
for (int j=0 ; j<columns; j++)
{
gridCount++;
CGRect frame = CGRectMake(contentWidth, contentHeight, chunkWidth, chunkHeight);
[self addNewImageViewWithTag:gridCount frame:frame];
contentWidth += chunkWidth;
}
contentHeight += chunkHeight;
}
[imageScrollView setContentSize:CGSizeMake(contentWidth, contentHeight)];
[imageScrollView setContentOffset:CGPointMake(0, 0)];
[imageScrollView setUserInteractionEnabled:YES];
And in ScrollViewDelegate method.
- (void) scrollViewDidScroll:(UIScrollView *)scrollView
{
if (isZoomed)
{
xOffset = scrollView.contentOffset.x;
yOffset = scrollView.contentOffset.y;
//*above : both are CGFloat type variable declared at class level
visibleColumn = xOffset/chunkWidth+1;
visibleRow = yOffset/chunkHeight+1;
gridNumber = (visibleRow-1)*columns+visibleColumn;
adjGrid1 = gridNumber+1;
adjGrid2 = gridNumber+columns;
adjGrid3 = adjGrid2+1;
//*above : all are NSInteger type variable declared at class level
if (gridNumber ==1)
{
[self createAndSendScrollRequest:gridNumber];
}
if (adjGrid1 > 0 && adjGrid1 <= totalGrids)
{
[self createAndSendScrollRequest:adjGrid1];
}
if (adjGrid2 > 0 && adjGrid2 <= totalGrids)
{
[self createAndSendScrollRequest:adjGrid2];
}
if (adjGrid3 > 0 && adjGrid3 <= totalGrids)
{
[self createAndSendScrollRequest:adjGrid3];
}
}
}
And this is how createAndSendScrollRequest is implemented.
- (void) createAndSendScrollRequest:(NSInteger)chunkId
{
TileImageView *loadingImageView = (TileImageView *)[imageScrollView viewWithTag:chunkId];
if ([loadingImageView image]==nil)
{
[loadingImageView startImageDownloading:<and here I pass url my url is based on tag so In reality I dont pass anything I just use it from the imageview's tag property>];
}
}
Thanks,

UIImageView subclass duplicate the image

I am working on a subclass of UIImageView and one of the things I require is when the object is initalised with the initWithImage: message a 'copy' is created.
I must be confusing something because I can't see what is not working here..
- (id)initWithImage:(UIImage *)image {
[image retain];
if (self = [super initWithImage:image]) {
if (!maskImage) {
maskImage = [UIImage imageWithCGImage:[image CGImage]];
if (maskImage != nil) {
NSLog(#"Made mask image");
} else {
NSLog(#"Failed");
}
//maskImage = [UIImage imageNamed:#"image.png"];
}
}
[image release];
return self;
}
There are no errors when I build this and the maskimage does appear to be created (i do not get the failure message). However, if I uncomment the line allocating from a png it works.
What am I missing?
Thanks!
You should retain created image, in example like this:
- (id)initWithImage:(UIImage *)image {
if (self = [super initWithImage:image]) {
if (!maskImage) {
maskImage = [[UIImage imageWithCGImage:[image CGImage]] retain];
if (maskImage != nil) {
NSLog(#"Made mask image");
} else {
NSLog(#"Failed");
}
}
}
return self;
}
Try this. Should work.
- (id)initWithImage:(NSString *)image {
if (self = [super initWithImage:image]) {
if (!maskImage) {
img = [UIImage imageNamed:image];
maskImage = CGImageRetain(img.CGImage);
if (maskImage != nil) {
NSLog(#"Made mask image");
} else {
NSLog(#"Failed");
}
}
}
return self;
}
Changes
pass NSString instead of image
no need to retain/release image
need to define img, maskImage in .h
maskImage in .h should have retain property set in #property ( e.g.
#property (nonatomic, retain))
First, you should set maskImage to nil, to make sure it isn't garbage:
self.maskImage=nil;
That may screwing up your line (if not now, then later):
if(!imaskImage)
Then, to make a copy, just implement NSCopying in a UIImage subclass. It's easy to do. Then you can type:
maskImage = [image copy];
Alternatively, you can convert the image to data, archive, then unarchive, then convert back to a UIImage. This gives you a complete copy of the image. It's a little more complex, but its the same method used for making deep copies of an object graph.