Selected image is not coming in Detail View Controller - ios

I have a CollectionView in a viewcontroller. I named this viewController as TabViewController. Now in that collectionView I have some images. Now when I am tapping on the cells it is pushing to another viewController named as DetailViewController. In DetailViewController I have an imageView. I want to show the selected image in TabViewController in the imageView of DetailViewController.
But no images are coming. Can any one show me where I am wrong.
This is the code that I have done.
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
if (collectionView.tag == 6) {
[self performSegueWithIdentifier:#"detailController" sender:self];
_lastSelectedImage = [UIImage imageNamed:_myPatternString];
}
}
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
DetailViewController *detailObject = (DetailViewController *) segue.destinationViewController;
detailObject.selectedImageInPreviousVC = _lastSelectedImage;
}
and in DetailViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
_myImageView.image = _selectedImageInPreviousVC;
}

You could directly sent the image in performSegueWithIdentifier.
Use something like this:
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
if (collectionView.tag == 6) {
[self performSegueWithIdentifier:#"detailController" sender:[UIImage imageNamed:_myPatternString]];
}
}
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
DetailViewController *detailObject = (DetailViewController *) segue.destinationViewController;
detailObject.selectedImageInPreviousVC = sender;
}
Also make sure that detailObject.selectedImageInPreviousVC is not a weak property.

Try this:
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
if (collectionView.tag == 6) {
// Perform segue need to be called after _lastSelectedImage has been set
_lastSelectedImage = [UIImage imageNamed:_myPatternString];
[self performSegueWithIdentifier:#"detailController" sender:self];
}
}
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
DetailViewController *detailObject = [segue destinationViewController];
detailObject.selectedImageInPreviousVC = _lastSelectedImage;
}

Related

ObjectiveC > Segue between TableView and ViewController

I'm a beginner in Objective C and I have an issue between my Table View Controller and ViewController. When I click on the cell nothing happens, I don't go in my view controller to have more details about my cell.
I use a push segue and I don't forget to give it an identifier and to do this code part in my TableView:
(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showDetails"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
ViewController *destViewController = segue.destinationViewController;
destViewController.details = data [indexPath.row];
}
}
My link between my two views is between the cell prototype and the ViewController window.
in didSelectRowAtIndexPath:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:#"showDetails" sender:self];
}
in prepareForSegue:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"showDetails"])
{
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
ViewController *destViewController = segue.destinationViewController;
destViewController.details = data [indexPath.row];
}
}

No responed after pressing UICollectionViewCell in the UICollectionViewController

when I come the part of sending image from UICollectionViewController to another ViewController here is View A:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"Detail Segue"])
{
PhotoDetailViewController *PhotoDetailVC = segue.destinationViewController;
NSIndexPath *path = [[self.collectionView indexPathsForSelectedItems] lastObject];
Photo *selectedPhoto = self.photos[path.row];
PhotoDetailVC.photo = selectedPhoto;
}
}
and I receive it in the ViewController (View B) using:
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.imageView.image= self.photo.image;
}
I think the problem is that you didn't call performSegueWithIdentifier:sender: in any place in code which actually responsible for triggering navigation not prepareForSegue:sender: which is called when preparing for the navigation
so I suggest to implement collectionView:didSelectItemAtIndexPath: as the following
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
Photo *selectedPhoto = self.photos[path.row];
// this line is the one that is responsible for navigation
[self performSegueWithIdentifier:#"Detail Segue" sender:selectedPhoto];
}
and modify prepareForSegue:sender: as the following
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"Detail Segue"]) {
PhotoDetailViewController *PhotoDetailVC = segue.destinationViewController;
PhotoDetailVC.photo = sender;
}
}

How to get the same image on detailed view on clicking a cell on collection view?

I am working on an iOS app.I have a collection view which have some images.Images come from an array I have created.When I clicked on a cell of collection view, a second view controller opens.I want to show that particular image on second view controller on which I have clicked on the collection view. How to do that?
Create image object in SecondViewController like below:
#property (nonatomic, strong) UIImageView *detailImageView;
#property (nonatomic, strong) UIImage *detailImage;
In your FirstViewController.m do the same as below:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
CollectionViewCell *cell = [collectionViewObject dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
SecondViewController *secondViewController = [[SecondViewController alloc] init];
secondViewController.detailImage = cell.imageView.image;
[self.navigationController pushViewController:secondViewController animated:YES];
}
And then in SecondViewController.m viewDidLoad method
- (void)viewDidLoad
{
[super viewDidLoad];
self.detailImageView.image = self.detailImage;
}
Hope this will work for you!!
I hope you have created UIImageView in next ViewController
Step 1. Firs of all in you next ViewController.h create image
#property (nonatomic, strong) UIImage *image;
then in previous ViewControler.m find you didSelectItemAtIndexPath method, or create them, and add next code:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
MyCollectionViewCell *cell = [self.collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentificer forIndexPath:indexPath];
MyViewController *myvc = [[MyViewController alloc] init];
myvc.image = cell.imageView.image;
[self presentViewController: myvc animated:YES completion:nil];
}
if you don`t using storyboard go to step 3.
Step 2. If you using storyboard create image in you next ViewController.h
then in previous ViewControler.m find you didSelectItemAtIndexPath method, or create them, and add next code:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
[self performSegueWithIdentifier:#"nextVCSeagueName" sender:self];
}
add method
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"nextVCSeagueName"]) {
MyviewController *myvc = segue.destinationViewController;
myvc.image = [imagesArray objectAtIndex:[[self.collectionView indexPathsForSelectedItems] firstObject]];
}
}
Step 3. In next ViewController.m in viewDidLoad add
-(void)viewDidLoad {
[super viewDidLoad];
myImageView.image = self.image;
}
Use the delegate method to know which image to pass-
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
Let's assume your array of images is called imageArray. In your class, declare an image String like-
#propert NSString *selectedImage;
Now, when you implement the didSelectItemAtIndexPath method, you can save the image that is loaded in that particular row in your selectedImage variable. Then you can implement the prepareForSegue method to pass this variable to your Second View Controller.
Let's assume, you have declared a variable called imageFromFirstviewController in your SecondViewcontroller.h file.
#propert NSString *imageFromFirstviewController;
Now, you can do something like following in your didSelectItemAtIndexPath method-
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
self.selectedImage = [self.imageArray objectAtIndex:indexPath.row] ;
}
after that pass this image name to the Second View Controller through the segue method.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// "my-segue-name" which is assign in the storyboard while attaching the segue
if ([[segue identifier] isEqualToString:#"my-segue-name"])
{
SecondViewcontroller *secondVC = [segue destinationViewController];
secondVC.imageFromFirstviewController = self.selectedImage;
}
}
Now, as you have access to your selected image in your second view controller, you can use this imageFromFirstviewController anyway you want.

Unable to pass a NSString from One VC to Next VC

I have two VCs and i want to pass resourceName from HomeViewController to SingleWebViewController. But the resourceName is getting null.
HomeViewController.m
#import "HomeViewController.h"
#import "SingleWebViewController.h"
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
singleWebViewController = segue.destinationViewController;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
selectedRow = indexPath.row;
switch (selectedRow)
{
case 0:
{
singleWebViewController.resourceName=#"intro";
NSLog(#"HtmlFileName:%#" , singleWebViewController.resourceName);
[self performSegueWithIdentifier:#"toSingleWebView" sender:self];
break;
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
SingleWebViewController.h has the following line
#property (nonatomic,strong)NSString *resourceName;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
NSString *htmlFile = [[NSBundle mainBundle] pathForResource:self.resourceName ofType:#"html" inDirectory:nil] ;
NSLog(#"%#se:" , self.resourceName);
NSURL *url = [NSURL fileURLWithPath:htmlFile ];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[_webView loadRequest:request];
_webView.delegate=(id)self;
}
i did notice that didSelectRowAtIndexPath is getting called before prepareForSegue. what's the cause for this. Please suggest.
In prepareForSegue, you're assigning something new to singleWebViewController. If this controller is different from the controller that's already assigned in tableView: didSelectRowAtIndexPath:, which I assume it is, then your property will be reset.
Instead, do this:
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
singleWebViewController = segue.destinationViewController;
singleWebViewController.resourceName = #"intro";
}
In your prepareForSegue you can set the property resourceName
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
SingleWebViewController *singleWebViewController = segue.destinationViewController;
[singleWebViewController setResourceName:#"Resource name"];
}
try this..pass value in prepareforsegue
Edit: if you want for different case to pass the different value then do this..i m assuming you want to segueway to same ViewController ie SingleWebViewController here.
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"toSingleWebView"]) {
SingleWebViewController *singleWebViewController = segue.destinationViewController;
NSIndexPath *indexPath = [self.tableView indexPathOfSelectedRow];
if(indexpath.row == 0){
singleWebViewController.resourceName=#"intro";
}
else if(indexPath.row == 1){
singleWebViewController.resourceName=#"some other value";
}
else{
singleWebViewController.resourceName=#"something else";
}
NSLog(#"HtmlFileName:%#" , singleWebViewController.resourceName);
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
selectedRow = indexPath.row;
switch (selectedRow)
{
case 0:
{
[self performSegueWithIdentifier:#"toSingleWebView" sender:self];
break;
}
case 1:
{
[self performSegueWithIdentifier:#"toSingleWebView" sender:self];
break;
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
You're setting resourceName after viewDidLoad has been called. Add a custom initialiser, initWithResourceName:(NSString *)resourceName, and set it there. Or move the code from viewDidLoad to viewDidAppear:.
Try with:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
HomeViewController *obj = segue.destinationViewController;
if([segue.identifier isEqualToString:#"toSingleWebView"]){
obj.singleWebViewController = singleWebViewController;
}
}

Transfering NSString from prototype cell not working with prepareForSegue

I am just trying to transfer a simple string from a UILabel in a prototype cell into a label in the next View Controller. Value of label.text in the viewDidLoad of the View Controller is returning (null).
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
mainCell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (mainCell == nil) {
mainCell = [[dictionaryTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSString* date = [dateArray objectAtIndex:indexPath.row];
mainCell.viewLabel.text = date;
return mainCell;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"View Segue"]) {
NSLog(#"View Load Segue Success");
ViewController *one = segue.destinationViewController;
one.label.text = mainCell.viewLabel.text;
}
}
What am I doing wrong here?
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"View Segue"]) {
NSLog(#"View Load Segue Success");
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
ViewController *one = segue.destinationViewController;
one.label.text = [dateArray objectAtIndex:indexPath.row];
}
}
And actually, assigning text to text label you should do in your viewController one's method(viewDidLoad or viewWillAppear). So, you need to make a property in viewController one for transferring NSString.
You can use indexPathForSelectedRow:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"View Segue"]) {
ViewController *one = segue.destinationViewController;
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
one.textProperty = [dateArray objectAtIndex:indexPath.row];
}
}
Or you can also use sender if your segue is from the cell to the next scene, e.g.:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"View Segue"])
{
ViewController *one = segue.destinationViewController;
NSAssert([sender isKindOfClass:[UITableViewCell class]], #"Not cell");
UITableViewCell *cell = sender;
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
one.textProperty = [dateArray objectAtIndex:indexPath.row];
}
}
Two things to note:
As a matter of good programming style, I am not retrieving the text value from the cell. I'm retrieving the text value from the model. You should not be relying upon the view for information to be passed along. Go back to the model, the original source of the information.
Do not set the text property of the label in the destination controller directly. The controls of the destinationController have not been created yet. You should defer setting controls until the destinationController's viewDidLoad. So, instead, create a NSString property in the destination controller:
#property (nonatomic, strong) NSString *textProperty;
Clearly, you should use a more descriptive name than textProperty, but hopefully you get the idea. Anyway, prepareForSegue can set this new property and the viewDidLoad of the destination controller should then use that NSString property to populate the text property of the UILabel, e.g.:
- (void)viewDidLoad
{
[super viewDidLoad];
self.label.text = self.textProperty;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
YourViewController *controller =[[YourViewController alloc] init];
[self presentModalViewController:controller animated:YES];
one.label.text = [dateArray objectAtIndex:indexPath.row];
}
Change the label.text after presentModalViewController. Now what happens?
- (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^)(void))completion
I understand you are already using Segue. You should follow the other answer.

Resources