URL Image issue iphone - iphone

I have 2 main small image buttons say aBtn & bBtn. When i click aBtn / bBtn i Generate 6 image url as default checking the condition that the images are not nil. In the 6 images if some images are empty then i avoid that empty image alone & set the frame accordingly. When i click from aBtn to bBtn, i have the time delay. It is due to checking the 6 url images generate without nil/empty image each time & by setting the frame position accordingly.
This is the code i used to display the images & check the condition from the 6 url images data is not nil if something say 3rd url image is nil it will be avoided. How to overcome the delay to display the images?
NSMutableString *strUrl;
int i;
int j=7;
int k=0;
xorigin=350;
int cou=1;
for( i=1;i<j;i++){
strUrl=[[NSMutableString alloc]init];
UIImageView *imageView= [[UIImageView alloc]init];
[strUrl appendFormat:#"http://commondatastorage.googleapis.com/images2.solestruck.com/%#%#%#%#%#%#%#)-01060%d.jpg",
[[[[shoeDetailDict objectForKey:#"vendorName"] lowercaseString] lowercaseString] stringByReplacingOccurrencesOfString:#" " withString:#"-"],#"-shoes/",[[shoeDetailDict objectForKey:#"vendorName"] stringByReplacingOccurrencesOfString:#" " withString:#"-"],#"-shoes-",[[shoeDetailDict objectForKey:#"productName"] stringByReplacingOccurrencesOfString:#" " withString:#"-"],#"-(",[[prdcolorimgArray objectAtIndex:tagedColor] stringByReplacingOccurrencesOfString:#" " withString:#"-"],i];
NSURL *imageUrl=[[NSURL alloc]initWithString:strUrl];
NSError *error;
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:strUrl] options:NSDataReadingUncached error:&error];
NSLog(#"imageurl colors : %#",strUrl);
if(i==4){
imageView.frame =CGRectMake(25, 0, (self.view.frame.size.width*80)/100,(self.view.frame.size.height*40)/100);
[imageView setImageWithURL:imageUrl];
}
else{
if(data != nil ){
cou++;
imageView.frame =CGRectMake(xorigin, 0, (self.view.frame.size.width*80)/100,(self.view.frame.size.height*40)/100);
[imageView setImageWithURL:imageUrl];
xorigin=xorigin+320;
}
}
imageView.backgroundColor=[UIColor whiteColor];
[productScroll addSubview:imageView];
productScroll.contentSize = CGSizeMake((self.view.frame.size.width)*cou, (self.view.frame.size.height*40)/100);
productScroll.contentOffset=CGPointMake(0, 0);
k++;
}

You are using dataWithContentsOfURL: that load information synchronously.
Try to load all images first and than put them on the scroll view.
Try to use this code:
- (void) prepareImages {
dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
NSMutableArray * imagesArray = [NSMutableArray array];
// Load all images here
[self imagesLoaded:imagesArray]
});
}
- (void) imagesLoaded:(NSArray*) images {
dispatch_async(dispatch_get_main_queue(), ^{
//Display images here
});
}

Related

UIButton with background image from sprite sheet in table view causes memory warning?

I have a sprite sheet in my documents directory. The sprites sheet consists of 256 icons.
I have a table view, in which for each row I am creating 3 buttons with background images from the sliced part of the sprite sheet.
Below is the code to extract the sliced icon from sprite. Using the coordinates known
-(UIImage *)getSlicedImageForDictionary:(NSDictionary *)spriteInfoDictionary spriteImageRef:(UIImage *)spriteImageReference{
NSString *frameString = [spriteInfoDictionary objectForKey:#"frame"];
NSString *frameStringWithOnlyCommas = [[[frameString stringByReplacingOccurrencesOfString:#"\"" withString:#""] stringByReplacingOccurrencesOfString:#"{" withString:#""] stringByReplacingOccurrencesOfString:#"}" withString:#""];
NSArray *frameValues = [frameStringWithOnlyCommas componentsSeparatedByString:#","];
CGImageRef cgIcon = CGImageCreateWithImageInRect(spriteImageReference.CGImage, CGRectMake([[frameValues objectAtIndex:0] floatValue], [[frameValues objectAtIndex:1] floatValue], [[frameValues objectAtIndex:2] floatValue], [[frameValues objectAtIndex:3] floatValue]));
UIImage *icon = [UIImage imageWithCGImage:cgIcon];
frameString = nil;
frameStringWithOnlyCommas = nil;
frameValues = nil;
CGImageRelease(cgIcon);
return icon;
}
I am calling the above method in the for loop as below,
for (int i = 0; i < [iconInfoArray count]; i ++) {
NSDictionary *currentBook = [spriteInfoDictionary objectForKey:[iconInfoArray objectAtIndex:i]];
articleMetaData.articleImage = [self getSlicedImageForDictionary:currentBook spriteImageRef:self.spriteImageSource];
[spriteIconsArray addObject:articleMetaData];
}
The problem is,
When I set the buttons in the table view from the spriteIconsArray I am getting the "Received memory warning" problem and the application crashes.
[btn setBackgroundImage:[spriteIconsArray objectAtIndex:i] forState:UIControlStateNormal];
But when I write the image reference to the documents directory I am not getting any memory warnings and the application runs smoothly.
NSData *data = UIImagePNGRepresentation([spriteIconsArray objectAtIndex:i]);
NSString *pathOfTempImage = [[NSHomeDirectory() stringByAppendingPathComponent:#"Documents"] stringByAppendingPathComponent:#"tempIcon.png"];
[data writeToFile:pathOfTempImage atomically:YES];
[btn setBackgroundImage:pathOfTempImage forState:UIControlStateNormal];
I am confused why this is happening. I don't want to write the image to the documents and read it again, which may create some latency for large set of data.
Please suggest me in this.
Thanks

How to remove duplicate data from nsmutableArray [duplicate]

This question already has answers here:
The best way to remove duplicate values from NSMutableArray in Objective-C?
(14 answers)
Closed 9 years ago.
Hi Iam working with Iphone Photo Library. I got all photos from photo library with AssetFramework. I displayed those photos in scrollview and are perfectly displaying and images count is assume 6. Then when iam clicking single image, it will show large image. it is also done. my problem is "count is 12 (double count) when clicking image to show it as large."
I used below code to get images:
- (void)createScrollView
{
#try
{
NSLog(#"in create scrollview");
//add views to scrolview
// UIImageView *backgroundImgView;
int x=5;
int y=7;
NSLog(#"assetsArray/count/createScrollview %d",assetsArray.count);
for (int i=0;i<[assetsArray count];i++)
{
UIView *userView=[[UIView alloc] initWithFrame:CGRectMake(x, y, 70, 80)];
userView.tag=i;
UIImageView *backgroundImgView=[[UIImageView alloc] initWithFrame:CGRectMake(1, 1, 70, 70)];
backgroundImgView.tag=1;
// [backgroundImgView setImageWithURL:[NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF16BigEndianStringEncoding]] placeholderImage:[UIImage imageNamed:#"NoImage.png"]];
//-------------Getting Images from AssetsLibrary ----------
ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset)
{
galleryObj=[[GalleryObject alloc]init];
ALAssetRepresentation *rep = [myasset defaultRepresentation];
CGImageRef iref = [rep fullResolutionImage];
UIImage *assetsLibraryImage;
if (iref)
{
assetsLibraryImage = [UIImage imageWithCGImage:iref scale:[rep scale] orientation:(UIImageOrientation)[rep orientation]];
galleryObj.galleryImage=assetsLibraryImage;
}
else
{
assetsLibraryImage = [UIImage imageNamed:#"NoImage.png"];
}
//[set addObject:[NSString stringWithFormat:#"1"]];
[uniqueSet addObject:galleryObj];
NSLog(#"uniqueSet data is .....%#",uniqueSet); // Output (3,1,4,2,5) ... all objects
[imagesArray addObject:galleryObj];
NSLog(#"imagesArray/resultBlock count is %d array is %#....",imagesArray.count,imagesArray);
backgroundImgView.image=assetsLibraryImage;
};
ALAsset *al_asset = [assetsArray objectAtIndex:i];
//NSLog(#"al_asset is ......%#",al_asset);
al_assetUrl=al_asset.defaultRepresentation.url;
//NSLog(#"al_assetUrl is %#",al_assetUrl);
ALAssetsLibraryAccessFailureBlock failureblock = ^(NSError *myerror)
{
NSLog(#"ALAssetsLibraryAccessFailureBlock");
};
ALAssetsLibrary* assetslibrary = [[ALAssetsLibrary alloc] init];
[assetslibrary assetForURL:al_assetUrl resultBlock:resultblock failureBlock:failureblock];
//-------------Getting Images from AssetsLibrary ----------
UIButton *userButton=[[UIButton alloc]initWithFrame:CGRectMake(1, 1, 70,70)];
[userButton addTarget:self action:#selector(userImageClicked:) forControlEvents:UIControlEventTouchUpInside];
userButton.tag=i;
[userView addSubview:backgroundImgView];
[userView addSubview:userButton];
[self.galleryScrollview addSubview:userView];
x+=79;
if ((i+1)%4==0)
{
//if added image is 4th image
y+=80;
x=5;
}
// [activity stopAnimating];
}
if (y+100>self.galleryScrollview.frame.size.height)
{
self.galleryScrollview.contentSize=CGSizeMake(320, y+100);
}
else
{
self.galleryScrollview.contentSize=CGSizeMake(320, self.galleryScrollview.frame.size.height+60);
}
}
#catch (NSException *exception)
{
NSLog(#"exception is %#",exception);
}
}
Please notice that i created button and action is userImageClicked in above method. when iam clicking userImageClicked button, the array count is double.
i dont know why this is happened. i try to remove duplicates using containsObject method. but no use.
In above method, I saved UIImage in objectclass and assinging that object to imagesArray.
I also took NSMutableSet to store value, but it is also no use.
Please any one can suggest to solve my issue.
This is how you delete duplicate data:
NSArray *copy = [mutableArray copy];
NSInteger index = [copy count] - 1;
for (id object in [copy reverseObjectEnumerator]) {
if ([mutableArray indexOfObject:object inRange:NSMakeRange(0, index)] != NSNotFound) {
[mutableArray removeObjectAtIndex:index];
}
index--;
}
Please use it accordingly...
A simpler way:
NSMutableArray *unique = [NSMutableArray array];
for (id obj in originalArray) {
if (![unique containsObject:obj]) {
[unique addObject:obj];
}
}
If above is the only method where you add images to imagesArray then try checking you are not calling it twice from any where, else check if imagesArray is not getting updated from any where else.
And if you need to call this method createScrollView more than once then write code for adding image in imagesArray separately.
The problem is in the creation of galleryObj.
You create a new object for every image.
Every instance of galleryObj is therefore unique.
Whether you use NSSet of NSMutableArray or NSWhatever, they will not know that inside the galleryObj object is the same UIImage.
The Apple documentation of ALAssetRepresentation states that it encapsulates one of the representations. So if you have both a JGP and a RAW picture saved, you will get two separate representations of the same picture.
In that case you have to ignore one or the other type. I would not recommend comparing a RAW picture with a JPG picture (;-)).
Hi Thank all for quick reply. after 3 hours i solved my problem. I got exact duplicates, so that i removed duplicates using below code. i know it is not good code. but it solves my issue.
if([imagesArray count]>0)
{
int dupCount=[imagesArray count]/2;
int imagesArrayCount=[imagesArray count];
for(int i=dupCount;dupCount<imagesArrayCount;dupCount++)
{
[imagesArray removeObjectAtIndex:i];
}
}
and also i find why the duplicate data is? the answer is i used the block code, it is calling two times. so that array contains double data values.
Thanks you all..

App crashes after download of 6th image

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.

issue with AlAsset library

I'm facing an issue with the ALAsset library: I have an UIView with 100 image views. When the view is loading, i'm calling a function for generating the images from the file name.
This is my class:
#interface myClass
{
NSString *fileName;
int pathId;
}
viewDidLoad
-(void)viewDidLoad
{
NSMutableArray *imageCollectionArray = [self createImage:arrayOfmyClassObject];
//Here I'm binding the 100 images in UIView using the images in imageCollectionArray
}
This is my method in which I found the issue:
- (NSMutableArray *)createImage:(NSMutableArray *)imageFileNamesArray
{
imageArray = [[NSMutableArray alloc] init];
for (int imageNameKey = 0; imageNameKey<100; imageNameKey++)
{
myClass *obj= [imageFileNamesArray objectAtIndex:imageNameKey];
if(obj.pathId == 0)
{
//Here adding the bundle image into the imageArray
[imageArray addObject:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:obj.fileName ofType:#"png" inDirectory:#"Images"]]];
}
else
{
typedef void (^ALAssetsLibraryAssetForURLResultBlock)(ALAsset *asset); typedef void (^ALAssetsLibraryAccessFailureBlock)(NSError *error);
ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset) {
};
ALAssetRepresentation *rep = [myasset defaultRepresentation];
CGImageRef iref = [rep fullResolutionImage];
UIImage *images;
if (iref)
{
//Here adding the photo library image into the imageArray
images = [UIImage imageWithCGImage:iref];
[imageArray addObject:images];
}
else
{
//Here adding the Nofile.png image into the imageArray if didn't find a photo library image
images = [UIImage imageNamed:#"Nofile.png"];
[imageArray addObject:images];
}
ALAssetsLibraryAccessFailureBlock failureblock = ^(NSError *myerror) {
//Here adding the Nofile.png image into the imageArray if any failure occurs
[imageArray addObject:[UIImage imageNamed:#"Nofile.png"]];
NSLog(#"booya, cant get image - %#",[myerror localizedDescription]);
};
NSURL *asseturl = [NSURL URLWithString:obj.fileName];
ALAssetsLibrary* assetslibrary = [[[ALAssetsLibrary alloc] init] autorelease];
[assetslibrary assetForURL:asseturl
resultBlock:resultblock failureBlock:failureblock];
}
}
return imageArray;
}
The problem was when I loads the view at first time the asset library images are not generating, only bundle images were displayed, if i go to any of the another view and return back to 100 image view then the asset images are generated.And works fine. The problem is the same function is not generating asset images at the first load. How can i fix this? Thanks in advance.
All methods related to ALAssetLibrary are asynchronous, so your view may complete its loading life cycle before the desired data is returned. You have to take this into account and redraw your view (or a portion of it) as needed.

Removing UIImageView from UIScrollView

My app consists of an image gallery. It is a scroll view which displays pics retrieved from the sqlite db. User can scroll the images, add or delete images etc. I can add a picture to the gallery dynamically. But the problem comes when I need to implement the delete functionality. I use the following code but even after calling removeFromSuperView the image is not getting removed from the scrollview.
-(void)deleteDeck{
if(selectedEditDeck!=0){
[deck deleteSelectedDeck:selectedEditDeck]; //deleting from database
//problem starts here ***
[(UIImageView*)[decksGallery viewWithTag:selectedEditDeck-1]removeFromSuperview];
[self loadGallery];
selectedEditDeck=0;
//Ends here*****
[tableData release];
tableData=[NSMutableArray array];
[self showCardNamesinTable];
[aTableView reloadData];
}
I have already created the uiscrollview in the loadview method. Then to refresh the view after every deletion and addition of images so that I can display the updated gallery, I use the following piece of code:
-(void)loadGallery{ //Reloading all for adding a single deck image.
//Database part****
NSString *sqlStr = [NSString stringWithFormat:#"select first_card from decksTable"];
char *sql = (char*)[sqlStr UTF8String];
kidsFlashCardAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSMutableArray *galleryImagesArray=[appDelegate.dbConnection fetchColumnFromTable:sql col:0];
NSArray *sysPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString *docDirectory = [sysPaths objectAtIndex:0];
numberofImages = [galleryImagesArray count];
printf("number is %d",numberofImages);//Database part of code ends here
//In the following fragment of code I add images to UIscrollView
for (int i = 0; i < [galleryImagesArray count]; i++) {
CGFloat yOrigin = i * 65;
NSString *filePath = [NSString stringWithFormat:#"%#/%#", docDirectory,[galleryImagesArray objectAtIndex:i]];
galleryImage = [[UIImageView alloc] initWithFrame:CGRectMake(yOrigin+140, 15,50,50 )];
//galleryImage.tag=[galleryImagesArray count];
galleryImage.tag=i;
printf("THE TAG IS %d",galleryImage.tag);
galleryImage.clipsToBounds=YES;
galleryImage.layer.cornerRadius=11.0;
galleryImage.backgroundColor=[UIColor clearColor];
galleryImage.image =[UIImage imageWithContentsOfFile:filePath];
[decksGallery addSubview:galleryImage];
[galleryImage release];
}
decksGallery.contentSize = CGSizeMake(115*[galleryImagesArray count], 80);
//[decksGallery reloadInputViews];
Make sure your [decksGallery viewWithTag:selectedEditDeck-1] is not returning nil and the image was actually deleted from your db before the refresh code running.
In addition, you are setting imageView.tag = i; in your creation code, since the i would be 0 which is the tag's default value for every UIView, you'd better fix your creation code as well.
If you just want to remove the image from your imageView, you can also do imageView.image = nil;
UIImageView*imageView = (UIImageView*)[decksGallery viewWithTag:selectedEditDeck-1];
[imageView removeFromSuperview];
imageView = nil;