Domanda

I'm writing an application that allows the users to take and store images on Parse. Thus far I've managed to accomplish saving the image array to Parse by using the following logic:

  • Take Image
  • Add Object to Array
  • Convert array to NSData
  • Convert NSData to PFFile
  • Set file upload destination (via unique objectId)
  • Upload PFFile to Parse

This is what the code looks like; please forgive the fact that it's in dismissViewController for now, I'm only trying to get it to save successfully:

- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
_takenImage = (UIImage *) [info objectForKey:UIImagePickerControllerOriginalImage];
[self dismissViewControllerAnimated:YES completion:^
{
    // Add object to array: Working
    [_tankImagesArray addObject:_takenImage];
    NSLog(@"Number of images taken: %lu", (unsigned long)_tankImagesArray.count);

    // Convert array to NSData Object
    NSData *imageData = [NSKeyedArchiver archivedDataWithRootObject:_tankImagesArray];

    // Convert NSData Object to PFFile
    PFFile *imageFile = [PFFile fileWithData:imageData];

    PFQuery *tankQuery = [PFQuery queryWithClassName:@"SavedTanks"];
    _tankObject = [tankQuery getObjectWithId:_passedValue];

    [_tankObject setObject:imageFile forKey:@"tankImages"];

    [_tankObject save];
}];
}

Now, my question is: How exactly would I go about retrieving that file? My ultimate goal here is to allow the user to see images they've taken in the past and add to the list of pictures in the collection and upload them to the server. I'm just unsure of how to retrieve the file once its been uploaded and make sure the integrity is maintained.

È stato utile?

Soluzione

Did you try:

PFQuery *query = [PFQuery queryWithClassName:@"SavedTanks"];
[query whereKey:@"tankImages" equalTo:@"your_image.jpg"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
  if (!error) {
    // The find succeeded.
    NSLog(@"Successfully retrieved %d images.", objects.count);
    // Do something with the found objects
    for (PFObject *object in objects) {
        NSLog(@"%@", object.objectId);
    }
  } else {
    // Log details of the failure
    NSLog(@"Error: %@ %@", error, [error userInfo]);
  }
}];

Altri suggerimenti

PFQuery *query = [PFQuery queryWithClassName:@"SavedTanks"];
// Add constraints here to get the image you want (like the objectId or something else)
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
  if (!error) {    
    for (PFObject *object in objects) {
        PFFile *imageFile = object[@"tankImages"];
        [imageFile getDataInBackgroundWithBlock:^(NSData *imageData, NSError *error) {
            if (!error) {
                UIImage *image = [UIImage imageWithData:imageData];  // Here is your image. Put it in a UIImageView or whatever
            }
        }];        
    }
  } else {
    // Log details of the failure
  }
}];

In the .h file of your collection view you need to have something like below. Note that the one I built you could like an image and then sort liked images using a segment controller.

#import <UIKit/UIKit.h>
#import "UICollectionCell.h"
#import <Parse/Parse.h>

@interface ParseViewController : UIViewController {

    NSArray *imageFilesArray;
    NSMutableArray *imagesArray;
}

@property (weak, nonatomic) IBOutlet UICollectionView *imagesCollection;
- (IBAction)segmentSelected:(id)sender;
@property (weak, nonatomic) IBOutlet UISegmentedControl *segmentedController;



@end

Then in the .m file of your collection view

    @interface ParseViewController ()

@end

@implementation ParseViewController

@synthesize imagesCollection;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    [self queryParseMethod];

}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

// code to add the number of images etc as per table view

-(void) queryParseMethod {
    NSLog(@"start query");
    PFQuery *query = [PFQuery queryWithClassName:@"collectionView"];
    [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
        if (!error) {
            imageFilesArray = [[NSArray alloc] initWithArray:objects];
            NSLog(@"%@", imageFilesArray);
            [imagesCollection reloadData];
        }
    }];

}

#pragma mark - UICollectionView data source

-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
    // number of sections
    return 1;
}

-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    // number of items
    return [imageFilesArray count];

}

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    // the custom cell we named for the reusable identifier
    static NSString *cellIdentifier = @"imageCell";
    UICollectionCell *cell = (UICollectionCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];

    PFObject *imageObject = [imageFilesArray objectAtIndex:indexPath.row];
    PFFile *imageFile = [imageObject objectForKey:@"imageFile"];

    // show loading spinner
    [cell.loadingSpinner startAnimating];
    cell.loadingSpinner.hidden = NO;

    [imageFile getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
        if (!error) {
            NSLog(@"%@", data);
            cell.parseImage.image = [UIImage imageWithData:data];
            [cell.loadingSpinner stopAnimating];
            cell.loadingSpinner.hidden = YES;

        }
    }];

    return cell;

}

-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
    [self likeImage:[imageFilesArray objectAtIndex:indexPath.row]];
}

-(void) likeImage:(PFObject *)object {

    [object addUniqueObject:[PFUser currentUser].objectId forKey:@"favorites"];

    [object saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
        if (!error) {
            NSLog(@"liked picture!");
            [self likedSuccess];
        }
        else {
            [self likedFail];
        }
    }];
}

-(void) likedSuccess {
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Success" message:@"You have succesfully liked the image" delegate:self cancelButtonTitle:@"OK" otherButtonTitles: nil];
    [alert show];
}

-(void) likedFail {
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Unsuccesfull" message:@"You have been unable to like the image" delegate:self cancelButtonTitle:@"OK" otherButtonTitles: nil];
    [alert show];
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

- (IBAction)segmentSelected:(id)sender {
    if (_segmentedController.selectedSegmentIndex == 0) {
        [self queryParseMethod];
    }
    if (_segmentedController.selectedSegmentIndex == 1) {
        [self retrieveLikedImages];
    }
}

-(void) retrieveLikedImages {
    PFQuery *getFavorites = [PFQuery queryWithClassName:@"collectionView"];
    [getFavorites whereKey:@"favorites" equalTo:[PFUser currentUser].objectId];

    [getFavorites findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
        if (!error) {
            imageFilesArray = [[NSArray alloc] initWithArray:objects];
            [imagesCollection reloadData];
        }
    }];
}



@end

Hope this is of some help to you.

All the above solutions are correct, but want to add one another way to have support of Image Caching of SDWebImage or any library like that. On Successful completion you will be have PFFile, whose property "url" will return you actuall URL of Image where it is saved. You can use that to load image. Using this approach I was able to have Image Cacheing based on key as URL.

...
NSString *strUrl = pfFileObject.url;
...
...
[img sd_setImageWithURL:[NSURL URLWithString:strUrl]];

Why would you want to download photos from parse that the user already has them locally..?

I recommend you to use : https://github.com/AFNetworking/AFNetworking

you can also save local photos to cache so you access them easily so you dont need any downloading from parse...

now if you still want to download the photos from parse just make a normal query and download all the photos parse object and you will get in the PFObject the PFFile of your photos.

Example:

PFQuery *query = [PFQuery queryWithClassName:@"SavedTanks"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
    if (!error) {
        for(PFObject *obj in objects){
            PFFile *file = [obj objectForKey:@"tankImages"];

            // now you can use this url to download the photo with AFNetwork
            NSLog(@"%@",file.url);
        }
    }
}];
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top