I have set up the sample from parse.com where you can upload an image from the camera and then display all the images in a grid view.
What I want is to display only the recent image taken instead of a total grid view.
The sample is located here : Parse example
The images is being downloaded and placed in some sort of grid view.
The use NSMutableArray *allImages; to get all the images.
The images is being output with button classes and a link to a new view.
The new view then only contains the image from the grid view (the one you click).
I would like to instead of downloading all of the images and placing them inside a grid view - just to display the latest image.
They code used to take the image from a small thumbnail to the full image view is like this:
// When picture is touched, open a viewcontroller with the image
PFObject *theObject = (PFObject *)[allImages objectAtIndex:[sender tag]];
PFFile *theImage = [theObject objectForKey:#"imageFile"];
NSData *imageData;
imageData = [theImage getData];
UIImage *selectedPhoto = [UIImage imageWithData:imageData];
PhotoDetailViewController *pdvc = [[PhotoDetailViewController alloc] init];
pdvc.selectedImage = selectedPhoto;
[self presentViewController:pdvc animated:YES completion:nil];
The code to get allImages is like:
// Contains a list of all the BUTTONS
allImages = [images mutableCopy];
// This method sets up the downloaded images and places them nicely in a grid
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
NSMutableArray *imageDataArray = [NSMutableArray array];
// Iterate over all images and get the data from the PFFile
for (int i = 0; i < images.count; i++) {
PFObject *eachObject = [images objectAtIndex:i];
PFFile *theImage = [eachObject objectForKey:#"imageFile"];
NSData *imageData = [theImage getData];
UIImage *image = [UIImage imageWithData:imageData];
[imageDataArray addObject:image];
}
// Dispatch to main thread to update the UI
dispatch_async(dispatch_get_main_queue(), ^{
// Remove old grid
for (UIView *view in [photoScrollView subviews]) {
if ([view isKindOfClass:[UIButton class]]) {
[view removeFromSuperview];
}
}
// Create the buttons necessary for each image in the grid
for (int i = 0; i < [imageDataArray count]; i++) {
PFObject *eachObject = [images objectAtIndex:i];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *image = [imageDataArray objectAtIndex:i];
[button setImage:image forState:UIControlStateNormal];
button.showsTouchWhenHighlighted = YES;
[button addTarget:self action:#selector(buttonTouched:) forControlEvents:UIControlEventTouchUpInside];
button.tag = i;
button.frame = CGRectMake(THUMBNAIL_WIDTH * (i % THUMBNAIL_COLS) + PADDING * (i % THUMBNAIL_COLS) + PADDING,
THUMBNAIL_HEIGHT * (i / THUMBNAIL_COLS) + PADDING * (i / THUMBNAIL_COLS) + PADDING + PADDING_TOP,
THUMBNAIL_WIDTH,
THUMBNAIL_HEIGHT);
button.imageView.contentMode = UIViewContentModeScaleAspectFill;
[button setTitle:[eachObject objectId] forState:UIControlStateReserved];
[photoScrollView addSubview:button];
}
// Size the grid accordingly
int rows = images.count / THUMBNAIL_COLS;
if (((float)images.count / THUMBNAIL_COLS) - rows != 0) {
rows++;
}
int height = THUMBNAIL_HEIGHT * rows + PADDING * rows + PADDING + PADDING_TOP;
photoScrollView.contentSize = CGSizeMake(self.view.frame.size.width, height);
photoScrollView.clipsToBounds = YES;
});
});
I'm not an expert at this iOS-coding and I'm really just looking for a simple solution to display the recent image posted.
Looking through the posted example code, it would be a big undertaking to modify it to handle just a one image (mostly deleting a lot of yuck that synchs object ids). If you just want the quickest path to get started, you can do this:
// ...
// where you do the query for UserPhoto
[query orderByAscending:#"createdAt"];
// use the getFirst form of the query
[query getFirstObjectInBackgroundWithBlock:^(PFObject *object, NSError *error) {
if (!error) {
// build the objects array that the demo code expects, but out of just one object
NSArray *objects = #[ object ];
// the remainder of the code as it is
A lot of UI code can get simpler, too. But the key is to skip all of the grid/button building code and do something like this:
// ...
// inside the method called setUpImages:
// this loop will only run once since we have only one object in the array
for (int i = 0; i < [imageDataArray count]; i++) {
PFObject *eachObject = [images objectAtIndex:i];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *image = [imageDataArray objectAtIndex:i];
// you're essentially done here. add a big image view
// that replaces photoScrollView, then:
self.myBigImageView.image = image;
Hope that helps.
Related
How to move objects in this array? Tried everything. I cannot select an individual object.
self.images = [NSMutableArray array];
NSFileManager* manager = [NSFileManager new];
NSBundle* bundle = [NSBundle mainBundle];
NSDirectoryEnumerator* enumerator = [manager enumeratorAtPath:[bundle bundlePath]];
for (NSString* name in enumerator) {
if ([name hasSuffix:#"PawnWhite.png"]) {
for (int i = 0; i <= 7; i++) {
UIImage* image = [UIImage imageNamed:name];
[self.images addObject:image];
}
}
}
for (int i = 0; i < self.images.count; i++) {
CGPoint myPoint = CGPointMake(75.f, 0);
self.view = [[UIView alloc] initWithFrame:CGRectMake(84.f + myPoint.x * i, 870.f, 75.f, 75.f)];
self.imagesView = [[UIImageView alloc] initWithFrame:self.view.bounds];
self.imagesView.image = [self.images objectAtIndex:i];
[self.view addSubview:self.imagesView];
[valueView addSubview:self.view];
}
I have pictures in the array, mapped on main view. I need to change any of them that she had changed the location.
If you want to move objects around within an array - you just remove an item from one location, and add it to another, like this :
[self.images removeObjectAtIndex:index];
[self.images insertObject:object atIndex:newIndex];
In my project, I have my image files stored in jpeg format. The code below "works" in that it doesn't crash, but my images don't flip when they're supposed to. I threw a breakpoint in to ensure that the code is running--it is, but the images that are displayed aren't flipped. I'm guessing I'm missing something basic, but it's not jumping out at me.
if (self.isTimer == YES) {
// this is where images get dumped if they exist
NSMutableArray *imageArray = [[NSMutableArray alloc] init];
for (int imageNumber = 1; self.currentItem.photo != nil; imageNumber++) {
NSString *fileName = [NSString stringWithFormat:#"%#-%d", self.currentItem.photo, imageNumber];
if ([UIImage imageNamed:fileName]) {
UIImage *image = [UIImage imageNamed:fileName];
// test whether count is even or odd
if (self.currentItem.sideMultiplier.intValue == 1) {
// if there's only one side to be done, dump unflipped images in array
[imageArray addObject:image];
NSLog(#"regular image added to array");
} else {
// if there are 2 sides, determine if it's even or odd side
if (self.stretchSideMultiplierCount % 2 == 1) {
// add a unflipped image to the array
[imageArray addObject:image];
NSLog(#"regular image added to array");
} else {
// ** I want to add a FLIPPED IMAGE here
UIImage *flippedImage = [UIImage imageWithCGImage:image.CGImage scale:image.scale orientation:UIImageOrientationUpMirrored];
[imageArray addObject:flippedImage];
NSLog(#"flipped image added to array");
}
}
NSLog(#"%# added to imageArray", fileName);
} else {
break;
}
}
I followed this post, but nothing's happening.
How to flip UIImage horizontally?
I added #import <QuartzCore/QuartzCore.h> to my implementation file. Aside from that, I'm out of ideas re: how to flip an image horizontally.
UPDATE: Much easier solution
Rather than flipping the UIImage, I flipped the UIImageView. The code above I used to create my imageArray now looks like this:
if (self.isTimer == YES) {
// this is where images get dumped if they exist
NSMutableArray *imageArray = [[NSMutableArray alloc] init];
for (int imageNumber = 1; self.currentItem.photo != nil; imageNumber++) {
NSString *fileName = [NSString stringWithFormat:#"%#-%d", self.currentItem.photo, imageNumber];
if ([UIImage imageNamed:fileName]) {
UIImage *image = [UIImage imageNamed:fileName];
[imageArray addObject:image];
NSLog(#"image added to array");
NSLog(#"%# added to imageArray", fileName);
} else {
break;
}
}
and the code I used to flip my UIImageView is in the answer below.
Problem solved. Rather than flipping the UIImage, I flipped the UIImageView as follows:
self.myImageView.transform = CGAffineTransformMakeScale(-1, 1);
I have a wallpaper app that has a paged scrollview on the main view. each page of the scrollview displays 9 images.
When the view is scrolled I'm loading the next 10 pages of images and set the previous 10 pages uiimages that I've loaded to nil to prevent memory warnings.
The problem is when the view scrolls and so the following method of scrollview gets called, there is few seconds delay before the view can scroll even though I have put the block code that loads new images in dispatch_async.
and when I comment out the whole section of the code with dispatch stuff, there is no delay.
If anyone has any idea on why this happens. please please let me know.
Thank you all so much
- (void)scrollViewDidScroll:(UIScrollView *)scrollV
{
float fractionalPage = scrollView.contentOffset.x / self.view.frame.size.width;
if (curPageNum != lround(fractionalPage)) {
curPageNum = lround(fractionalPage);
//display the page number
pageNumLabel.text = [NSString stringWithFormat:#"%d",curPageNum+1];
pageNumLabel.alpha = 1.0;
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(dismissPageNum) userInfo:nil repeats:NO];
//loading more pages with 9 image in each
lastLoadedPageNum = MIN(lastLoadedPageNum + 10, numPages - 1);
dispatch_queue_t getImages = dispatch_queue_create("Getting Images", nil);
dispatch_async(getImages, ^{
for (int i = curPageNum + 4 ; i <= lastLoadedPageNum ; i++) {
int numPicsPerPage = 9;
if (picsNames.count%9 && i == numPages-1) {
numPicsPerPage = picsNames.count%9;
}
for (int j = 0 ; j < numPicsPerPage ; j++) {
UIImage *image = [brain imageWith:[picsNames objectAtIndex:(i*9) + j]];
dispatch_async(dispatch_get_main_queue(), ^{
//loading the image to imageview
UIImageView *imageView = (UIImageView *)[scrollView viewWithTag:IMAGE_VIEWS_TAG + (i*9) + j];
imageView.image = image;
});
}
}
});
//setting old imageview images to nil to release memory
int oldFirstLoadedPageNum = firtLoadedPageNum;
firtLoadedPageNum = MAX(curPageNum - 4, 0);
for (int i = oldFirstLoadedPageNum ; i < firtLoadedPageNum ; i++) {
int numPicsPerPage = 9;
if (picsNames.count%9 && i == numPages-1) {
numPicsPerPage = picsNames.count%9;
}
for (int j = 0 ; j < numPicsPerPage ; j++) {
UIImageView *imageView = (UIImageView *)[scrollView viewWithTag:IMAGE_VIEWS_TAG + (i*9) + j];
imageView.image = nil;
[((UIActivityIndicatorView *)[imageView viewWithTag:ACTIVITY_INDICATOR_TAG]) startAnimating];
}
}
}
}
Brain method imageWith:
-(UIImage *)imageWith:(NSString *)imageName
{
NSString *imagePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:imageName];
UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
if (!image && [self connected]) {
image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#/%#", picsURL, imageName]]]];
if (image) {
[UIImagePNGRepresentation(image) writeToFile:imagePath atomically:YES];
}
}
return image;
}
Clearly your code is looping which causes the delay. I think since the dispatch is inside the for loop it gets called only after a certain bit of iterations so that there is no real gain in using multi threading here.
Most likely your logic after the block with the nested for loops is causing the delay. Move that out into a separate method and run it in a separate thread.
As suggested by Mike Pollard I used
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,0)
instead of
dispatch_queue_create("Getting Images", nil)
and it solved the issue.
Thanks everyone.
I have a UIImageView on my storyboard, which is linked to an outlet in the code. When I run the code, it only shows the static picture that the storyboard shows, not the animation that I create programmatically. Any ideas?
for(int i=0; i<4; i++) {
UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:#"loading%d",i]];
[self.images addObject:image];
}
self.loadingView.animationImages = self.images;
self.loadingView.animationDuration = 2;
self.loadingView.animationRepeatCount = 1;
[self.loadingView startAnimating];
Note: loadingView is the UIImageView, images is an NSMutableArray.
If you want to make run time array you can use like this way.
NSMutableArray *images = [[NSMutableArray alloc] init];
for (int i = 1 ; i < 4; i++) {
[images addObject:[UIImage imageNamed:[NSString stringWithFormat: #"loading%d.jpg", i]]];
}
self.loadingView.animationImages = images;
self.loadingView.animationDuration = 2;
self.loadingView.animationRepeatCount = 1;
[self.loadingView startAnimating];
Hope this will help you. It's working fine for me.
I recommend you to use array directly like this.
NSArray *images = [[NSArray alloc] initWithObjects:
[UIImage imageNamed:#"1.jpg"],
[UIImage imageNamed:#"2.jpg"],
nil];
self.loadingView.animationImages = images;
self.loadingView.animationDuration = 2;
self.loadingView.animationRepeatCount = 1;
[self.loadingView startAnimating];
I'm trying to free up my apps memory and want to completely remove loadingImageView from memory when I tap a button. How do I do this?
-(IBAction)animationOneStart {
NSMutableArray *images = [[NSMutableArray alloc] initWithCapacity:88];
for(int count = 1; count <= 88; count++)
{
NSString *fileName = [NSString stringWithFormat:#"testPic1_%03d.jpg", count];
UIImage *frame = [UIImage imageNamed:fileName];
[images addObject:frame];
}
loadingImageView.animationImages = images;
loadingImageView.animationDuration = 5;
loadingImageView.animationRepeatCount = 1; //Repeats indefinitely
[loadingImageView startAnimating];
[images release];
}
-(IBAction)removeFromMemory {
//What do I add here?
}
Thanks!
Ok. If you want to remove UIImageView animation try this:
-(IBAction)removeFromMemory {
[loadingImageView stopAnimating]; //here animation stops
[loadingImageView removeFromSuperview]; // here view removes from view hierarchy
[loadingImageView release]; loadingImageView = nil; //clean memory
}
For remove CoreAnimation from UIView instance use method:
[view.layer removeAllAnimations];