I need some help figuring out how to pass data from my collection view to the detail view controller. I am starting by simply passing the image through. My code is below:
ViewController:
-(MyCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
MyCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"CELL" forIndexPath:indexPath];
PFObject *imageObject = [imageFilesArray objectAtIndex:indexPath.row];
__block UIImage *MyPicture = [[UIImage alloc]init];
PFFile *imageFile = [imageObject objectForKey:#"test"];
[imageFile getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
if (!error) {
MyPicture = [UIImage imageWithData:data];
cell.CollectionImg.image = [UIImage imageWithData:data];
cell.cellLabel.text = [object objectForKey:#"phone"];
}
}];
return cell;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
TopDetailViewController *detailVC = [[TopDetailViewController alloc] initWithNibName:#"TopDetailViewController" bundle:[NSBundle mainBundle]];
detailVC.img= [imageFilesArray objectAtIndex: indexPath.row];
[self.navigationController pushViewController:detailVC animated:YES];
}
And the Detail view:
.h
#property (nonatomic, strong) IBOutlet UIImageView *imageView;
#property (nonatomic, strong) IBOutlet NSString *img;
.m
- (void)viewDidLoad
{
[super viewDidLoad];
self.imageView.image = [UIImage imageNamed:self.img];
// Do any additional setup after loading the view from its nib.
}
If someone could help me out I would greatly appreciate.
You can only use [UIImage imageNamed:] to retrieve images that are in your app bundle. It looks like you create these images at run-time based on the PDF file, so just passing in the string to the detail view and loading it with [UIImage imageNamed:] won't work. You should pass the reference to the image or the PFFile object so that the detail view can generate the image itself.
Related
I'm using Parse as the database for my app. I want to create a CollectionViewCell and transfer my code there, instead of having it inside the View Controller's cellForItemAtIndexPath. How do I do this?
Thanks.
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
static NSString *identifier = #"productCell";
ProductCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
PFObject *product = [self.products objectAtIndex:indexPath.row];
NSString *price = [NSString stringWithFormat:#"$%#.00", product[#"price"]];
cell.price.text = price;
PFFile *userImageFile = product[#"firstThumbnailFile"];
[userImageFile getDataInBackgroundWithBlock:^(NSData *imageData, NSError *error) {
if (!error) {
UIImage *thumbnailImage = [UIImage imageWithData:imageData];
UIImageView *thumbnailImageView = [[UIImageView alloc] initWithImage:thumbnailImage];
cell.image.image = thumbnailImageView.image;
}
}];
return cell;
}
Cell.h
#interface ProductCell : UICollectionViewCell
#property (nonatomic, weak) IBOutlet UIImageView *image;
#property (nonatomic, weak) IBOutlet UILabel *price;
#end
Remember that cellForIndexPath is called over and over as cells scroll into view. So it's bad practice to make unguarded network requests in that method.
If you want to fetch the images lazily, add logic that caches the retrieved results, and only fetch images that haven't been fetched before...
// in private interface
#property(strong,nonatomic) NSMutableDictionary *imageForProduct;
// in init
self.imageForProduct = [#{} mutableCopy];
A method to fetch an image...
- (void)imageForProduct:(PFObject *)product completion:(void (^)(UIImage *))completion {
PFFile *userImageFile = product[#"firstThumbnailFile"];
[userImageFile getDataInBackgroundWithBlock:^(NSData *imageData, NSError *error) {
UIImage *image;
if (!error) {
image = [UIImage imageWithData:imageData];
}
completion(image);
}];
}
Now, in cellForIndexPath, we can't count on the state of the collection being the same by the time the image arrives, so rather than retaining manipulating the cell in the completion block, just reload the index path...
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
static NSString *identifier = #"productCell";
ProductCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
PFObject *product = [self.products objectAtIndex:indexPath.row];
NSString *price = [NSString stringWithFormat:#"$%#.00", product[#"price"]];
cell.price.text = price;
if (self.imageForProduct[product.objectId]) {
cell.image = self.imageForProduct[product.objectId];
} else {
cell.image = // optionally put a placeholder image here
[self imageForProduct:product completion:^(UIImage *)image {
self.imageForProduct[product.objectId] = image;
[collectionView reloadItemsAtIndexPaths:#[indexPath]];
}];
}
return cell;
}
create a method in your custom cell which is exposed in your .h file.
This method should receive an argument of type PFObject.
Then in you cellForItemAtIndexPath, call that method and pass your object in that method.
And in the implementation of that method, extract the details from your object and assign them to respective properties.
I am creating an array of images selected from the phones camera roll. They are being stored but for some reason I can't get them to display in my collectionView.
in my CollectionViewController.m
- (void)viewDidLoad {
[self.photoCollectionView registerClass:[PhotoCell class] forCellWithReuseIdentifier:#"PhotoCell"];
self.assets = [[NSMutableArray alloc]init];
[super viewDidLoad];
- (NSInteger) collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return self.assets.count;
}
- (UICollectionViewCell *) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
PhotoCell *cell = (PhotoCell *)[collectionView dequeueReusableCellWithReuseIdentifier:#"PhotoCell" forIndexPath:indexPath];
ALAsset *asset = self.assets[indexPath.row];
cell.asset = asset;
cell.backgroundColor = [UIColor redColor];
return cell;
}
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
NSMutableArray *tmpAssets = [#[] mutableCopy];
[tmpAssets addObject:image];
self.assets = tmpAssets;
self.testImage.image = [self.assets objectAtIndex:0];
[picker dismissViewControllerAnimated:YES completion:Nil];
[self.photoCollectionView reloadData];
}
in my PhotoCell.h class
#interface PhotoCell : UICollectionViewCell
#property (nonatomic,strong) ALAsset *asset;
#end
in my PhotoCell.m class
#import "PhotoCell.h"
#interface PhotoCell ()
#property(nonatomic, strong) IBOutlet UIImageView *photoImageView;
#end
#implementation PhotoCell
- (void) setAsset:(ALAsset *)asset
{
_asset = asset;
self.photoImageView.image = [UIImage imageWithCGImage:[asset thumbnail]];
}
#end
Any help would be great thank you.
Among other data (specifically strings), I've got a URL being pulled from JSON and saved in the array "jsonArray". I need the the URL (which is for an image dependent on the user signed in) to be converted into an actual image ready to be displayed in my imageview "imageProfPic". I'm not that familiar with GCD, so I'd greatly appreciate any and all help with my code and getting my image successfully displayed in imageProfPic.
(EDIT: Forgot to mention that I'm getting the error "_NSCFString isFileURL")
TableViewController.m file
NSURL *myURL = [[NSURL alloc]initWithString:#"http://domain.com/json2.php"];
NSData *myData = [[NSData alloc]initWithContentsOfURL:myURL];
NSError *error;
jsonArray = [NSJSONSerialization JSONObjectWithData:myData options:NSJSONReadingMutableContainers error:&error];
[tableView reloadData]; // if tableView is unidentified make the tableView IBOutlet
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return jsonArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NeedCardTableViewCell *cell = (NeedCardTableViewCell *) [tableView dequeueReusableCellWithIdentifier:#"needCard" forIndexPath:indexPath];
NSDictionary *needs = jsonArray[indexPath.row]; // get the data dict for the row
cell.textNeedTitle.text = [needs objectForKey: #"needTitle"];
cell.textNeedPoster.text = [needs objectForKey: #"needPoster"];
cell.textNeedDescrip.text = [needs objectForKey: #"needDescrip"];
dispatch_async(dispatch_queue_create("imageQueue", NULL), ^{
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:needs[#"userImage"]]];
dispatch_async(dispatch_get_main_queue(), ^{
[cell.imageProfPic setImage:image];
});
});
return cell;
TableViewController.h file
#interface NeedCardTableViewCell : UITableViewCell
#property (weak, nonatomic) IBOutlet UILabel *textNeedTitle;
#property (weak, nonatomic) IBOutlet UILabel *textNeedPoster;
#property (weak, nonatomic) IBOutlet UILabel *textNeedDescrip;
#property (weak, nonatomic) IBOutlet UIImageView *imageProfPic;
#property (strong, nonatomic) IBOutlet UITableView *tableView;
I think you just need to create a NSURL with your string and you should be good. Give this a go:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
NSURL *imageURL = [NSURL URLWithString:needs[#"userImage"]];
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:imageURL]];
dispatch_async(dispatch_get_main_queue(), ^{
[cell.imageProfPic setImage:image];
});
});
If what you mean is displaying the image from a JSON, I used SDWebImage and it easily works with me.
Using UIImageView+WebCache category with UITableView
Just #import the UIImageView+WebCache.h header, and call the setImageWithURL:placeholderImage: method from the tableView:cellForRowAtIndexPath: UITableViewDataSource method. Everything will be handled for you, from async downloads to caching management.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:MyIdentifier] autorelease];
}
// Here we use the new provided setImageWithURL: method to load the web image
[cell.imageView setImageWithURL:[NSURL URLWithString:#"http://www.domain.com/path/to/image.jpg"]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
cell.textLabel.text = #"My Text";
return cell;
}
Using blocks
With blocks, you can be notified about the image download progress and whenever the image retrival has completed with success or not:
// Here we use the new provided setImageWithURL: method to load the web image
[cell.imageView setImageWithURL:[NSURL URLWithString:#"http://www.domain.com/path/to/image.jpg"]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType) {... completion code here ...}];
I know this question might be asked many time but i am a beginner so kindly being gentle is a humble request.
I am trying to make an image gallery which displays all the images Of a URL.
I have used all asset framework and made a simple gallery which return the images of camera roll, I want to have the image of some URL so kindly help me to Get images from url and display them to Image Gallery
Here Is the view Controller header File
#import <UIKit/UIKit.h>
#import <AssetsLibrary/AssetsLibrary.h>
#interface ViewController : UIViewController <UICollectionViewDelegate,UICollectionViewDataSource>
#property (retain, nonatomic) IBOutlet UICollectionView *collectionView;
#property(nonatomic, strong) NSArray *assets;
Here is the Implementation file In which I have registered An .NIB file to add Cell to my CollectionView
#import "ViewController.h"
#import <AssetsLibrary/AssetsLibrary.h>
#import "MyCell.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self.collectionView registerNib:[UINib nibWithNibName:#"MyCell" bundle:nil] forCellWithReuseIdentifier:#"CELL"];
_assets = [#[] mutableCopy];
__block NSMutableArray *tmpAssets = [#[] mutableCopy];
// 1
here it is calliing defaultAssetsLibrary method which you can see later
ALAssetsLibrary *assetsLibrary = [ViewController defaultAssetsLibrary];
// 2
[assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
[group enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
if(result)
{
// 3
[tmpAssets addObject:result];
}
}];
// 4
//NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:#"date" ascending:NO];
//self.assets = [tmpAssets sortedArrayUsingDescriptors:#[sort]];
self.assets = tmpAssets;
// 5
[self.collectionView reloadData];
} failureBlock:^(NSError *error) {
NSLog(#"Error loading images %#", error);
}];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - collection view data source
- (NSInteger) collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return self.assets.count;
}
// The cell that is returned must be retrieved from a call to -dequeueReusableCellWithReuseIdentifier:forIndexPath:
- (MyCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
MyCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"CELL" forIndexPath:indexPath];
ALAsset *asset = self.assets[indexPath.row];
cell.asset = asset;
cell.backgroundColor = [UIColor redColor];
////
//=
cell.cellLabel.text = [NSString stringWithFormat:#"cell %i",indexPath.row];
return cell;
}
- (void) collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
ALAsset *asset = self.assets[indexPath.row];
ALAssetRepresentation *defaultRep = [asset defaultRepresentation];
UIImage *image = [UIImage imageWithCGImage:[defaultRep fullScreenImage] scale:[defaultRep scale] orientation:0];
// Do something with the image
}
And here is that method which I think returning the photo library
+ (ALAssetsLibrary *)defaultAssetsLibrary
{
static dispatch_once_t pred = 0;
static ALAssetsLibrary *library = nil;
dispatch_once(&pred, ^{
library = [[ALAssetsLibrary alloc] init];
});
return library;
}
Please Help me to get Images From URL and display them in Image Gallery.
As Far as MyCell file is concern.
Here is MYCell.m file
#interface MyCell ()
// 1
#property(nonatomic, strong) IBOutlet UIImageView *photoImageView;
#end
#implementation MyCell
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
- (void) setAsset:(ALAsset *)asset
{
// 2
_asset = asset;
self.photoImageView.image = [UIImage imageWithCGImage:[asset thumbnail]];
}
If we are getting images from URL we don't need AlAsset for image gallery really.
I have followed this tutorial to make the image gallery Guide and Simple passed the array of url and it worked for me.
I am having a problem loading images to UICollectionView. I am trying to take a photo and save it with certain name to Documents folder, and I want this photo to appear in Collection View after photo taking dismisses.
Up until now my images are being saved in the documents folder and automatically added to an _stepImagesArray but I can't figure out how to load those images and populate uicollectionview with them.
Please help, it has been a while with my trials and errors :)
StepsCollectionViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
_stepImagesArray = [[NSMutableArray alloc] init];
}
#pragma mark - UICollectionView settings
- (NSInteger)collectionView:(UICollectionView *)view numberOfItemsInSection: (NSInteger)section {
return _stepImagesArray.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = #"Cell";
CollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
cell.imageCell.image = [UIImage imageNamed:[_stepImagesArray objectAtIndex:indexPath.row]];
cell.labelCell.text = _stepImagesArray[indexPath.row];
return cell;
}
- (IBAction)takePhoto
{
UIImagePickerController *photoPicker = [[UIImagePickerController alloc] init];
photoPicker.delegate = self;
photoPicker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentViewController:photoPicker animated:YES completion:NULL];
}
- (void)imagePickerController:(UIImagePickerController *)photoPicker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *selectedImage = [info valueForKey:UIImagePickerControllerOriginalImage];
[self.selectedImageView setImage:selectedImage];
arrayCount = self.stepImagesArray.count;
NSLog(#"array count is: %i",arrayCount);
NSString *jpgImageName = [NSString stringWithFormat:#"Documents/FolderName_%#%i.jpg", passedStepName, arrayCount+1];
NSString *jpgImageNameForArray = [NSString stringWithFormat:#"FolderName_%#%i.jpg", passedStepName, arrayCount+1];
NSString *jpgPath = [NSHomeDirectory() stringByAppendingPathComponent: jpgImageName];
[UIImageJPEGRepresentation(selectedImage, 0.1) writeToFile:jpgPath atomically:YES];
// Let's check to see if files were successfully written...
// Create file manager
NSError *error;
NSFileManager *fileMgr = [NSFileManager defaultManager];
// Point to Document directory
NSString *documentsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
// Write out the contents of home directory to console
NSLog(#"Documents directory: %#", [fileMgr contentsOfDirectoryAtPath:documentsDirectory error:&error]);
[_stepImagesArray addObject:jpgImageNameForArray];
[photoPicker dismissViewControllerAnimated:YES completion:nil];
}
CollectionViewCell.h
#interface CollectionViewCell : UICollectionViewCell
#property (weak, nonatomic) IBOutlet UIImageView *imageCell;
#property (weak, nonatomic) IBOutlet UILabel *labelCell;
#end