i have a tableview and i want to when I touch on the cells to be navigate to the editViewController and when I Long touch (touch and wait) on the cells to be navigate to the DetailsViewController.
I got the answer to this question here.
now i have another problem, i use following code to pass selected row to detailViewContoler
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
if([[segue identifier] isEqualToString:#"ContectDetails"])
{
//get selected contact
NSManagedObject *selectedContact=[contacts objectAtIndex:[[self.tableView indexPathForSelectedRow] row]];
//pass selected contact to MyContactAppViewController for editing
ContactDetailsViewController *destViewcontroller=segue.destinationViewController;
destViewcontroller.contact=selectedContact;
//contact is my core data object
}
}
now i need to creat a modal segue and set segue identifier to "ContectDetails" in long press method.
Create a segue in storyboard between your table view's view controller and the ContactDetailsViewController and name it in the attributes inspector (let's say you name it 'ContactDetailsModalSegue').
Then in the gesture recognizer handler method you can call the segue like this:
-(void)handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer {
[self performSegueWithIdentifier:#"ContactDetailsModalSegue"
sender:self];
}
In this case self should be the view controller that your table view resides in. If you are handling the long press inside the table view cell class, then you should keep a weak reference to the table view's view controller and refactor accordingly:
In your table view cell's .h file include a pointer to the parent vc:
#property (weak, nonatomic) UIViewController *vc;
Make sure you pass a reference to the cell when you set it up in the table view delegate:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MyIdentifier"];
cell.vc = self; //Assuming your datasource is in the view controller file (adjust if necessary)
}
and finally in the tableview cell's .m file, use the pointer to the vc to call the segue:
-(void)handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer {
[self.vc performSegueWithIdentifier:#"ContactDetailsModalSegue"
sender:self];
}
Update:
In order to pass a reference to the data that was used to populate the table view cell to the destinationViewController, you can do the following:
First, ensure that the data is stored in a model object in your custom table view cell subclass .h file. For this example I am using an NSManagedObject because thats what is in your question, but others reading this can swap this out with any model object (e.g. an NSObject subclass):
#property (strong, nonatomic) NSManagedObject *managedObject;
Note that in the performSegueWithIdentifier: method call you are passing a reference to self as the sender parameter. The object you specify for the sender parameter will be passed as an argument to the - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender method. This enables you to retrieve the public property you just added to your custom table view cell, like this:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
//Verify segue identifier
if([[segue identifier] isEqualToString:#"ContactDetailsModalSegue"])
{
//Protect yourself from unrecognized selector errors in case you reuse this segue
if ([sender isKindOfClass:[YourCustomTableCellClass class]] &&
[segue.destinationViewController respondsToSelector:#selector(setContact:)]) {
//get selected contact
NSManagedObject *selectedContact= (YourCustomTableCellClass *)sender.managedObject;
//pass selected contact to ContactDetailsViewController for editing
ContactDetailsViewController *destViewController= segue.destinationViewController;
destViewController.contact = selectedContact;
}
}
}
replace [self.navigationController pushViewController:detailView animated:YES]; with [self.navigationController presentModalViewController:detailView animated:YES completion:nil]; in the method
-(void)handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer
{
}
Related
I have a controller with a listview that contain a custom cell.
I have created a modal segue from the cell to the next controller and I gave a name to this segue but when I click on the cell, prepareForSegue isn't called.
I could use the didSelectRowAtIndexPath and performSegueWithIdentifier but I have to send data to the next controller from the cell I've clicked on.
Any idea why the prepareForSegue isn't called? Or how to send data to the controller with another method?
You can get the cell data in didSelectRowAtIndexPath by getting the cell from the index of customCell that you clicked, and after you can performSegueWithIdentifier.
So let's make this easier:
Under your didSelectRowAtIndexPath method, add this line to get the properties of your customCell
YourCustomCell *customCell = (YourCustomCell *)[self.tableView cellForRowAtIndexPath:indexPath];
So now if you have something stored under your customCell you can access it from customCell instance.
After you managed to store or manipulate your data from customCell you do the performSegueWithIndenfier:
[self performSegueWithIdentifier:#"yourSegueID" sender:self];
Hope this helps
When you connect a segue from a cell to another view controller, unless it's a static table view, you'll have to trigger performSegueWithIdentifier from the didSelectRowAtIndexPath
After you execute performSegueWithIdentifier, prepareForSegue would be called.
In prepareForSegue, you can set up your destination view controller, which you can access via segue.destinationViewController
Like so:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
[super prepareForSegue:sender sender:sender];
if ([segue.identifier isEqualToString:#"YOUR_SEGUE_NAME_HERE"]) {
UIViewController *destinationViewController = segue.destinationViewController;
}
}
Or if you need to set things up in the didSelectRowAtIndexPath , you could do (iOS7+ only)
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self performSegueWithIdentifier:#"YOUR_SEGUE_NAME_HERE" sender:self];
UIViewController *destinationViewController = [self.transitionCoordinator viewControllerForKey:UITransitionContextToViewControllerKey];
}
Update:
Turns out #rdelmar is correct, it does work with dynamic cells.
All you have to do then is
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
[super prepareForSegue:sender sender:sender];
if ([segue.identifier isEqualToString:#"YOUR_SEGUE_NAME_HERE"]) {
NSIndexPath *selectedIndexPath = [self.tableView indexPathForCell:sender];
}
}
And you have the index path of the cell that was tapped. Then you can use that to query your datasource and find the object that was used to populate that cell.
I implemented SWRevealController in my application. It has two segues one for slideviewcontroller and viewcontroller.
My slideviewcontroller is UITableViewController, I created a new class MenuTableViewController for use as a custom class of that siderbar(slideview). When I add a MenuTableViewController as a custom class of that view, it isn't shown when i slide a menu. If i leave it blank it's shown.
The problem is that I want when cell clicked to perform segue identifier or a button clicked, but I don't know where to implement them.
You can implement your segue in your tableview's delegate method:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:#"YourSegueIdentifier" sender:self];
}
You can segue to a proper ViewController depending on indexPath of the selected item inside of that method. Then implement your:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"YourSegueIdentifier"])
{
DestinatinoVCClass *destinationVC = (DestinatinoVCClass *)segue.destinationViewController;
//here you can set any public properties of the destinationVC
}
}
But in general, as far implementing SWRevealController into your app goes here is a full tutorial.
I have a popover segue that goes to a view controller. I want to set some properties in the view controller when a cell is clicked. I tried using -prepareForSegue:, but then I realized that it doesn't have the scope of the selected cell. I know that I have to use:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
delegate method, but I'm not sure how that will affect the popover segue. Do I have to programatically create the popover, or is there another way?
Thanks much!
~Carpetfizz
Use self.tableView.indexPathForSelectedRow to get the data from your table's data source, e.g., the array backing the table data. If, for some reason, you don't want to get the data from your data source, then the sender is the UITableViewCell that was tapped to trigger the segue.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"YourSegueID"]) {
YourDestinationViewControllerClass* destinationController = segue.destinationViewController;
destinationController.somePublicProperty = self.yourTablesDataSourceArray[self.tableView.indexPathForSelectedRow.row];
UITableViewCell *cell = (UITableViewCell *)sender;
destinationController.someOtherPublicProperty = cell.textLabel.text;
}
}
So add an NSIndexPath propriety to your VC. Let's call it selectedCell. In your tableView:didSelectRowAtIndexPath method, save the selected index path to the instance variable.
Then in your prepareForSegue method, use the instance variable.
Alternately, in your prepareForSegue method, you could ask the table view for the currently selected row using the table view's indexPathForSelectedRow method.
The best approach is to use the indexPathForSelectedRow property.
For example you can write a code like this:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"YourSegueIdentifier"])
{
NSIndexPath *indexPath = [sender indexPathForSelectedRow];
NextViewController *vc = (NextViewController *)segue.destinationViewController;
vc.yourProperty = #"Some Value";
}
}
Assuming NextViewController as your segue destination controller and yourProperty as the property you want to set during the segue, you can access and set information from your parent controller because indexPathForSelectedRow automatically knows which cell has been clicked.
More information can be found here.
My storyboard application flows like this:
When a button(let me call it "BtnA") is clicked it loads a table view(Let me call it "TblA").
Once clicked on particular cell, a corresponding image("ImgA") will be loaded in a image view.
On image view's top bar there is another button(let me call it "BtnB").When I click on the button(BtnB) one table view(Let me call it "TblB") as popover is loaded; And, its cell values as same as the previously loaded tableview("TblA") cell(that is tableview loaded after my initial button click).
Now, What I want is, when popover tableview("TblB") cell is selected I want to load my corresponding image("ImgA") back to the image view.How Can I do this?
Note: .Button("BtnB") is connected tableview("TblB") as popover segue.
I was referring to this(load images in an image view from a table in a popover ), but, its seems that its bit different as its loading tableview's cell image to the image view.
Hope my question explanation is understandable.Please help.
You can use delegation in this case. What you can is, create a protocol in TblB controller
#protocol TblBDelegate <NSObject>
-(void)didSelectCellWithImage:(UIImage*)image
#end
I passed the image here, but you can pass whatever you need.
You create a delegate property in TblB
#property (nonatomic, assign) id< TblBDelegate> delegate
Now you said you are presenting TblB popover with a segue. So in TblA, you implement prepareForSegue method and set TblA controller as the delegate
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"SEGUE NAME"]) {
TblBController *controller = (TblBController*)[segue destinationViewController];
controller.delegate = self;
}
}
Now in your TblA controller, you conform to protocol TblBDelegate, and implement the method
#interface TblAController <TblBDelegate>
#end
and in your .m file
-(void)didSelectCellWithImage:(UIImage*)image
{
// Update your imageView with new image
}
and in your TblB controller
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Get selected image
// and call your delegate method
if (self.delegate && [self.delegate respondsToSelector:#selector(didSelectCellWithImage:)]) {
[self.delegate didSelectCellWithImage:selectedImage]
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
I want to create table, and when click cell in table , the content will display in another view. Each of table has different design. How do I do that.
I don't enough to post image, you can see in this link. thanks.
Use this delegate method:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:#"InstructionToSection" sender:nil]; //"InstructionToSection" is seque name
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
InstructionSectionViewController * instructSection = [segue destinationViewController]; // InstructionSectionViewController is ur next viewcontroller. 1st u need to import your destination viewcontroller in header
instructSection.SelectedItem = #"Ur Passing value"; // selectedItem should be declare in InstructionSectionViewController as property, need to synthesize
}
For more detail refer to this link