How to Add UIImage to NSMutableArray - objective-c

I'm trying to add my UIImage from web service to my NSMutableArray using this code:
for (int i=0; i<[totalRowCountString intValue]; i++)
{
NSString *criticsRatingString = [[JSON valueForKeyPath:#"movies.ratings.critics_rating"] componentsJoinedByString:#" "];
NSLog(#"criticsRatingString: %#", criticsRatingString);
if ([criticsRatingString isEqualToString:#"Certified Fresh"])
{
self.ratingImage = [UIImage imageNamed:#"rt_certified_fresh.png"];
}
else if ([criticsRatingString isEqualToString:#"Fresh"])
{
self.ratingImage = [UIImage imageNamed:#"rt_fresh.png"];
}
else if ([criticsRatingString isEqualToString:#"Rotten"])
{
self.ratingImage = [UIImage imageNamed:#"rt_rotten.png"];
}
else if ([criticsRatingString isEqualToString:#"Spilled"])
{
self.ratingImage = [UIImage imageNamed:#"rt_spilled.png"];
}
else if ([criticsRatingString isEqualToString:#"Upright"])
{
self.ratingImage = [UIImage imageNamed:#"rt_upright.png"];
}
[tomatorRatingImages addObject:self.ratingImage];
NSLog(#"tomatoRatingImages: %#", tomatorRatingImages);
}
But my NSLog for tomatoRatingImages returns NULL. Any ideas why it returns NULL?
UPDATE: my NSMutableArray is already initialized in my viewWillAppear method.

You must initialize the array before adding objects to it.
NSMutableArray *tomatorRatingImages = [[NSMutableArray alloc] init];

NSMutableArray * tomatorRatingImages =[[NSMutableArray alloc]init];
[tomatorRatingImages addObject:[UIImage imageNamed:#"rt_spilled.png"]];
[tomatorRatingImages addObject:[UIImage imageNamed:#"rt_spilled1.png"]];
[tomatorRatingImages addObject:[UIImage imageNamed:#"rt_spilled2.png"]];
you can enter multiple image in NSMutableArray.

If you have a property for the NSMutableArray instance, it's better to write getter to initialize it. It takes care of initializing the variable only ones also it gets loaded only when it's required.
-(NSMutableArray *) tomatorRatingImages {
if(_tomatorRatingImages == nil) {
_tomatorRatingImages = [NSMutableArray alloc] init];
}
return _tomatorRatingImages;
}

Initialize like this
NSMutableArray * tomatorRatingImages =[[NSMutableArray alloc]initWithCapacity:3];

Related

Changing UIImageView dynamically

-(void)viewDidLoad {
NSMutableArray *coolImagesArray = [[NSMutableArray alloc] initWithObjects:#"active-1.jpg", #"active-2.jpg", #"active-3.jpg", #"active-4.jpg", #"active-5.jpg", nil];
}
-(void)someMethodWithData {
dispatch_async(dispatch_get_main_queue(), ^{
NSMutableArray *imagesArray = [[NSMutableArray alloc] init];
NSMutableString *inactiveString = [[NSMutableString alloc] init];
for (int i = 0; i < progress; i++) {
imageView.image = [UIImage imageNamed:[coolImagesArray objectAtIndex:i]];
inactiveString = [NSMutableString stringWithFormat:#"inactive-%d.png",i];
[imagesArray addObject:imageView];
}
UIImage *setImage = [UIImage imageNamed:#"inactive-1.png"];
for (int i = 0; i < [imagesArray count]; i++) {
[(UIImageView*)[imagesArray objectAtIndex:i] setImage:setImage];
}
});
}
This will always set the last or i(th) image correctly. It will not loop and change all the images I need. Is there another way to manage this?
imageView is pointing to one UIImageView object and in a loop you are changing the image of imageView not adding new UIImageView object to your array. All the objects inside the array pointing to 1 UIImageView object. So it is so normal that you can only change the last object's image only, because there is no other object in your array.
you should do it like:
dispatch_async(dispatch_get_main_queue(), ^{
NSMutableArray *imagesArray = [[NSMutableArray alloc] init];
NSMutableString *inactiveString = [[NSMutableString alloc] init];
for (int i = 0; i < progress; i++) {
UIImageView *temp = [[UIImageView alloc] initWithFrame:imageView.frame];
temp.image = [UIImage imageNamed:[coolImagesArray objectAtIndex:i]];
inactiveString = [NSMutableString stringWithFormat:#"inactive-%d.png",i];
[imagesArray addObject:temp];
}
UIImage *setImage = [UIImage imageNamed:#"inactive-1.png"];
for (int i = 0; i < [imagesArray count]; i++) {
[(UIImageView*)[imagesArray objectAtIndex:i] setImage:setImage];
}
});
For starters, I would create the image once so as to save memory.
I would also cast the object to a UIImageView (Not sure how that isn't getting flagged in xcode).
Lastly I would wrap it in a dispatch_async() to make sure it's happening on the main UI thread, because it could be getting called on a background thread and somehow the last image makes it to the main run loop, either way this is what it would look like:
dispatch_async(dispatch_get_main_queue(), ^{
UIImage *setimage = [UIImage imageNamed:#"set-image.png"];
for (int i = 0; i < [imagesArray count]; i++) {
[(UIImageView *)[imagesArray objectAtIndex:i] setImage:setimage]];
}
});

Image not displayed on UICollectionViewCell

I am trying to get images on contacts,here i used UICollectionViewCell but in the collection view i didn't get image for the contact,i get only name and number.Here my code is
- (IBAction)ContactDisplay:(id)sender {
_addressBookController = [[ABPeoplePickerNavigationController alloc] init];
[_addressBookController setPeoplePickerDelegate:self];
[self presentViewController:_addressBookController animated:YES completion:nil];
}
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker didSelectPerson:(ABRecordRef)person
{
[self displayPerson:person];
}
- (void)displayPerson:(ABRecordRef)person
{
NSString* name = (__bridge_transfer NSString*)ABRecordCopyValue(person,
kABPersonFirstNameProperty);
NSLog(#"%#",name);
NSString* phone = nil;
ABMultiValueRef phoneNumbers = ABRecordCopyValue(person,
kABPersonPhoneProperty);
if (ABMultiValueGetCount(phoneNumbers) > 0) {
phone = (__bridge_transfer NSString*)
ABMultiValueCopyValueAtIndex(phoneNumbers, 0);
} else {
phone = #"[None]";
}
NSLog(#"%#",phone);
UIImage *img ;
if (person != nil && ABPersonHasImageData(person)) {
if ((&ABPersonCopyImageDataWithFormat) != nil ) {
img= [UIImage imageWithData:(__bridge NSData *)ABPersonCopyImageDataWithFormat(person, kABPersonImageFormatThumbnail)];
}
} else {
NSString *imageUrlString = #"http://www.google.co.in/intl/en_com/images/srpr/logo1w.png";
NSURL *url = [NSURL URLWithString:imageUrlString];
NSData *data = [[NSData alloc] initWithContentsOfURL:url];
img= [UIImage imageWithData:data];
}
NSString *string ;//
string =[NSString stringWithFormat:#"%#",img];
NSLog(#"%#",img);
self.name.text=name;
self.number.text=phone;
[self.nameArray addObject:name];
[self.imageArray addObject:string];
NSLog(#"%#",self.nameArray);
NSLog(#"%#",self.imageArray);
[self.collectionView reloadData];
[self.collectionView performBatchUpdates:^{
[self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:0]];
} completion:nil];
}
finally an image array i got like this
(
"add-button.png",
"<UIImage: 0x17e56c80>, {148, 148}"
)
On image array every image like display .PNG format it will display fine ,then how can modify it.
Can you please suggest me how can you solve this,thank you.
I don't fully agree with everything you're doing there but I think you're getting your data wrong. Try using this instead when you're fetching the ABPerson image data.
if (person != nil) {
CFDataRef imageData = ABPersonCopyImageData(person);
NSData *data = CFBridgingRelease(imageData);
if (data != nil && data.length > 10){ //arbitrary length to make sure our data object isnt' really empty
img = [UIImage imageWithData:data];
} else {
NSString *imageUrlString = #"http://www.google.co.in/intl/en_com/images/srpr/logo1w.png";
NSURL *url = [NSURL URLWithString:imageUrlString];
NSData *data = [[NSData alloc] initWithContentsOfURL:url];
img= [UIImage imageWithData:data];
}
Then don't store your images as Strings in your array. Store them either as NSData or UIImage, but NOT STRINGS.
so
[myArray addObject:img]; //not the string.
And when you fetch it later, make sure you treat is as an image and not as a string
on your storyboard, select the image and look at the properties panel.
there are "Installed" options at the bottom. check the topmost "Installed" box.
I think there might be issue with conversion of image to string
NSString *string ;//
string =[NSString stringWithFormat:#"%#",img];
Add image to image array without converting to string
[self.imageArray addObject:img];
I do it like this in my app. Assuming 'person' is an ABRecordRef.
NSMutableDictionary *contactInfoDict = [[NSMutableDictionary alloc]
initWithObjects:#[#"", #"", #"", #""]
forKeys:#[#"firstName", #"lastName", #"birthday", #"picture"]];
CFTypeRef generalCFObject;
// Firtname
generalCFObject = ABRecordCopyValue(person, kABPersonFirstNameProperty);
if (generalCFObject) {
[contactInfoDict setObject:(__bridge NSString *)generalCFObject forKey:#"firstName"];
CFRelease(generalCFObject);
}
// Lastname
generalCFObject = ABRecordCopyValue(person, kABPersonLastNameProperty);
if (generalCFObject) {
[contactInfoDict setObject:(__bridge NSString *)generalCFObject forKey:#"lastName"];
CFRelease(generalCFObject);
}
// Birthday
generalCFObject = ABRecordCopyValue(person, kABPersonBirthdayProperty);
if (generalCFObject) {
[contactInfoDict setObject:(__bridge NSString *)generalCFObject forKey:#"birthday"];
NSLog(#"Date : %#", [contactInfoDict objectForKey:#"birthday"]);
CFRelease(generalCFObject);
}
// User image
CFDataRef photo = ABPersonCopyImageData(person);
if (photo) {
CFRelease(photo);
UIImage *image = [UIImage imageWithData:(__bridge NSData*)photo];
[contactInfoDict setObject:image forKey:#"picture"];
}

How to remove array object from for loop

please Help me. I stuck here when deleting an object from array.
for (id obj in self.arrSavedImage)
{
Class cls = [obj class];
id newObj = [[cls alloc] init];
//UIImage *img = nil;
if([newObj isKindOfClass:[UIImage class]]){
NSLog(#"class type %#", [newObj class]);
}
else{
[self.arrSavedImage removeObject:obj];
}
}
Thank You.
You shouldn't remove objects from an array you are enumerating over. Better is to keep a list of the objects you want to delete, and then delete them when you've finished enumerating the original array:
NSMutableArray *toDelete = [NSMutableArray new];
for (id obj in self.arrSavedImage)
{
Class cls = [obj class];
id newObj = [[cls alloc] init];
if([newObj isKindOfClass:[UIImage class]]){
NSLog(#"class type %#", [newObj class]);
}
else{
[toDelete addObject:obj];
}
}
for (id obj in toDelete)
[self.arrSavedImage removeObject:obj];
NSMutableArray *itemsToDelete = [[NSMutableArray alloc] init];
for (id obj in self.arrSavedImage)
{
Class cls = [obj class];
id newObj = [[cls alloc] init];
//UIImage *img = nil;
if([newObj isKindOfClass:[UIImage class]]){
NSLog(#"class type %#", [newObj class]);
}
else{
[itemsToDelete addObject:obj];
}
}
[self.arrSavedImage removeObjectsInArray:itemsToDelete];
You can not remove the object in array while in loop.
You should create a new array with existing array and remove objects from it. Then replace the old array with editedArray.
NSMutableArray * editedArray = [[NSMutableArray alloc] initWithArray:self.arrSavedImage];
for (id obj in self.arrSavedImage)
{
Class cls = [obj class];
id newObj = [[cls alloc] init];
//UIImage *img = nil;
if([newObj isKindOfClass:[UIImage class]]){
NSLog(#"class type %#", [newObj class]);
}
else{
[editedArray removeObject:obj];
}
}
[self.arrSavedImage setArray:editedArray];
editedArray = nil;

Add UIImage to NSMutableArray

I have a problem with a piece of code that should add images to a NSMutableArray. For some reason the images are not added (the count of the array stays at 0). Can someone please tell me what I'm doing wrong here?
- (void)incomingNotification:(NSNotification *)notification {
[self.popoverController dismissPopoverAnimated:YES];
_URLString = [notification object];
for (int i = 0; i < [[self returnLargeUrls] count]; i++) {
[self getImageFromURL:_URLString];
}
}
And in getImageFromUrl::
-(NSData *) getImageFromURL:(NSString *)fileURL {
UIImage *result;
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:fileURL]];
result = [UIImage imageWithData:data];
[self.pageImages addObject:result];
NSLog(#"%d", self.pageImages.count);
return data;
}
The first thing to check would be that you property pageImages is not nil to begin with.
You can check that like:
if(!pageImages)
NSLog(#"The NSMutableArray pageImages is NIL. Damn... :(");
This is most likely your problem.
Make sure you alloc init your NSMutableArray first.
Make sure your NSData is not nil after fetching contents from URL. NSLog(#"%#", data);

How to load several photos with assetForURL with a list of URLs

For a list of URLs I need to load the photos with ALAssetsLibrary:assetForURL, and this within one method.
Since this method works async but it is not iterating over the passed list of URLs, as we all know.
I found this snippet (which should work):
- (void)loadImages:(NSArray *)imageUrls loadedImages:(NSArray *)loadedImages callback: (void(^)(NSArray *))callback
{
if (imageUrls == nil || [imageUrls count] == 0) {
callback(loadedImages);
}
else {
NSURL *head = [imageUrls head];
__unsafe_unretained id unretained_self = self;
ALAssetsLibrary* library = [[ALAssetsLibrary alloc] init];
[library assetForURL:head resultBlock:^(ALAsset *asset) {
ALAssetRepresentation *assetRepresentation = asset.defaultRepresentation;
UIImage *image = [UIImage imageWithCGImage:assetRepresentation.fullResolutionImage scale:assetRepresentation.scale orientation:(UIImageOrientation)assetRepresentation.orientation];
[unretained_self loadImages:[imageUrls tail] loadedImages:[loadedImages arrayByAddingObject:image] callback:callback];
} failureBlock:^(NSError *error) {
[unretained_self loadImages:[imageUrls tail] loadedImages:loadedImages callback:callback];
}];
}
}
How do I write the method definition in the form (above all the callback)
void loadImages(NSArray *imageUrls, NSArray *loadedImages, ...) ?
How do I call this method from another method (again mainly the callback part) ?
Can the callback be in the calling method or a 3rd method needed for this? and how does this method need to be written?
I have found the snippet here: http://www.calebmadrigal.com/functional-programming-deal-asynchronicity-objective-c/
Use NSThread to call the loadImages method.
NSMutableArray *imageCollection = [NSThread detachNewThreadSelector:#selector (loadImages:)
toTarget:self
withObject:imageUrlsCollection];
- (NSMutableArray *)loadImages:(NSArray *)imageUrls
{
ALAssetsLibrary* library = [[ALAssetsLibrary alloc] init];
NSMutableArray *loadedImages = [[NSMutableArray alloc] init];
#try
{
for(int index = 0; index < [imageUrls count]; index++)
{
NSURL *url = [imageUrls objectAtIndex:index];
[library assetForURL:url resultBlock:^(ALAsset *asset) {
ALAssetRepresentation *assetRepresentation = asset.defaultRepresentation;
dispatch_async(dispatch_get_main_queue(), ^{
UIImage *image = [UIImage imageWithCGImage:assetRepresentation.fullResolutionImage scale:assetRepresentation.scale orientation:(UIImageOrientation)assetRepresentation.orientation];
[loadedImages addObject:image];
});
} failureBlock:^(NSError *error) {
NSLog(#"Failed to get Image");
}];
}
}
#catch (NSException *exception)
{
NSLog(#"%s\n exception: Name- %# Reason->%#", __PRETTY_FUNCTION__,[exception name],[exception reason]);
}
#finally
{
return loadedImages;
}
}
Note: With ARC,take care about invalid attempt to access ALAssetPrivate past the lifetime of its owning ALAssetsLibrary issue
Here is the fix :)