0

I created the custom cell (XIB) as the subclass of UICollectionViewCell and the cell has a button in it. When I click a button, I want to go to another view with some data on that, and could go back to the original view by clicking a button as well. I've search for that and found something like "segue" or "modal" but I can't do it initially from my custom cell.

Is there any way to do this? Any help would be very thankful.

BlueBookBi.
  • 39
  • 2
  • 9
  • What is your problem? Add some property to your cell that provides you with all the information you need to launch the new view and launch it. And yes, you may present it modally or you can push the view controller to your navigation controller or you can use a segue from a storyboard. – Hermann Klecker Jul 16 '15 at 15:22
  • @HermannKlecker I've using no storyboard, only XIB. There is no "Trigger segues" as storyboard. – BlueBookBi. Jul 16 '15 at 15:30
  • Well, then you cannot use a segue.There are still two options left. – Hermann Klecker Jul 16 '15 at 15:32
  • @user1967709 yeah just like that – BlueBookBi. Jul 17 '15 at 03:08

5 Answers5

2

So what you want to do, since it seems like UICollectionView works the same as UITableView, is make a subclass of UICollectionViewCell that contains a protocol to send actions, like pressing a button, to a view controller from a different view. In this case, a different view being the UICollectionViewCell.

Adding a Protocol to a UICollectionViewCell

Add a new Cocoa Touch Class called UICustomCollectionViewCell with subclass of UICollectionViewCell. And include the interface builder file

header file UICustomCollectionViewCell.h

@protocol UICustomCollectionViewCellDelegate;

@interface UICustomCollectionViewCell : UICollectionViewCell

@property ( nonatomic, retain) IBOutlet UIButton *button;
- (IBAction)pressButton:(id)sender;

@property ( assign) id< UICustomCollectionViewCellDelegate> delegate;

@end

@protocol UICustomCollectionViewCellDelegate <NSObject>

@optional
- (void)customCollectionViewCell:(UICustomCollectionViewCell *)cell pressedButton:(UIButton *)button;

@end

implementation file UICustomCollectionViewCell.m

@implementation UICustomCollectionViewCell
@synthesize delegate;

- (IBAction)pressButton:(id)sender {
    if ([delegate respondsToSelector: @selector( customCollectionViewCell:pressedButton:)])
        [delegate customCollectionViewCell: self pressedButton: sender];

}

@end

xib file UICustomCollectionViewCell.xib

make sure the connections from the UICustomCollectionViewCell are connected to the button from the Connections Inspector:

  1. button
  2. -pressButton:

example

Finally, using this class in your project

Import the class as well as the delegate:

#import "UICustomCollectionViewCell.h"

@interface ViewController () < UICustomCollectionViewCellDelegate>

@end

In this following code, you will use the UICustomCollectionViewCell class instead of UICollectionViewCell:

UICustomCollectionViewCell *cell;

...
[cell setDelegate: self];
...

return cell;

And now the action, or method, that is called when the button is pressed:

- (void)customCollectionViewCell:(UICustomCollectionViewCell *)cell pressedButton:(UIButton *)button {
    //action will be here when the button is pressed

}

If you want to find out what indexPath this cell was from:

[collectionView indexPathForCell: cell];
ErickES7
  • 558
  • 6
  • 16
  • please do ask for any explanation of any of this. i'm happy to reply right away :) – ErickES7 Jul 17 '15 at 04:04
  • I've seen you answers, now trying, will reply if it works. :) – BlueBookBi. Jul 17 '15 at 04:13
  • I wonder if new view required to be subclass of `UICollectionViewCell` and how to go to that view, using `presentViewController` didn't work. – BlueBookBi. Jul 17 '15 at 05:51
  • When you mean by "new view" are you trying to present this "new view" as a view controller? Not sure what you're trying to present – ErickES7 Jul 17 '15 at 05:53
  • Yes, I want to put my "new view" some stuff. I actually want to jump from the main page of my app to the page which like "Settings". – BlueBookBi. Jul 17 '15 at 06:11
  • Ooh okay. You will have to create a subclass of UIViewController. Like when we created a subclass of `UICollectionViewCell` and called it `UICustomCollectionViewCell` Makes sense? Here's an example of what I believe you're trying to get to pass data between view controllers: http://stackoverflow.com/q/5210535/1967709 Is this what you mean?? – ErickES7 Jul 17 '15 at 06:20
  • Btw did the code work? Did the app get to the code: `- (void)customCollectionViewCell:(UICustomCollectionViewCell *)cell pressedButton:(UIButton *)button { //action will be here when the button is pressed }` – ErickES7 Jul 17 '15 at 06:22
  • Build failed T^T Cannot find protocol declaration – BlueBookBi. Jul 17 '15 at 06:41
  • Did you have this in your header file of the UICustomCollectiomViewCell: `@protocol UICustomCollectionViewCellDelegate;` and `@protocol UICustomCollectionViewCellDelegate ` the two names has to be exactly the same. Where is this error pointing at? Like which file? Your view controller or the cell class? – ErickES7 Jul 17 '15 at 06:43
  • I created the custom cell before so I just used its name but did make sure the name are the same. I've import the custom cell.h yet the error occurs in ViewController. It seems like it doesn't know the delegate. – BlueBookBi. Jul 17 '15 at 07:04
  • Sounds like it should all work. Is the protocol name exactly the same as the class name? I'm making sure that the only difference between the protocol name and the class name is the protocol has **Delegate** at the end of the name – ErickES7 Jul 17 '15 at 07:08
  • Oh! I just noticed that my initial controller is UICollectionView! Could the protocol be applied to this? – BlueBookBi. Jul 17 '15 at 07:14
  • I just delete the point which error occurred and it worked to the method you mentioned. (//action will be here when the button is pressed). Light of hope comes O.O What now? I'm trying something in the link you sent but still got some confusion. – BlueBookBi. Jul 17 '15 at 08:32
  • That's good, I don't believe you can just add a methods to an existing class. You would have to subclass it, which is what we did, to add your own protocol. I'm assuming by removing the code with the error you're getting a warning pointing to `[cell setDelegate: self];` ? But I am glad this worked! :D – ErickES7 Jul 17 '15 at 15:28
  • What's next is you said you wanted to send data from this first view controller to the next, the view controller you're presenting when the button is pressed? – ErickES7 Jul 17 '15 at 15:30
  • That point got Warning but still run fine. Actually, It doesn't matter what controller of the next one should be (to get the easiest solution), as long as it could switch my view to another as the button pressed. – BlueBookBi. Jul 17 '15 at 15:47
  • Right it will run just had those warnings and without that line of code, you'll have to copy and paste the methods from the protocol we made, if there was more you wanted to use/make. – ErickES7 Jul 17 '15 at 15:56
  • 1
    Well you'd want to make a new class called **SettingsViewController** and also **include xib file**. Then import this new class to the **implementation file** of your main view controller then paste this code where the action is when button is pressed: `SettingsViewController *viewSettings = [[SettingsViewController alloc] initWithNibName: @"SettingsViewController" bundle: [NSBundle mainBundle]];` this will allocate your new view controller. Then paste this in the next line: `[self presentViewController: viewSettings animated: YES completion: ^{ }];` and then this will present the settings – ErickES7 Jul 17 '15 at 15:58
  • neato! :D glad to have helped out, takes some time to understand what the question is but happy to have succeeded :) – ErickES7 Jul 18 '15 at 13:18
1

You can't/shouldn't perform navigation jobs in the cell, navigation is not in the cells domain.

What you can try is

1) Use a delegate, setup a delegate and wire it up to the button action, the controller hosting the tableview/collection view can set itself up as the delegate and listen to any events. This controller should be in charge of pushing a new view to the stack using any method you desire.

2) If you hate delegates but love blocks, you can setup a callback block on the cell, its actions could be setup in the cellForRowAtIndex: method in the controller.

Noticed a pattern here? both the above methods are delegating the task from the cell to the controller.

If all fails, just implement didSelectItemAtIndexPath: and stick with it.

Edwin
  • 3,812
  • 2
  • 21
  • 16
1

Did you try with didSelect method?

- (void)collectionView:(UICollectionView *)collectionView
didSelectItemAtIndexPath:(NSIndexPath *)indexPath{

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle: nil];

YourNewViewControllerClass *someViewController = [storyboard instantiateViewControllerWithIdentifier:@"YourNewVCID"];

[self presentViewController:someViewController
                     animated:YES
                   completion:nil];
}
Gaby Fitcal
  • 1,814
  • 1
  • 17
  • 28
0

Easiest way would be to implement cellForRow.. method, set a tag for your cell/button and react basing on that tag (eg. indexPath.row).

Nat
  • 12,032
  • 9
  • 56
  • 103
0

1.custom your button

NouMapButton.h

#import <Foundation/Foundation.h>

@interface NouMapButton : UIButton 
@property (nonatomic, readwrite, retain) NSObject *dataObj;
@end

NouMapButton.m

#import "NouMapButton.h"
@implementation NouMapButton
@end
  1. set your button data and target in

    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    
    btn01.dataObj = YOUR_DATA;
    [btn01 addTarget:self action:@selector(map:) forControlEvents:UIControlEventTouchUpInside];
    
  2. then you can get button custom dataObj in sender.dataObj

    -(void)map:(NouMapButton *)sender{
        MapViewController *nextView = [[MapViewController alloc] init];
        nextView.dataObj = sender.dataObj;
        //TODO....
    
    
    }
    
Bhavin Bhadani
  • 22,224
  • 10
  • 78
  • 108
focusardi
  • 54
  • 5