Last active
August 29, 2015 14:08
-
-
Save gabanox/543df2b348c7bef890a2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// ViewController.m | |
// SavingImagesTutorial | |
// | |
// Created by Sidwyn Koh on 29/1/12. | |
// Copyright (c) 2012 Parse. All rights reserved. | |
// | |
// Photo credits: Stock Exchange (http://www.sxc.hu/) | |
#import "ViewController.h" | |
#import "PhotoDetailViewController.h" | |
@implementation ViewController | |
#define PADDING_TOP 0 // For placing the images nicely in the grid | |
#define PADDING 4 | |
#define THUMBNAIL_COLS 4 | |
#define THUMBNAIL_WIDTH 75 | |
#define THUMBNAIL_HEIGHT 75 | |
- (void)didReceiveMemoryWarning | |
{ | |
[super didReceiveMemoryWarning]; | |
// Release any cached data, images, etc that aren't in use. | |
} | |
#pragma mark - Main methods | |
- (IBAction)refresh:(id)sender | |
{ | |
NSLog(@"Showing Refresh HUD"); | |
refreshHUD = [[MBProgressHUD alloc] initWithView:self.view]; | |
[self.view addSubview:refreshHUD]; | |
// Register for HUD callbacks so we can remove it from the window at the right time | |
refreshHUD.delegate = self; | |
// Show the HUD while the provided method executes in a new thread | |
[refreshHUD show:YES]; | |
PFQuery *query = [PFQuery queryWithClassName:@"UserPhoto"]; | |
PFUser *user = [PFUser currentUser]; | |
[query whereKey:@"user" equalTo:user]; | |
[query orderByAscending:@"createdAt"]; | |
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) { | |
if (!error) { | |
// The find succeeded. | |
if (refreshHUD) { | |
[refreshHUD hide:YES]; | |
refreshHUD = [[MBProgressHUD alloc] initWithView:self.view]; | |
[self.view addSubview:refreshHUD]; | |
// The sample image is based on the work by http://www.pixelpressicons.com, http://creativecommons.org/licenses/by/2.5/ca/ | |
// Make the customViews 37 by 37 pixels for best results (those are the bounds of the build-in progress indicators) | |
refreshHUD.customView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"37x-Checkmark.png"]]; | |
// Set custom view mode | |
refreshHUD.mode = MBProgressHUDModeCustomView; | |
refreshHUD.delegate = self; | |
} | |
NSLog(@"Successfully retrieved %d photos.", objects.count); | |
// Retrieve existing objectIDs | |
NSMutableArray *oldCompareObjectIDArray = [NSMutableArray array]; | |
for (UIView *view in [photoScrollView subviews]) { | |
if ([view isKindOfClass:[UIButton class]]) { | |
UIButton *eachButton = (UIButton *)view; | |
[oldCompareObjectIDArray addObject:[eachButton titleForState:UIControlStateReserved]]; | |
} | |
} | |
NSMutableArray *oldCompareObjectIDArray2 = [NSMutableArray arrayWithArray:oldCompareObjectIDArray]; | |
// If there are photos, we start extracting the data | |
// Save a list of object IDs while extracting this data | |
NSMutableArray *newObjectIDArray = [NSMutableArray array]; | |
if (objects.count > 0) { | |
for (PFObject *eachObject in objects) { | |
[newObjectIDArray addObject:[eachObject objectId]]; | |
} | |
} | |
// Compare the old and new object IDs | |
NSMutableArray *newCompareObjectIDArray = [NSMutableArray arrayWithArray:newObjectIDArray]; | |
NSMutableArray *newCompareObjectIDArray2 = [NSMutableArray arrayWithArray:newObjectIDArray]; | |
if (oldCompareObjectIDArray.count > 0) { | |
// New objects | |
[newCompareObjectIDArray removeObjectsInArray:oldCompareObjectIDArray]; | |
// Remove old objects if you delete them using the web browser | |
[oldCompareObjectIDArray removeObjectsInArray:newCompareObjectIDArray2]; | |
if (oldCompareObjectIDArray.count > 0) { | |
// Check the position in the objectIDArray and remove | |
NSMutableArray *listOfToRemove = [[NSMutableArray alloc] init]; | |
for (NSString *objectID in oldCompareObjectIDArray){ | |
int i = 0; | |
for (NSString *oldObjectID in oldCompareObjectIDArray2){ | |
if ([objectID isEqualToString:oldObjectID]) { | |
// Make list of all that you want to remove and remove at the end | |
[listOfToRemove addObject:[NSNumber numberWithInt:i]]; | |
} | |
i++; | |
} | |
} | |
// Remove from the back | |
NSSortDescriptor *highestToLowest = [NSSortDescriptor sortDescriptorWithKey:@"self" ascending:NO]; | |
[listOfToRemove sortUsingDescriptors:[NSArray arrayWithObject:highestToLowest]]; | |
for (NSNumber *index in listOfToRemove){ | |
[allImages removeObjectAtIndex:[index intValue]]; | |
} | |
} | |
} | |
// Add new objects | |
for (NSString *objectID in newCompareObjectIDArray){ | |
for (PFObject *eachObject in objects){ | |
if ([[eachObject objectId] isEqualToString:objectID]) { | |
NSMutableArray *selectedPhotoArray = [[NSMutableArray alloc] init]; | |
[selectedPhotoArray addObject:eachObject]; | |
if (selectedPhotoArray.count > 0) { | |
[allImages addObjectsFromArray:selectedPhotoArray]; | |
} | |
} | |
} | |
} | |
// Remove and add from objects before this | |
[self setUpImages:allImages]; | |
} else { | |
[refreshHUD hide:YES]; | |
// Log details of the failure | |
NSLog(@"Error: %@ %@", error, [error userInfo]); | |
} | |
}]; | |
} | |
- (IBAction)cameraButtonTapped:(id)sender | |
{ | |
// Check for camera | |
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera] == YES) { | |
// Create image picker controller | |
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init]; | |
// Set source to the camera | |
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera; | |
// Delegate is self | |
imagePicker.delegate = self; | |
// Show image picker | |
[self presentViewController:imagePicker animated:YES completion:nil]; | |
} | |
else{ | |
// Device has no camera | |
UIImage *image; | |
int r = arc4random() % 5; | |
switch (r) { | |
case 0: | |
image = [UIImage imageNamed:@"ParseLogo.jpg"]; | |
break; | |
case 1: | |
image = [UIImage imageNamed:@"Crowd.jpg"]; | |
break; | |
case 2: | |
image = [UIImage imageNamed:@"Desert.jpg"]; | |
break; | |
case 3: | |
image = [UIImage imageNamed:@"Lime.jpg"]; | |
break; | |
case 4: | |
image = [UIImage imageNamed:@"Sunflowers.jpg"]; | |
break; | |
default: | |
break; | |
} | |
// Resize image | |
UIGraphicsBeginImageContext(CGSizeMake(640, 960)); | |
[image drawInRect: CGRectMake(0, 0, 640, 960)]; | |
UIImage *smallImage = UIGraphicsGetImageFromCurrentImageContext(); | |
UIGraphicsEndImageContext(); | |
NSData *imageData = UIImageJPEGRepresentation(smallImage, 0.05f); | |
[self uploadImage:imageData]; | |
} | |
} | |
- (void)uploadImage:(NSData *)imageData | |
{ | |
PFFile *imageFile = [PFFile fileWithName:@"Image.jpg" data:imageData]; | |
HUD = [[MBProgressHUD alloc] initWithView:self.view]; | |
[self.view addSubview:HUD]; | |
// Set determinate mode | |
HUD.mode = MBProgressHUDModeDeterminate; | |
HUD.delegate = self; | |
HUD.labelText = @"Uploading"; | |
[HUD show:YES]; | |
// Save PFFile | |
[imageFile saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) { | |
if (!error) { | |
//Hide determinate HUD | |
[HUD hide:YES]; | |
// Show checkmark | |
HUD = [[MBProgressHUD alloc] initWithView:self.view]; | |
[self.view addSubview:HUD]; | |
// The sample image is based on the work by http://www.pixelpressicons.com, http://creativecommons.org/licenses/by/2.5/ca/ | |
// Make the customViews 37 by 37 pixels for best results (those are the bounds of the build-in progress indicators) | |
HUD.customView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"37x-Checkmark.png"]]; | |
// Set custom view mode | |
HUD.mode = MBProgressHUDModeCustomView; | |
HUD.delegate = self; | |
// Create a PFObject around a PFFile and associate it with the current user | |
PFObject *userPhoto = [PFObject objectWithClassName:@"UserPhoto"]; | |
[userPhoto setObject:imageFile forKey:@"imageFile"]; | |
// Set the access control list to current user for security purposes | |
userPhoto.ACL = [PFACL ACLWithUser:[PFUser currentUser]]; | |
PFUser *user = [PFUser currentUser]; | |
[userPhoto setObject:user forKey:@"user"]; | |
[userPhoto saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) { | |
if (!error) { | |
[self refresh:nil]; | |
} | |
else{ | |
// Log details of the failure | |
NSLog(@"Error: %@ %@", error, [error userInfo]); | |
} | |
}]; | |
} | |
else{ | |
[HUD hide:YES]; | |
// Log details of the failure | |
NSLog(@"Error: %@ %@", error, [error userInfo]); | |
} | |
} progressBlock:^(int percentDone) { | |
// Update your progress spinner here. percentDone will be between 0 and 100. | |
HUD.progress = (float)percentDone/100; | |
}]; | |
} | |
- (void)setUpImages:(NSArray *)images | |
{ | |
// 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; | |
}); | |
}); | |
} | |
- (void)buttonTouched:(id)sender { | |
// 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]; | |
} | |
#pragma mark - View lifecycle | |
- (void)viewDidLoad | |
{ | |
[super viewDidLoad]; | |
allImages = [[NSMutableArray alloc] init]; | |
} | |
- (void)viewDidUnload | |
{ | |
[super viewDidUnload]; | |
// Release any retained subviews of the main view. | |
// e.g. self.myOutlet = nil; | |
} | |
- (void)viewWillAppear:(BOOL)animated | |
{ | |
[super viewWillAppear:animated]; | |
} | |
- (void)viewDidAppear:(BOOL)animated | |
{ | |
[super viewDidAppear:animated]; | |
} | |
- (void)viewWillDisappear:(BOOL)animated | |
{ | |
[super viewWillDisappear:animated]; | |
} | |
- (void)viewDidDisappear:(BOOL)animated | |
{ | |
[super viewDidDisappear:animated]; | |
} | |
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation | |
{ | |
// Return YES for supported orientations | |
return (interfaceOrientation == UIInterfaceOrientationPortrait); | |
} | |
#pragma mark - | |
#pragma mark UIImagePickerControllerDelegate methods | |
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info | |
{ | |
// Access the uncropped image from info dictionary | |
UIImage *image = [info objectForKey:@"UIImagePickerControllerOriginalImage"]; | |
// Dismiss controller | |
[picker dismissViewControllerAnimated:YES completion:nil]; | |
// Resize image | |
UIGraphicsBeginImageContext(CGSizeMake(640, 960)); | |
[image drawInRect: CGRectMake(0, 0, 640, 960)]; | |
UIImage *smallImage = UIGraphicsGetImageFromCurrentImageContext(); | |
UIGraphicsEndImageContext(); | |
// Upload image | |
NSData *imageData = UIImageJPEGRepresentation(smallImage, 0.05f); | |
[self uploadImage:imageData]; | |
} | |
#pragma mark - | |
#pragma mark MBProgressHUDDelegate methods | |
- (void)hudWasHidden:(MBProgressHUD *)hud { | |
// Remove HUD from screen when the HUD hides | |
[HUD removeFromSuperview]; | |
HUD = nil; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment