I cant possibly get the image that i parsed from the XML to show on my UIImageView using the code below. Am I doing something wrong because I checked it using NSLog to show if there is a link and apparently there is.
NSString *imageURL = [currentData.imageLink];
NSLog(#"this is link = %#", imageURL);
[cachedList addObject:imageURL];
[myCache setObject:cachedList forKey:#"imageURL"];
cachedList = [myCache objectForKey:#"imageURL"]; /where cachedList is NSMutableArray
for(id obj in cachedList){
NSLog(#"value = %#", obj); //to show value
cell.imageShow.image = [UIImage imageNamed:obj];
}
and also I tried doing the below code, but it gives me an error.
if (cachedList != nil) {
cell.imageShow.image = [UIImage imageNamed:[cachedList valueForKey:#"imageURL"]];
}
I think if you are using UITableView then this is the thing i have used and i prefer for tableview
Link: https://github.com/jakemarsh/JMImageCache
Related
I have an app that creates an animation from images stored in a group in my project navigator (not Images.xcassets). This code "works" in that it animates properly, but using imageNamed causes a memory leak because the image files are not getting deallocated.
I can't figure out why adding with imageNamed: works adds images to my array, but imageWithContentsOfFile: doesn't.
A little info on the mechanics of my app:
self.myPhoto is set on the segue from another ViewController. The number of images can vary, so I test to see the file is "there" before adding it to the array.
Filenames follow this naming convention:
"1-1.jpg"
"2-1.jpg"
"2-2.jpg"
"99-1.jpg"
"99-2.jpg"
"99-3.jpg"
"99-4.jpg"
This code works, but the images don't deallocate, causing a memory leak:
- (void)startAnimation {
NSMutableArray *imageArray = [[NSMutableArray alloc] init];
for (int imageNumber = 1; self.myPhoto != nil; imageNumber++) {
NSString *fileName = [NSString stringWithFormat:#"%#-%d.jpg", self.myPhoto, imageNumber];
// check if a file exists
if ([UIImage imageNamed:fileName]) {
// if it exists, add it to the array
[imageArray addObject:[UIImage imageNamed:fileName]];
} else {
// otherwise, don't add image to the array
break;
}
}
self.myImageView.animationImages = imageArray;
self.myImageView.animationDuration = 1.5f;
self.myImageView.animationRepeatCount = 0;
self.myImageView.contentMode = UIViewContentModeScaleAspectFit;
[self.myImageView startAnimating];
}
I ran Instruments on it and saw I had a memory leak emanating from my animation. Digging around a little on StackOverflow, I discovered the manner I'm adding my files to myArray results in images not getting deallocated.
So I tried this, instead:
- (void)startAnimation {
NSMutableArray *imageArray = [[NSMutableArray alloc] init];
for (int imageNumber = 1; self.myPhoto != nil; imageNumber++) {
NSString *fileName = [NSString stringWithFormat:#"%#-%d", self.myPhoto, imageNumber];
// check if a file exists
if ([UIImage imageNamed:fileName]) {
// if it exists, add it to the array
[imageArray addObject:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle]pathForResource:[NSString stringWithFormat:#"%#", fileName] ofType:#"jpg"]]];
NSLog(#"%# added to imageArray", fileName);
} else {
// otherwise, don't add image to the array
break;
}
}
NSLog(#"There are %lu images in imageArray", (unsigned long)imageArray.count);
self.myImageView.animationImages = imageArray;
self.myImageView.animationDuration = 1.5f;
self.myImageView.animationRepeatCount = 0;
self.myImageView.contentMode = UIViewContentModeScaleAspectFit;
[self.myImageView startAnimating];
}
When I do it this way, the page where the animation loads appears, but the images don't get added to my array--the . This is a well-documented issue. Here are a few posts covering this problem:
Dirty Memory because of CoreAnimation and CG image
How do I use imageWithContentsOfFile for an array of images used in an animation?
Thank you for reading. I'm stumped, though I'm confident the resolution to this problem is a startlingly stupid oversight on my part. Prove me right ;)
I made some minor changes out of desperation and I stumbled into the "answer". Comments note where I made changes:
- (void)startAnimation {
NSMutableArray *imageArray = [[NSMutableArray alloc] init];
for (int imageNumber = 1; self.myPhoto != nil; imageNumber++) {
// I set the filename here, adding .jpg to it
NSString *fileName = [NSString stringWithFormat:#"%#-%d.jpg", self.myPhoto, imageNumber];
// check if a file exists
if ([UIImage imageNamed:fileName]) {
// if it exists, add it to the array
// I blanked out ofType, as it's set when I create the local fileName variable
[imageArray addObject:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle]pathForResource:[NSString stringWithFormat:#"%#", fileName] ofType:#""]]];
} else {
// otherwise, don't add image to the array
break;
}
}
self.myImageView.animationImages = imageArray;
self.myImageView.animationDuration = 1.5f;
self.myImageView.animationRepeatCount = 0;
self.myImageView.contentMode = UIViewContentModeScaleAspectFit;
[self.myImageView startAnimating];
}
So I am using the new Parse Config for my application. The easy part was the installation of the NSString, but now I am working on the ImageView. Can someone help me figure out how to execute this?
Here is how I am calling for a NSString:
[PFConfig getConfigInBackgroundWithBlock:^(PFConfig *config, NSError *error) {
NSNumber *number = config[#"numberOne"];
textLabel.text = [number stringValue];
}];
Now I have created an Image called mainImage and I need this to set to mainImageFile from my Parse server. This is where I got stuck:
[PFConfig getConfigInBackgroundWithBlock:^(PFConfig *config, NSError *error) {
PFFile *pfFileMainImage = config[#"mainImageFile"];
//
//
}];
If this helps.. This is how I would set the images from Parse in tableView:
PFFile *thumbnail = [object objectForKey:#"imageFile"]; PFImageView
thumbnailImageView = (PFImageView)[cell viewWithTag:100]; thumbnailImageView.image = [UIImage
imageNamed:#"add-photo-placeholder.png"]; thumbnailImageView.file =
thumbnail; [thumbnailImageView loadInBackground];
Thank you!
I am trying to add Images fetched from an external service to an NSMutableDictionary and seeing weird results. This is what I am doing:
- (void)fetchImages{
//Fetch Item Brand Images
//self.itemBrands is an NSArray of NSDictionaries
for (NSDictionary *itemBrand in self.itemBrands){
NSString *currentItemId = [itemBrand objectForKey:#"ITEM_ID"];
//Valid Item Id. This Log message is displayed
NSLog(#"Current Item Id: %#",currentItemId);
NSString *currentItemImageUrl = [[IMAGE_URL stringByAppendingString:currentItemId] stringByAppendingString:#".png"];
//Image URL is valid. This log message is displayed
NSLog(#"Current Image URL: %#",currentItemImageUrl);
NSURL *url = [NSURL URLWithString:currentItemImageUrl];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];
if (image == nil){
//This log message is displayed when image is not present
NSLog(#"Image not Present 1");
}else{
//This log message is displayed when image is present
NSLog(#"Image Present 1");
[self.itemBrandImages setObject:image forKey:currentItemId];
}
}
//This for loop is not being executed at all. No log messages displayed.
for(id key in self.itemBrandImages){
NSLog(#"Current Item Id2: %#",key);
if ([self.itemBrandImages objectForKey:key] == nil){
NSLog(#"Image Not Present 2");
}else{
NSLog(#"Image Present 2");
}
}
}
The 2nd for loop where I am iterating over self.itemBrandImages is not being executed at all. None of the log messages inside are being displayed.
I tried the following before posting my issue here:
1) Researched similar problems in stack overflow and incorporated suggestion from one of them. The suggestion was "Perform an alloc init of the NSMUtableDictionary" in the init method of the .m file. This didn't help either.
2) To isolate the issue, I even tried adding a simple string to the NSMUtableDictionary instead of the image but even that does not seem to retained.
I am really confused as as to what I am missing or doing wrong here. Inputs are really appreciated.
Thanks,
Mike G
Perhaps:
for(NSString *key in [self.itemBrandImages allKeys])
I did an alloc init of the NSMutableDictianary right in my fetchImages method and it worked! Not sure why the alloc init in the init method did not work.
So here are my takeaways from this issue:
1) If you have an Array or dictionary #property that you are just getting and setting and not really adding or deleting objects to, then you don't need to explicitly alloc init them.
2) If you have an Array or dictionary #property that you are adding or deleting objects to ,you need to explicitly alloc init them.
Are my above statements true? Would love to hear your inputs on this.
Thanks,
Mike
New code:
- (void)fetchImages{
//Fetch Item Brand Images
self.itemBrandImages = [[NSMutableDictionary alloc] init];
for (NSDictionary *itemBrand in self.itemBrands){
NSString *currentItemId = [itemBrand objectForKey:#"ITEM_ID"];
NSLog(#"Current Item Id in ItemList: %#",currentItemId);
NSString *currentItemImageUrl = [[#"http://anythingtogo.freeiz.com/images/"stringByAppendingString:currentItemId] stringByAppendingString:#".png"];
NSLog(#"Current Image URL in ItemList: %#",currentItemImageUrl);
NSURL *url = [NSURL URLWithString:currentItemImageUrl];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];
if (image == nil){
NSLog(#"Image not Present 1");
}else{
NSLog(#"Image Present 1");
[self.itemBrandImages setObject:#"Test" forKey:currentItemId];
}
}
This is another of those "I'm sure there's an easy answer to this" questions, but I find myself baffled.
I'm using the split view controller from the template. I'm successfully passing a NSString to the _detailItem variable, but am unable to use it to create and load an image into an UIImageView (named "stripImage").
It works up until:
[self.stripImage setImage:[UIImage imageNamed: _detailItem]];
If I put a string literal into the same line of code (like #"image20.jpg"), it works fine.
- (void)configureView
{
// Update the user interface for the detail item.
if (self.detailItem) {
NSLog(#"_detailItem is still: %#",_detailItem);
// correctly reports the name of the imagefile (for example: "image20.jpg"
[self.stripImage setImage:[UIImage imageNamed: _detailItem]];
NSLog(#"The image being shown is: %#",self.stripImage.image);
//returns "The image being shown is: (null)"
}
}
Please help keep my head from exploding. Thanks in advance.
... and I've tried it this way:
(in my Master view controller):
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"Selected row %i",[indexPath row]);
NSString *imageName = [[stories objectAtIndex:[indexPath row]] objectForKey:#"link"];
NSLog(#"The image is: %#", imageName);
// These two work, oddly enough...
self.detailViewController.detailTitle.text = [[stories objectAtIndex:[indexPath row]]
objectForKey:#"title"];
self.detailViewController.detailSubtitle.text = [[stories objectAtIndex:[indexPath row]]
objectForKey:#"subtitle"];
// this one, not so much...
[self.detailViewController loadUpImageWith:imageName];
}
and in my Detail view controller:
- (void)loadUpImageWith:(NSString *)what
{
NSString *path = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:[NSString
stringWithFormat:#"strips/%#", what]];
NSLog(#"The file's url is: %#",path);
UIImage *img = [UIImage imageWithContentsOfFile:path];
NSLog(#"The resultant image is: %#",img);
stripImage.image = img;
}
But here's the weird thing... If I replace the variable ("what" in this case) with a string literal:
NSString *path = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:[NSString
stringWithFormat:#"strips/%#", #"grumbles300.jpg"]];
... it works, displaying that one image. But I want to be able to use a variable there!!
Help me Obiwan Kenobi! You're my only hope.
Embarrassing operator error.
I was adding a buncha images to the bundle, but it apparently kept track of the folder that contained them, which needed to be added to the file name. I thought UIImage imageNamed: would track down the images, as long as they were contained in the main bundle. Apparently not.
Perhaps this would be useful to someone who's experiencing the same sort of brain fart.
After resolving this, it was easy to do this:
- (void)loadupDetailTitle:(NSString *)title
subtitle:(NSString *)subtitle
image:(NSString *)imageName
{
NSString *path = [#"strips/" stringByAppendingPathComponent:imageName];
stripImage.image = [UIImage imageNamed:path];
detailTitle.text = title;
detailSubtitle.text = subtitle;
}
I am trying to use the following code to load a UIButton and UITextField with information based upon a UISegmentedControl's current segment that is clicked but it is causing a SIGABRT crash.
Here is the code:
- (void)updateInfo {
NSLog(#"count1:%d", [self.accounts count]);
[self saveInfo];
NSLog(#"count2:%d", [self.accounts count]);
NSDictionary *dict = [self.accounts objectAtIndex:0];
NSData *imageData = [dict objectForKey:#"ProfileImage"];
UIImage *imageProfile = [UIImage imageWithData:imageData];
[image1 setImage:imageProfile];
NSDictionary *dict2 = [self.accounts objectAtIndex:1];
NSData *imageData2 = [dict2 objectForKey:#"ProfileImage"];
UIImage *imageProfile2 = [UIImage imageWithData:imageData2];
[image2 setImage:imageProfile2];
if ([self.accounts objectAtIndex:accountSC.selectedSegmentIndex] != nil) {
NSDictionary *dict = [self.accounts objectAtIndex:accountSC.selectedSegmentIndex];
//NSString *name = [dict objectForKey:#"Name"];
NSString *name = [accountSC titleForSegmentAtIndex:accountSC.selectedSegmentIndex];
[Name setText:name];
NSData *imageData = [dict objectForKey:#"ProfileImage"];
UIImage *imageProfile = [UIImage imageWithData:imageData];
[pictureButton setImage:imageProfile forState:UIControlStateNormal];
}
else {
Name.text = nil;
[pictureButton setImage:nil forState:UIControlStateNormal];
}
}
The first & second big block of code is temporary because I wanted to see the UIImage's based upon different objectAtIndex numbers.
Here is the console crash log:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFConstantString objectForKey:]: unrecognized selector sent to instance 0x2cc08'
Any reason why this can be happening? Do I need to post any other code I am using?
I really need help on this, I have been pulling my hair out!!!
Edit1:
I am using this code, also you were talking about isKindOfClass right?
Anyway this is the code:
NSDictionary *dict = [self.accounts objectAtIndex:1];
if ([dict isKindOfClass:[NSDictionary class]]) {
NSLog(#"YES");
}
else {
NSLog(#"NO");
}
Im testing now...
You're sending objectForKey: to an NSString object, specifically one that you've typed directly into your code somewhere in #"..." form rather than one you've created programmatically (or had created programmatically for you). Someone is putting something other than a dictionary into self.accounts.
NSDictionary: objectForKey:
objectForKey: returns the value associated with key, or nil if no value is associated with key.
key :A string identifying the value. If nil, just return nil.
(1)you should know the key is not blank
(2)you should know the object is not blank and the objects are the same type ,because you shouldn't use different kinds of type in a NSDictionary.
e.g. {#"key1":NSString,#"key2":NSArray} //this is a demonstration of error