I am working on displaying several Images in a scrollview loaded from a MapServer which returns an image of showing a map.
So what I did is I have created 4 UIImageViews, put them in a NSMutableDictionary.
Then when scrolling to the desirable Image it will initiate to load the data from the url asynchronous.
so first I display an UIActivityIndicatorView, then it will load the data and at the end hide the UIActivityIndicatorView and display the UIImageView.
everything is working more or less fine, apart that it takes sooo long until the image displays, allthough the image is not that big and I have a log text indicating that the end of the function arrived... this log message appears immediately but the image still does not show...
If I call the URL by the Webbrowser the image is shown immediately as well.
below you see my piece of code.
- (void) loadSRGImage:(int) page {
UIImageView *currentSRGMap = (UIImageView *)[srgMaps objectForKey:[NSString stringWithFormat:#"image_%i", page]];
UIActivityIndicatorView *currentLoading = (UIActivityIndicatorView *)[srgMaps objectForKey:[NSString stringWithFormat:#"loading_%i", page]];
// if the image has been loaded already, do not load again
if ( currentSRGMap.image != nil ) return;
if ( page > 1 ) {
MKCoordinateSpan currentSpan;
currentSpan.latitudeDelta = [[[srgMaps objectForKey:[NSString stringWithFormat:#"span_%i", page]] objectForKey:#"lat"] floatValue];
currentSpan.longitudeDelta = [[[srgMaps objectForKey:[NSString stringWithFormat:#"span_%i", page]] objectForKey:#"lon"] floatValue];
region.span = currentSpan;
region.center = mapV.region.center;
[mapV setRegion:region animated:TRUE];
//[mapV regionThatFits:region];
}
srgLegende.hidden = NO;
currentSRGMap.hidden = YES;
currentLoading.hidden = NO;
[currentLoading startAnimating];
NSOperationQueue *queue = [NSOperationQueue new];
NSInvocationOperation *operation = [[NSInvocationOperation alloc]
initWithTarget:self
selector:#selector(loadImage:)
object:[NSString stringWithFormat:#"%i", page]];
[queue addOperation:operation];
[operation release];
}
- (void) loadImage:(NSInvocationOperation *) operation {
NSString *imgStr = [#"image_" stringByAppendingString:(NSString *)operation];
NSString *loadStr = [#"loading_" stringByAppendingString:(NSString *)operation];
WGS84ToCH1903 *converter = [[WGS84ToCH1903 alloc] init];
CLLocationCoordinate2D coord1 = [mapV convertPoint:mapV.bounds.origin toCoordinateFromView:mapV];
CLLocationCoordinate2D coord2 = [mapV convertPoint:CGPointMake(mapV.bounds.size.width, mapV.bounds.size.height) toCoordinateFromView:mapV];
int x1 = [converter WGStoCHx:coord1.longitude withLat:coord1.latitude];
int y1 = [converter WGStoCHy:coord1.longitude withLat:coord1.latitude];
int x2 = [converter WGStoCHx:coord2.longitude withLat:coord2.latitude];
int y2 = [converter WGStoCHy:coord2.longitude withLat:coord2.latitude];
NSString *URL = [NSString stringWithFormat:#"http://map.ssatr.ch/mapserv?mode=map&map=import/dab/maps/dab_online.map&mapext=%i+%i+%i+%i&mapsize=320+372&layers=DAB_Radio_Top_Two", y1, x1, y2, x2];
NSData* imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:URL]];
UIImage* image = [[UIImage alloc] initWithData:imageData];
[imageData release];
UIImageView *currentSRGMap = (UIImageView *)[srgMaps objectForKey:imgStr];
UIActivityIndicatorView *currentLoading = (UIActivityIndicatorView *)[srgMaps objectForKey:loadStr];
currentSRGMap.hidden = NO;
currentLoading.hidden = YES;
[currentLoading stopAnimating];
[currentSRGMap setImage:image]; //UIImageView
[image release];
NSLog(#"finished loading image: %#", URL);
}
I had a similar thing in my app, and i used the SDWebImage from https://github.com/rs/SDWebImage. This has a category written over UIImageView. You need to mention a placeholder image and a url to the UIImageView. It will display the image once it is downloaded and also maintains a cache of the downloaded images, hence avoiding multiple server calls.
Related
I have a problem, need help.
I have a table, on cell I have horizontal scroll with images. Images are downloaded from internet.
When i download the 6th image, my app crashes.
For async upload I use https://github.com/rs/SDWebImage
-(void) fastCreateImage
{
int tempID = self.currentPageNow;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1.2f * NSEC_PER_SEC), dispatch_get_current_queue(), ^{
if(tempID==self.currentPageNow)
{
NSUInteger objIdx = [self.imageViews indexOfObject: [NSNumber numberWithInt:tempID]];
if(objIdx != NSNotFound) {
NSLog(#"WAS CACHED!!!!!!");
}
else
{
UIImageView *myImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 193.5f)];
NSString *urlInString =[NSString stringWithFormat:#"%#/uploads/gallery/hotels/%#",webSite,[self.urlGarbage objectAtIndex:self.currentPageNow]];
SDWebImageManager *manager = [SDWebImageManager sharedManager];
[manager downloadWithURL:[NSURL URLWithString:urlInString]
delegate:self
options:0
success:^(UIImage *image, BOOL cached)
{
myImageView.image = image;
[[self.views objectAtIndex:tempID] addSubview:myImageView];
[self.imageViews addObject:[NSNumber numberWithInt:tempID]];
NSLog(#"LOADED IMG");
}
failure:nil];
[myImageView release];
}
}
});
}
Since you're getting a memory warning, I guess your images are too large to fit in memory. An image uses a maximum of width*height*4 (depending on color depth) of your memory. Calculate this memory requirement for each of your images to see if this is the problem.
In my app, I use UIImageView and UIScrollView to show a lot of images (every time there are about 20 images and every image is about 600px*500px and size is about 600kb).
I use this code to accomplish this function:
// Here is pictures Data;
self.klpArry = self.pictureData;
CGSize size = self.klpScrollView1.frame.size;
for (int i=0; i < [klpArr count]; i++) {
UIImageView *iv = [[UIImageView alloc] initWithFrame:CGRectMake((size.width * i)+300, 20, 546, 546)];
NSString *filePath = [[NSBundle mainBundle] pathForResource:[klpArr objectAtIndex:i] ofType:#"jpg"];
UIImage *imageData = [[UIImage alloc]initWithData:[NSData dataWithContentsOfFile:filePath]];
[iv setImage:imageData];
iv.backgroundColor = [UIColor grayColor];
[self.klpScrollView1 addSubview:iv];
imageData = nil;
iv = nil;
iv.image = nil;
filePath = nil;
[imageData release];
[filePath release];
[iv release];
}
// show the picture in scrollview;
[self.klpScrollView1 setContentSize:CGSizeMake(size.width * numImage, size.height)];
self.klpScrollView1.pagingEnabled = YES;
self.klpScrollView1.showsHorizontalScrollIndicator = NO;
self.klpScrollView1.backgroundColor = [UIColor grayColor];
But every time I initialize this function, the memory will increase about 5MB. Actually I release UIImageView, UIimage and UIScrollView (vi.image=nil, [vi release]) but it doesn't work, the allocated memory is not getting released. BTW, I used my friend's code first vi.image = nil then vi = nil; but the pictures are not getting displayed on scrollview.
The main problem, as I see it, is that you're setting your local variables to nil and then you proceed to try to use those local variables in methods like release and the like, but because they've been set to nil, those methods now do nothing, and the objects with the +1 retainCount (or now +2 because you've added them to your view) are never released.
Thus, I'd suggest the following:
//Here is pictures Data;
self.klpArry = self.pictureData;
CGSize size = self.klpScrollView1.frame.size;
for (int i=0; i < [klpArr count]; i++) {
UIImageView *iv = [[UIImageView alloc] initWithFrame:CGRectMake((size.width * i)+300, 20, 546, 546)];
NSString *filePath = [[NSBundle mainBundle] pathForResource:[klpArr objectAtIndex:i] ofType:#"jpg"];
UIImage *imageData = [[UIImage alloc]initWithData:[NSData dataWithContentsOfFile:filePath]];
[iv setImage:imageData];
iv.backgroundColor = [UIColor grayColor];
[self.klpScrollView1 addSubview:iv];
// Don't set these to nil, or else subsequent release statements do nothing!
// These statements are actually not necessary because they refer to local
// variables so you don't need to worry about dangling pointers. Make sure
// you're not confusing the purpose of setting a pointer to nil in ARC to
// what you're doing in your non-ARC code.
//
// imageData = nil;
// iv = nil;
// You don't want to set this to nil because if iv is not nil, your image
// will be removed from your imageview. So, not only is this not needed,
// but it's undesired.
//
// iv.image = nil;
// This statement is not necessary for the same reason you don't do it
// to imageData or iv, either. This is probably even worse, though, because
// filePath is not a variable that you initialized via alloc. You should
// only be releasing things you created with alloc (or new, copy, mutableCopy,
// for which you issued a retain statement).
//
// filePath = nil;
[imageData release];
// filePath is a +0 retainCount already, so don't release. You only release
// those items for which you increased retainCount (e.g. via new, copy,
// mutableCopy, or alloc or anything you manually retained).
//
// [filePath release];
[iv release];
}
// show the picture in scrollview;
[self.klpScrollView1 setContentSize:CGSizeMake(size.width * numImage, size.height)];
self.klpScrollView1.pagingEnabled = YES;
self.klpScrollView1.showsHorizontalScrollIndicator = NO;
self.klpScrollView1.backgroundColor = [UIColor grayColor];
Thus, your code would be simplified (and corrected) to probably just be:
//Here is pictures Data;
self.klpArry = self.pictureData;
CGSize size = self.klpScrollView1.frame.size;
for (int i=0; i < [klpArr count]; i++) {
UIImageView *iv = [[UIImageView alloc] initWithFrame:CGRectMake((size.width * i)+300, 20, 546, 546)];
NSString *filePath = [[NSBundle mainBundle] pathForResource:[klpArr objectAtIndex:i] ofType:#"jpg"];
UIImage *imageData = [[UIImage alloc] initWithData:[NSData dataWithContentsOfFile:filePath]];
[iv setImage:imageData];
iv.backgroundColor = [UIColor grayColor];
[self.klpScrollView1 addSubview:iv];
[imageData release];
[iv release];
}
// show the picture in scrollview;
[self.klpScrollView1 setContentSize:CGSizeMake(size.width * numImage, size.height)];
self.klpScrollView1.pagingEnabled = YES;
self.klpScrollView1.showsHorizontalScrollIndicator = NO;
self.klpScrollView1.backgroundColor = [UIColor grayColor];
Or you could further simplify your code through the use of autorelease:
//Here is pictures Data;
self.klpArry = self.pictureData;
CGSize size = self.klpScrollView1.frame.size;
for (int i=0; i < [klpArr count]; i++) {
UIImageView *iv = [[[UIImageView alloc] initWithFrame:CGRectMake((size.width * i)+300, 20, 546, 546)] autorelease];
NSString *filePath = [[NSBundle mainBundle] pathForResource:[klpArr objectAtIndex:i] ofType:#"jpg"];
UIImage *imageData = [[[UIImage alloc] initWithData:[NSData dataWithContentsOfFile:filePath]] autorelease];
[iv setImage:imageData];
iv.backgroundColor = [UIColor grayColor];
[self.klpScrollView1 addSubview:iv];
}
// show the picture in scrollview;
[self.klpScrollView1 setContentSize:CGSizeMake(size.width * numImage, size.height)];
self.klpScrollView1.pagingEnabled = YES;
self.klpScrollView1.showsHorizontalScrollIndicator = NO;
self.klpScrollView1.backgroundColor = [UIColor grayColor];
By the way, the statement (with autorelease):
UIImage *imageData = [[[UIImage alloc] initWithData:[NSData dataWithContentsOfFile:filePath]] autorelease];
could probably be simplified to:
UIImage *imageData = [UIImage imageWithContentsOfFile:filePath];
This gives you a UIImage, with a +0 retainCount (i.e. you don't have to release it) from your file.
So, a few final observations:
You really should probably review and study the Advanced Memory Management Programming Guide. It's dense reading if you're new to memory management, but mastery of these concepts (especially in non-ARC code) is critical.
If you haven't, I'd encourage you to run your code through the static analyzer ("Product" - "Analyze" or shift+command+B). I'd be surprised if many (if not most) of these issues wouldn't have been identified for you by the analyzer. You should have zero warnings when you run your code through the analyzer.
If you want to take this to the next level, you might want to be far more conservative about your memory management. The governing principle would be a system design that only loads the images that are needed at the UI at any given time, which involves not only calvinBhai's excellent suggestion of lazy loading of images (i.e. don't load images into memory until your UI really needs them), but also a pro-active releasing images once they've scrolled off the screen. Maybe you don't need to worry about it in your app, because you're only dealing with 20 images at a time, but if any of your portfolios/galleries expanded to 100 or 1000 images, the idea of keeping all of those in memory at any given time is just a bad idea. This is a more advanced concept, so maybe you should focus on the basic memory management problems of your existing code first, but longer term, you might want to contemplate lazy loading and pro-active releasing of images.
If memory is your concern,
try lazy loading the images = Load the visible image, the next and previous image. You dont have to have all images added to your klpscrollview.
Once you figure out lazy loading the images onto your scrollview, then you can think of fixing the images not showing on your scrollview.
Easier would be to search for "lazy load uiimage uiscrollview"
I'm working working on an iPhone application for uploading video files to a specific platform, and one feature I would really love is to be able to present, say, ten different thumbnails for the same video for the user to pick from.
The problem is, that ALAsset only provides a thumbnail method, which just returns the default thumbnail. I have read through the ALAssetRepresentation and ALAsset documentation and I can't seem to find a way to get a thumbnail for a specific timestamp.
I guess one option would be to use something along the lines of libav to get thumbnails but that seems a little "over the top" for something like this. Can anyone help me on this one?
Best regards,
Nick
i think this will help you , and
you can also see through this prompt
Video File thumbnail timestamp missing in ALAsset
{
if ([theAsset valueForProperty:ALAssetPropertyType] == ALAssetTypeVideo) {
// Black semi-transparent background at the bottom of the item
CGRect containerFrame = CGRectMake(0, frame.size.height - AGIPC_ITEM_HEIGHT, frame.size.width, AGIPC_ITEM_HEIGHT);
UIView *containerForMovieInfo = [[[UIView alloc] initWithFrame:containerFrame] autorelease];
containerForMovieInfo.backgroundColor = [UIColor blackColor];
containerForMovieInfo.alpha = 0.7f;
// Movie icon on left side
CGRect movieFrame = CGRectMake(4, 60, 26, 15);
UIImageView *movieImageView = [[[UIImageView alloc] initWithFrame:movieFrame] autorelease];
if (IS_IPAD()) {
movieImageView.image = [UIImage imageNamed:#"AGIPC-Movie-iPad"];
} else {
movieImageView.image = [UIImage imageNamed:#"AGIPC-Movie-iPhone"];
}
[containerForMovieInfo addSubview:movieImageView];
// Movie duration on right side
if ([theAsset valueForProperty:ALAssetPropertyDuration] != ALErrorInvalidProperty) {
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
[formatter setDateFormat:#"mm:ss"];
CGRect durationFrame = CGRectMake(frame.size.width - 26 - 4, 60, 26, 15);
UILabel *durationView = [[[UILabel alloc] initWithFrame:durationFrame] autorelease];
durationView.backgroundColor = [UIColor clearColor];
durationView.textColor = [UIColor whiteColor];
durationView.text = [formatter stringFromDate:[NSDate dateWithTimeIntervalSince1970:[[theAsset valueForProperty:ALAssetPropertyDuration] doubleValue]]];
durationView.font = [UIFont systemFontOfSize:10];
[containerForMovieInfo addSubview:durationView];
}
[self addSubview:containerForMovieInfo];
}
}
last but not least, you must creat the image of the camera on your own.
// Get URL from ALAsset* asset:
NSURL* assetURL = [asset valueForProperty:ALAssetPropertyAssetURL];
// Create AVURLAsset using this URL (assetOptions is optional):
NSDictionary* assetOptions = nil;
// assetOptions = #{AVURLAssetPreferPreciseDurationAndTimingKey : #(YES)};
AVAsset* avAsset = [[AVURLAsset alloc] initWithURL:assetURL options:assetOptions];
// Create generator:
AVAssetImageGenerator* generator = [[AVAssetImageGenerator alloc] initWithAsset:avAsset];
generator.appliesPreferredTrackTransform = YES;
// Create array with CMTimes of thumbnails using your own logic.
// (Use +(NSValue*)valueWithCMTime:(CMTime)time to add CMTime in array).
NSArray* times = [self generateThumbnailTimesForVideo:avAsset];
// Generate thumbnail images asynchronously:
[generator generateCGImagesAsynchronouslyForTimes:times
completionHandler:^(CMTime requestedTime,
CGImageRef image,
CMTime actualTime,
AVAssetImageGeneratorResult result,
NSError* error)
{
// This block is performed for each CMTime in times array.
UIImage* thumbnail = [[UIImage alloc] initWithCGImage:image];
}
];
Synchronous method to get thumbnail at any time is
// PS: SYNC method:
CGImageRef imgRef = [generator copyCGImageAtTime:time actualTime:NULL error:&error];
UIImage* thumbnail = [[UIImage alloc] initWithCGImage:image];
I am trying to add elements to a scroll view using this code:
int missionCount;
[connection release];
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSDictionary *missionsDict = [responseString JSONValue];
/*NSArray *luckyNumbers = [json objectWithString:responseString error:&error];*/
NSLog(#"user Info array is: %#", missionsDict);
// NSDictionary *array = [luckyNumbers1 objectForKey:#"data"];
NSDictionary *missionsData;
missionsData = [missionsDict objectForKey:#"data"];
NSLog(#"missionsData is: %#", missionsData);
NSEnumerator *inner = [missionsData objectEnumerator];
missionsScroll.contentSize = CGSizeMake(768, 1005);
id value;
int badgeY1;
int badgeY2;
int badgeY3;
badgeY1 = 146;
badgeY2 = 188;
badgeY3 = 188;
while((value = [inner nextObject])) {
NSLog(#"value is: %#", value);
NSLog(#"progress is: %#", [value objectForKey:#"progress"]);
NSLog(#"user Info array is: %#", missionsDict);
NSLog(#"name is: %#",[value objectForKey:#"reward_definitions"]);
NSLog(#"missionsData is: %#", missionsData);
NSDictionary *moreData;
moreData = [value objectForKey:#"reward_definitions"];
NSEnumerator *inner2 = [moreData objectEnumerator];
id value2;
int badgeX;
int badgeCount;
badgeX = 0;
badgeCount = 0;
while((value2 = [inner2 nextObject])) {
UIProgressView *progressView;
progressView = [[UIProgressView alloc] initWithFrame:CGRectMake(323, badgeY1, 372, 9)];
float progressValue;
progressValue = ([[[value objectForKey:#"progress"] objectForKey:#"earned"] floatValue] / [[[value objectForKey:#"progress"] objectForKey:#"possible"] floatValue]);
NSLog(#"progressValue is: %f", progressValue);
[progressView setProgress:progressValue];
[missionsScroll addSubview:progressView];
UILabel *missionName;
missionName = [[UILabel alloc] initWithFrame:CGRectMake(66, badgeY1, 227, 21)];
missionName.backgroundColor = [UIColor clearColor];
missionName.textColor = [UIColor whiteColor];
missionName.font = [UIFont fontWithName:#"Heiti TC" size:23.0];
missionName.text = [value objectForKey:#"name"];
[missionsScroll addSubview:missionName];
UILabel *requirementsLabel;
requirementsLabel = [[UILabel alloc] initWithFrame:CGRectMake(66, badgeY2+25, 227, 21)];
requirementsLabel.backgroundColor = [UIColor clearColor];
requirementsLabel.textColor = [UIColor whiteColor];
requirementsLabel.font = [UIFont fontWithName:#"Papyrus" size:19];
requirementsLabel.text = #"To complete you need:";
[missionsScroll addSubview:requirementsLabel];
NSLog(#"Image URL is: %#", [value2 objectForKey:#"image_url"]);
NSURL *url1 = [NSURL URLWithString: [NSString stringWithFormat:#"%#", [value2 objectForKey:#"image_url"]]];
NSData *urlData1 = [NSData dataWithContentsOfURL:url1];
UIImage *image1 = [UIImage imageWithData:urlData1];
UIImageView *badge = [[UIImageView alloc] initWithImage:image1];
[badge setFrame:CGRectMake(badgeX, badgeY2+70, 70, 70)];
[missionsScroll addSubview:badge];
[badge release];
badgeCount = badgeCount+1;
NSLog(#"badgeCount is: %i", badgeCount);
if (badgeCount == 4) {
NSLog(#"Badge Count = 4");
badgeY2 = badgeY2 +70;
badgeX = 0;
badgeCount = 0;
} else {
NSLog(#"Badge Count ≠ 4");
badgeX = badgeX +75;
}
}
NSLog(#"1st While loop done");
// NSLog(#"reward_definitions is: %#", [missionsData objectForKey:#"id"]);
// NSLog(#"Image URL is: %#", [[value objectForKey:#"reward_definitions"] objectForKey:#"image_url"]);
//if ( [array isKindOfClass:[NSDictionary class]] ) {
badgeY1 = badgeY1 +200;
badgeY2 = badgeY2 +200;
badgeY3 = badgeY3 +200;
missionCount = missionCount+1;
}
NSLog(#"While loops done");
for (int a; missionCount > 4; a = a+1) {
missionsScroll.contentSize = CGSizeMake(776, missionsScroll.contentSize.height+200);
}
Nothing is showing up in the scroll view.
It's not obvious what is happening, but first things to check are where the views are valid (not nil) and that this code is running on the main thread.
Put these in and post the results.
NSLog(#"missionsScroll: %#", (missionsScroll==nil)?#"NIL":#"OK");
NSLog(#"progressView: %#", (progressView==nil)?#"NIL":#"OK");
NSLog(#"missionName: %#", (missionName==nil)?#"NIL":#"OK");
NSLog(#"mainThread: %#", ([NSThread isMainThread])?#"OK":#"Background Thread");
Your code is quite convoluted and very difficult to read. Perhaps you could check if your complicated coordinates calculations work as expected, e.g.
NSLog(#"Frame of badge %#", NSStringFromCGRect(badge.frame));
How many times are your while loops iterating? The outer loop increases the y-position of your labels. But the labels will only be displayed at the end of the run loop / start of the next run loop. If you exit this method with the labels with a high y-value then you'll not see them. (It doesn't matter how many times you change the y-value while you're running this code. The display will only update when it's all done.)
** Correction ** You seem to be adding new views each time around your while loop. So in fact I'd expect you to have multiple copies of the subviews appearing when they finally get displayed.
(There's a lot of code to wade through here. If my answer is way off, you might get better answers, but trimming back some of the code and isolating the issue.)
I am loading the images of size 450KB in UIImage view and then adding it to UIscrollview. while am scrolling the 30 images continously,its getting crashed.. what may be the reason..is this memory leak issue...or image size is the problem...? thanks in advance..
here is my code ..
#try{
NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init];
//NSArray *array = [global_ContentString componentsSeparatedByString:#"###"];
NSArray *array1 = [catalogURL componentsSeparatedByString:#"&"];
//**NSLog(#"array1****** = %#",array1);
NSLog(#"loading catalog image(method: loadCatalogImage).......%#%#",baseURL, [[[array1 objectAtIndex:0] componentsSeparatedByString:#"##"] objectAtIndex:0]);
//NSLog(#"baseURL = %#",baseURL);
NSLog(#"loading catalog image.......%#%#",baseURL, [[[array1 objectAtIndex:0] componentsSeparatedByString:#"##"] objectAtIndex:0]);
zoomedImageURL = [NSString stringWithFormat:#"%#%#", baseURL, [[[array1 objectAtIndex:0] componentsSeparatedByString:#"##"] objectAtIndex:1]];
[zoomedImageURL retain];
NSLog(#"aaaaaaaaaaaaaa = %#",zoomedImageURL);
//UIImage *img = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#%#",baseURL, [[[array1 objectAtIndex:0] componentsSeparatedByString:#"##"] objectAtIndex:0]]]]];
UIImage *img = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#",zoomedImageURL]]]];
imgView.contentMode = UIViewContentModeScaleAspectFit;
imgView.image = img;//[GPSTripTracking generatePhotoThumbnail:img:109];
[pool release];
[global_imgProgress stopAnimating];
}
#catch (NSException *e) {
[global_imgProgress stopAnimating];
NSLog(#"Exception....");
}
#finally {
}
am releasing my imgView in dealloc method..
i imlemented the following code in "scrollviewdidscroll"
- (void)scrollViewDidScroll:(UIScrollView *)sender {
// We don't want a "feedback loop" between the UIPageControl and the scroll delegate in
// which a scroll event generated from the user hitting the page control triggers updates from
// the delegate method. We use a boolean to disable the delegate logic when the page control is used.
if (pageControlUsed) {
// do nothing - the scroll was initiated from the page control, not the user dragging
//pageText.text = [NSString stringWithFormat:#"%d/%d", (pageControl.currentPage +1), pageControl.numberOfPages];
pageText.text = [NSString stringWithFormat:#"%d/%d", (pageControl.currentPage ), pageControl.numberOfPages];
//NSLog(#"not scrollling page....");
return;
}
// Switch the indicator when more than 50% of the previous/next page is visible
CGFloat pageWidth = scrollView.frame.size.width;
int page = floor((scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
pageControl.currentPage = page;
// load the visible page and the page on either side of it (to avoid flashes when the user starts scrolling)
[self loadScrollViewWithPage:page - 1];
[self loadScrollViewWithPage:page];
[self loadScrollViewWithPage:page + 1];
//NSLog(#"scrolling page....%d", page);
// A possible optimization would be to unload the views+controllers which are no longer visible
}
and my code for " loadScrollViewWithPage" is
- (void)loadScrollViewWithPage:(int)page
{
//page--;
if (page < 0) return;
if (page >= numberOfPages) return;
if(!isViewCatalog && searchId == 1)
{
//NSLog(#"curre page = %d",pageControl.currentPage);
NSArray *array1 = [global_ContentString componentsSeparatedByString:#"###"];
if(searchInCatalogFlag == 1)
{
pageControl.currentPage=0;
NSArray *urlArray = [[array1 objectAtIndex:pageControl.currentPage] componentsSeparatedByString:#"##"];
//NSLog(#"url array** = %#",urlArray);
headerText.text = [NSString stringWithString:[urlArray objectAtIndex:0]];
pageText.text = [NSString stringWithFormat:#"%d/%d", pageControl.currentPage, (pageControl.numberOfPages - 1)];
}
else
{
NSArray *urlArray = [[array1 objectAtIndex:pageControl.currentPage] componentsSeparatedByString:#"##"];
//NSLog(#"url array** = %#",urlArray);
headerText.text = [NSString stringWithString:[urlArray objectAtIndex:0]];
pageText.text = [NSString stringWithFormat:#"%d/%d", pageControl.currentPage, (pageControl.numberOfPages - 1)];
}
if(page == selectedPage && ![global_imgProgress isAnimating])
[global_imgProgress startAnimating];
}
else
{
headerText.text = [NSString stringWithString:global_SelectedCatalogName];
pageText.text = [NSString stringWithFormat:#"%d/%d", (pageControl.currentPage + 1), (pageControl.numberOfPages - 1)];
if(page == selectedPage + 1 && ![global_imgProgress isAnimating] )
[global_imgProgress startAnimating];
// NSLog(#"header text = %#", headerText.text);
//headerText.text = [NSString stringWithString:[urlArray objectAtIndex:0]];
}
FullPageView *controller = [viewControllers objectAtIndex:page];
if ((NSNull *)controller == [NSNull null] ) {
//NSLog(#"Loading page =========== %d, %d", page, selectedPage);
//voucherPageNo = page;
//[voucherImage retain];
if(universalApp==2)
{
controller = [[FullPageView alloc] initWithNibName:#"FullPageView_iphone" bundle:nil];//:page];
[controller.view setFrame:CGRectMake(0, 0, 320,332)];
}
else
{
controller = [[FullPageView alloc] initWithNibName:#"FullPageView" bundle:nil];//:page];
[controller.view setFrame:CGRectMake(0, 192, 768, 691)];
}
//[controller.view setFrame:CGRectMake(0, 0, 320,480)];
//[controller.view setFrame:CGRectMake(0, 192, 768, 691)];
if((!isViewCatalog && searchId < 2 && searchInCatalogFlag == 0))// || searchInCatalogFlag == 1)
{
// NSLog(#">>>>>>>>>>>>>>>>>> LOADING IMAGE >>>>>>>>>>>>>>>>>>>>");
[controller setPageNo:page];
// if(page >= selectedPage - 1)
[NSThread detachNewThreadSelector:#selector(loadImage) toTarget:controller withObject:nil];
}
else //if((page >= (selectedPage - 1) && page <= (selectedPage + 1)) || !isFirstTimeLoading)
{
NSLog(#"Loading CATALOG IMAGE = %d, %d, %#", page, selectedPage, (isFirstTimeLoading ?#"YES" : #"NO"));
[controller setCatalogURL:[NSString stringWithFormat:#"%#", [catalogArray objectAtIndex:page+(searchId< 2 && !isViewCatalog && searchInCatalogFlag == 0?0:1)]]];
NSLog(#"loading image ipad= %#", [catalogArray objectAtIndex:page+(searchId< 2 && !isViewCatalog && searchInCatalogFlag == 0?0:1)]);
// if(page >= selectedPage - 1)
[NSThread detachNewThreadSelector:#selector(loadCatalogImage) toTarget:controller withObject:nil];
// if(page == (selectedPage + 1))
//isFirstTimeLoading = NO;
}
[viewControllers replaceObjectAtIndex:page withObject:controller];
[controller release];
}
// add the controller's view to the scroll view
if (nil == controller.view.superview)
{
// NSLog(#"Voucher view addead at page..... %d", page);
CGRect frame = scrollView.frame;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0;
controller.view.frame = frame;
// NSLog(#">>>>>>>>> %f, %f", frame.size.width, frame.origin.x);
[scrollView addSubview:controller.view];
}
//if(page == pageControl.currentPage)
//[imgProgress startAnimating];
//else
//pageControlUsed = YES;
}
where wil be the problem..?
450KB is the compressed image size. When an image is loaded into memory, it is uncompressed.
A rule of thumb for working out how much memory an uncompressed image will occupy is:
width * height * 4
With 30 images it is very likely that you're running out of memory.
You should write your code to only keep images in memory if they are visible on screen.
It very likely that your program gets terminated by iOS because it consumes too much memory. Start it from XCode and look at the console - it will probably print that it receives memory warnings.
You will have to load the images on demand, i.e. only when the user gets close to seeing them, and you will have to release the ones that move out of view again. To that end, implement the
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
delegate method, look at the scroll view's content offset and load/release the appropriate images. Alternatively, you can choose to not release them there but instead wait for a memory warning to do so. To do so, implement the
- (void)didReceiveMemoryWarning
method in your view controller.
This might be the issue of memory leaks.
Try to replace this line
UIImage *img = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#",zoomedImageURL]]]]
and use this
UIImage *img = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#",zoomedImageURL]]]];
<<<<<YOUR CODE>>>>
[img release];
I hope this helps