object inside NSMutableArray - ios

I've a tableview which has list of images and image thumbnail (image list and thumbnails are parsed from JSON object), I'm adding image data objects to imagesArray like this -
ImageData *imageDataObject = [[ImageData alloc]initWithImageId:[[imageListArray
objectAtIndex:indexPath.row] imageId] imageData:imageData];
[imagesArray addObject:imageDataObject];
ImageData object
#property (nonatomic, strong) NSString* imageId;
#property (nonatomic, strong) NSData* imageData;
allImagesArray like this
[ImageData object1,ImageData object2,....]
I want to assign imageData of the object from this array based on selectedImageId to
UIImage* image =[[UIImage alloc] initWithData:........];
I'm not able to think of a way to get to that imageData based on selectedImageId
Please help.
Update -
Thank you all for the help, I could do it.

One of the possible way will be, iterate through the array, find your selectedImageId from the dictionary and use it.
Example:
ImageData *imageDataObject = nil;
for(int i=0; i<allImagesArray.count;i++){
NSDictionary *dict= allImagesArray[i];
imageDataObject = [dict objectForKey:selectedImageId];
if(imageDataObject != nil){
UIImage* image =[[UIImage alloc] initWithData:........];
//do whatever
break;
}
}
As per your EDIT:
What you have is an array of ImageData objects [ImageData1,ImageData2,...]. For each ImageData object, you have imageId and imageData property and what you want is simply compare the selectedImageId with this imageId and get the imageData from that.
So for that, in your PPImageViewController, you can iterate the allImagesArray like this and get the imageData.
for(ImageData* imgDataObj in self.allImagesArray){
if([imgDataObj.imageId isEqualToString:self.selectedImageId]){
UIImage* image =[[UIImage alloc] initWithData:imgDataObj.imageData];
}
}

So you have:
NSArray* allImagesArray = #[#{#"some_image_id_in_NSString_1":#"the data in NSData 1"}, #{#"some_image_id_in_NSString_2":#"the data in NSData 2"}];
As a property of PPImageViewController.
Assuming the imageid is an NSString and imagedata is NSData, you can create a method something like this on PPImageViewController:
- (UIImage*) findSelectedImage
{
UIImage* selectedImage;
for(NSDictionary* d in allImagesArray)
{
NSString* currentKey = [[d allKeys] objectAtIndex:0];
if([currentKey isEqualToString:[self selectedImageId]])
{
NSData* imageData = [d objectForKey:currentKey];
selectedImage = [UIImage imageWithData:imageData];
break;
}
}
return selectedImage;
}
Then call it like this, maybe on your viewDidLoad method:
UIImage* selectedImage = [self findSelectedImage];
Hope it help.

I see you are adding ImageData objects directly into the Array. You could have just used a NSDictionary instead. The key can be imageID (assuming it to be unique) and value will be the imageData object. Then pass the dictionary instead of array to PPImageViewController.
NSMutableDictionary *imageData = [NSMutableDictionary dictionary];
ImageData *imageDataObject = [[ImageData alloc]initWithImageId:[[imageListArray
objectAtIndex:indexPath.row] imageId] imageData:imageData];
[imageData setObject:imageDataObject forKey:imageId];
And then within PPImageViewController, you can easily get the imageDataObject based on selected imageID like this:
ImageData *imageDataObject = allImagesDictionary[selectedImageID];
EDIT:
NSArray *imageIndexes = [allImagesDictionary allKeys];
// Now use imageIndexes to populate your table. This will guarantee the order
// Fetch the imageId
selectedImageID = imageIndexes[indexPath.row];
// Fetch the imageData
ImageData *imageDataObject = allImagesDictionary[selectedImageID];

Related

Receiveing array of Images from CoreData

I've created NSManagedObject* imagesArrayData that stores strings (paths) to images stored in the documents directory:
- (void)setImagesArray:(NSMutableArray *)imagesArray {
NSMutableArray* newImagesArray = [NSMutableArray new];
int i = 1;
for (UIImage* image in imagesArray) {
//generate path to createdFile
NSString* fileName = [NSString stringWithFormat:#"%#_%d", self.name, i];
NSString* filePath = [self documentsPathForFileName:fileName];
//save image to disk
NSData *imageData = UIImagePNGRepresentation(image);
[imageData writeToFile:filePath atomically:YES];
//add image path to CoreData
[newImagesArray addObject:filePath];
i++;
}
//set new value of imagesArray
imagesArrayData = [NSKeyedArchiver archivedDataWithRootObject:newImagesArray];
I am now not showing pathsToImages in header file, but property imagesArray:
-(NSMutableArray*) imagesArray {
NSMutableArray* images = [NSMutableArray new];
NSArray* imagePaths = [NSKeyedUnarchiver unarchiveObjectWithData:imagesArrayData];
for (NSString* imagePath in imagePaths) {
UIImage *image = [[UIImage alloc] initWithContentsOfFile: imagePath];
[images addObject:image];
}
return images;
The problem is, that whenever I want to get to [imagesArray objectatIndex:xxx], the imagesArray getter is called, and it takes time to recreate the full array. When trying to switch fast between images, the UI slows down.
What would be the elegant way to overcome this problem? Maybe creating another array full of images and updating it from time to time? Maybe something else? Please, help.
One thing you could do is refactor your getter to lazily load the array. If it is already defined, simply return it. If not, build it:
-(NSMutableArray*) imagesArray
{
if (!_imagesArray)
{
NSMutableArray* _imagesArray = [NSMutableArray new];
NSArray* imagePaths =
[NSKeyedUnarchiver unarchiveObjectWithData: imagesArrayData];
for (NSString* imagePath in imagePaths)
{
UIImage *image = [[UIImage alloc] initWithContentsOfFile: imagePath];
[_imagesArray addObject:image];
}
return _imagesArray;
}
I'm not sure what you mean about updating an array of images from time to time.
If your array of image names changes you will need some method to respond to those changes.

I am trying to save to and retrieve from NSMutableDictionary

Hello everyone !, I have an app that requires saving multiple Images. I want to save these images in a NSMutableDictionary as they may be accessed at another time..
I have a NSDictionaryFile class that looks like this set up as
#interface NSDictionaryFile : NSMutableDictionary
-(NSMutableDictionary *) mutDict {
mutDict = [[NSMutableDictionary alloc]initWithCapacity:24];
return mutDict;
}
-(void) addToDictionary : (NSData *) nsData : (NSString *) key {
NSString *tempStringKey = [NSString stringWithFormat:#"%#",key];
[mutDict setObject:[NSData dataWithData:nsData] forKey:tempStringKey];
NSLog(#"The Key is %# And The nsData has this %#",key,nsData);
}
-(NSData *) getFromDict : (NSData *) getNSData : (NSString *) getKey {
NSString *tempStringKey = [NSString stringWithFormat:#"%#",getKey];
NSData *tempData = [mutDict objectForKey:tempStringKey];
getNSData = [NSData dataWithData:tempData];
return getNSData;
}
I am saving to the above class from
#interface PhotoViewController : UIViewController<UIImagePickerControllerDelegate,UINavigationControllerDelegate>
-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
image = [info valueForKey:UIImagePickerControllerOriginalImage];
NSData *imgData = UIImagePNGRepresentation(image);
NSString *imageString;
num = 1;
imageString = [NSString stringWithFormat:#"imageKey%i",num];
[[NSDictionaryFile sharedDictionary] addToDictionary:imgData :imageString];
And I am retrieving it like this in the View Did Load like so,
-(void)viewDidLoad {
NSData *tempData;
NSData *imageData;
_num = 1;
imageString = [NSString stringWithFormat:#"imageKey%i",_num];
[[NSDictionaryFile sharedDictionary]getFromDict:tempData :imageString];
self.imageView.image = [UIImage imageWithData:imageData];
}
When the data is being saved to the NSDictionaryFie.m I know it is going because I am NSLog(#"The Image Data is %#",nsData); and my print out is , as would be expected.
89504e47 0d0a1a0a 0000000d 49484452 00000215 00000155 08020000 00d7368a d8000000 01735247 4200aece 1ce90000 001c6944 4f540000 00020000 00000000 00ab0000 00280000 00ab0000 00aa0003 41798433 c89e0000 40004944 41547801 a4bd079c 2547752f 7c677636 2a2192f1 b3fd6c63 3f6cb009 42486857 4802990c 1212b2c0 809f6d6c 30185bc0 27139456 bbda202d ca5aadb4 2badc2ae 36e79d0d b3333b39 e77c676e cef9debe b7730ef5 fed53d33 5a09f8de 07dffdd5 afe77475 d5a953a7
So , when the PickerdidFinisPicking , the image shows in my imageView, but when I try to retrieve it i get null.
If someone can tell me where I am going wrong it is much appreciated.
Regards
JZ
I think the error is pretty simple:
you are not using the return value from getFromDict, but an uninitialized variable imageData.
I think you should call your method and use the return value, like this
-(void)viewDidLoad {
NSData *tempData;
NSData *imageData;
_num = 1;
imageString = [NSString stringWithFormat:#"imageKey%i",_num];
imageData=[[NSDictionaryFile sharedDictionary]getFromDict:tempData :imageString];
self.imageView.image = [UIImage imageWithData:imageData];
}
Besides the getter methods seems overly complicated to me:
-(NSData *) getFromDict : (NSData *) getNSData : (NSString *) getKey {
NSString *tempStringKey = [NSString stringWithFormat:#"%#",getKey];
NSData *tempData = [mutDict objectForKey:tempStringKey];
getNSData = [NSData dataWithData:tempData];
return getNSData;
}
You pass the method an NSData which you just use to store a value and pass it back to the caller. It' useless to pass such a parameter.
Have you tried a slimmer method?
-(NSData *) getFromDict : (NSString *) getKey {
return[mutDict objectForKey:getKey];
}

Convert array of image path into base64 encoded string.?

I want to convert array of Image Paths which are in document directory into Encoded baSE 64 string.
Here is my code
NSArray *recipeImages = [savedImagePath valueForKey:#"Image"];
this array contains path of the images (MULTIPLE IMAGES).
This is how array looks in Logs.
Saved Images == (
"/Users/ZAL02M/Library/Developer/CoreSimulator/Devices/F1F3C01E-8686-4367-82FB-80B003E2F416/data/Containers/Data/Application/694494B1-0DCA-497A-B8B0-586276EEF240/Documents/cached0.png",
"/Users/ZAL02M/Library/Developer/CoreSimulator/Devices/F1F3C01E-8686-4367-82FB-80B003E2F416/data/Containers/Data/Application/694494B1-0DCA-497A-B8B0-586276EEF240/Documents/cached1.png"
)
How to make base64 string ???
Try this to cycle all your images and save each encoded string into a new array:
NSMutableArray *encodedImages = [NSMutableArray new];
for (NSString *path in recipeImages)
{
UIImage *image = [UIImage imageWithContentsOfFile:path];
NSData *imageData = UIImagePNGRepresentation(image);
NSString *dataString = [imageData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
[encodedImages addObject:dataString];
}
Convert your ImagePaths (Strings) to NSData and from NSData back to string via base64EncodedStringWithOptions:
Here the code:
NSArray *recipeImages = [savedImagePath valueForKey:#"Image"];
NSMutableArray *mutableBase64StringsArray = #[].mutableCopy;
for (NSString *imagePath in recipeImages)
{
NSData *imagePathData = [imagePath dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64ImagePath = [imagePathData base64EncodedStringWithOptions:0];
[mutableBase64StringsArray addObject:base64ImagePath];
}
In the mutableBase64StringsArray you have all imagePaths as base64 encoded strings.
Look at this post from SO for more explanations: Base64 Decoding in iOS 7+
you can try this
Encoding :
- (NSString *)encodeToBase64String:(UIImage *)image {
return [UIImagePNGRepresentation(image) base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
}
Decoding :
- (UIImage *)decodeBase64ToImage:(NSString *)strEncodeData {
NSData *data = [[NSData alloc]initWithBase64EncodedString:strEncodeData options:NSDataBase64DecodingIgnoreUnknownCharacters];
return [UIImage imageWithData:data];
}
To get image from your path you can use this code
NSString* imagePath = [recipeImages objectAtIndex:i];
UIImage *image = [[UIImage alloc] initWithContentsOfFile:imagePath];
Then add encoded content to your array.
Hope it helps.

image not showing in UIImage from cached data

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

Iterating an NSMutableDictionary with UIImage not working

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];
}
}

Resources