I have dynamic tableview for which I have 6 cells.
Problem statement:
Now, I want to show a popover which should come just right to the selected cell and with arrow pointing left towards the cell .
What I did :
1) created the PopUpViewController.m/.h .
2) created a "Present as popover" segue from the cell to this popUpViewController.
3) currently anchor point in storyboard is set to tableview so the popover shows from the top left corner.
After some reading,
1) I created a XTableViewCell.m/.h class for the cell.
2) created a small button towards right end in the cell and put an outlet of it in XTableViewCell.h file to use this button as an anchor.
MY question is , I have done all this in storyboard.
Consider my tableViewController class as YTableViewController.h/.m
1) Where and how should I use the anchor button to anchor my popover to my requirement ?
2) By default, in story board the anchor is set to the cell name . Will it be overwritten to my button ?
3) Where should I configure the UIPopoverPresentationController params ?
4) How can show the popup as "popup" in iPhone also and not as full screen view controller?
Please help.
First, you should create a popover segue from your view controller with your table view in it. You can do this by control dragging from the yellow view controller icon in the document outline to the view controller you want to popover. Give it a segue identifier, by clicking on the segue and opening the attributes inspector and adding it to the segue identifier field. Something like "Popover" will work for now.
Next, you should drag from the anchor view circle below the segue identifier field to your view controller's view (we'll adjust this later in code).
You should add a button to your UITableViewCell subclass. Then in your cellForRowAtIndexPath: you can add a target for the button like:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *cellIdentifier = [menuItems objectAtIndex:indexPath.row]; // I'm not sure what's going on here but hopefully you do
RegisterTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
[cell.PopoverAnchorButton addTarget:self action:#selector(presentPopover:) forControlEvents:UIControlEventTouchUpInside];
// Configure the cell...
return cell;
}
Add the presentPopover: method to your view controller:
- (void) presentPopover:(UIButton *)sender
{
[self performSegueWithIdentifier:#"Popover" sender:sender];
}
Now, you can change the source view in your view controller's prepareForSegue:
You can get a reference to the UIPopoverPresentationController and check if the source view is an instance of your subclass of UITableViewCell. If so, adjust the source view to its button.
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"Popover"] && segue.destinationViewController.popoverPresentationController) {
UIPopoverPresentationController *popController = segue.destinationViewController.popoverPresentationController;
popController.sourceView = sender;
popController.delegate = self;
// if you need to pass data you can access the index path for the cell the button was pressed by saying the following
CGPoint location = [self.tableView convertPoint:sender.bounds.origin fromView:sender];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:location];
// do something with the indexPath
}
}
If you want the view controller to always be displayed as a popover even on implement the UIPopoverPresentationControllerDelegate method:
- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller{
return UIModalPresentationStyleNone;
}
At this point, you'll likely have a warning. This can by silenced by telling the complier that you conform to the UIPopoverPresentationControllerDelegate protocol. For example:
#interface MyTableViewController () <UITableViewDataSource, UITableViewDelegate,UIPopoverPresentationControllerDelegate>
Related
Let's say I have the cells for a UITableView outlined programmatically. Labels, positioning, etc... In order to drag a segue to a different view, I need to see some visual representation of a prototype cell in storyboard. How do I proceed?
What I have tried is to drag a prototype cell onto my UITableView. I changed "Identifier" to my reuse cell identifier which was set in code. After this, I proceeded to link up the prototype cell by right dragging to the destination view, selecting modal, etc... When I run the app, nothing happens after I tap on a cell.
What would the best method be to link up an entirely coded cell with a visual depiction in storyboard?
Not sure what code to paste here, or if it's even necessary since I'm asking for generic information. Please let me know if and what I should include for example.
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([[segue identifier] isEqualToString:#"alertDetail"]) {
NSIndexPath *indexPathA = [[self.tableViewA indexPathsForSelectedRows] lastObject];
NSString *grabTicker = [[homeJson objectAtIndex:indexPathA.row]objectForKey:#"returnId"];
[[segue destinationViewController] setGrabTicker:grabTicker];
}
}
Create the segue from the view controller itself to the destination view controller by ctrl dragging from the view controller icon below the view layout to the destination view controller.
Name the segue.
Use the segue:
-(void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath
{
[self performSegueWithIdentifier:#"alertDetail" sender:indexPath];
}
Then your prepareForSegue looks like:
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(NSIndexPath*)indexPath {
if([[segue identifier] isEqualToString:#"alertDetail"]) {
NSString *grabTicker = [[homeJson objectAtIndex:indexPath.row]objectForKey:#"returnId"];
[[segue destinationViewController] setGrabTicker:grabTicker];
}
}
Of course, all of this begs the question of why you're not just doing the cell layout as a prototype cell in a storyboard, but there ya go.
Change the class of the prototype cell in your storyboard to the subclass of the cell you use in code. Make sure to set the prototype cell's type to custom so that it doesn't replace your cell's view hierarchy.
(As a side note, remember to add your views to the contentView of the cell, not directly to the cell itself!)
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 am creating a news app that has title, description, video and details.
this is displayed on UIViewCell on TableView, when a user clicks on that
particular cell, corresponding news is displayed as shown below
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NewsViewController *newsdetail = [[NewsViewController alloc] initWithNibName:#"NewsDetailView" bundle:nil];
self.newsdetails = detail;
[detail release];
newsdetails.title = [NSString stringWithFormat:#"%#",[titleData objectAtIndex:indexPath.row]];
newsdetails.itemID = [NSString stringWithFormat:#"%#",[NewsIds objectAtIndex:indexPath.row]];
[self.navigationController pushViewController:newsdetails animated:YES];
}
The variables (which hold JSON data) are properly defined in NewsViewController and synthesised as follows
NSMutableArray *NewsIds;
NSMutableArray *titleData;
NSMutableArray *descriptionData; etc
Now, what I want is to add a video button as shown on the storyboard, so that a user can click it and be able to see details of corresponding video through modal /popup
any suggestions or help?
In the Storyboard, just use an Action segue on the UIButton and select modal. Control Drag from the button to the Video Details VC. Give that segue a name, let's say
playVideo
Then inside the prepareForSegue method in your PlayersViewController.m you just add this:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"playVideo"]) {
// set properties on your destinationVieController to pass the data you need
}
}
Also use unwind segues on the buttons 'Cancel' and 'Done' in your destination VC to return to the previous TVC. Alternatively you could also use dismissViewControllerAnimated: that will be passed to the calling VC.
you should have a custom table view cell which will be handling actions and data on cell.
I'm totally lost in this issue. I have been working with storyboards, I have created a navigation controller with tableviews and some stuff. There are Services in each row of the tableview and I need to create one detail view for each service.
There are a lot of services, so I can't create them in the storyboard. The idea is to download the Services from a webservice (number of parameters, types of each one, etc..) and add as textfields / buttons as appropriate to the Service.
So, my problems and questions are:
1) Can I combine Storyboards and views programmatically? When I create a NewView in MyTableviewClass, should I do it in my prepareforsegue method? How can I show it in the screen without loosing my navigation controller? this is what I have (it doesn't work: it says to me that there is no segue with name 'Service1' ) :
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
if ([[segue identifier] isEqualToString:#"NextLevel"]) {
[segue.destinationViewController setActualNodo:[actualNodo getSonAtIndex:indexPath.row]];
} else if ([[segue identifier] isEqualToString:#"Service1"]) {
CGRect bounds = self.view.bounds;
UIView *myview = [[UIView alloc] initWithFrame:bounds];
[myview setBackgroundColor: [UIColor redColor]];
[self.view addSubview:myview];
[self.view bringSubviewToFront:myview]; }
Any book or reference is welcomed but I couldn't find anything similar. Is this very complicated in iOS? I have done a similar thing in Java. I have read about generating interfaces dynamically with XIBs but, sincerely, I don't know what it is..
Thanks for all.
Yes you can create a StoryBoard with a view and then add views programmatically to it.
You should not try creating a view within your prepareForSegue method. This really should be used for passing objects to another ViewController.
I would suggest this to you. Go back to your StoryBoard and create a new UIViewController scene. Click on your first scene and CTRL drag to the new scene. Next, click on your segue and give it a name.
Step 1:
Create a new class called ServicesViewController and make sure it's a subclass of `UIViewController:
Step 2:
Go back to your StoryBoard and click on scene so that it is selected. Next, click on the Files Owner and finally click on the class info button (the third button) and finally select your ServiceViewController class you just created.
Step 3:
Back in your ServicesViewController in the didSelectRowAtIndex method call your seque:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:#"YOUR_SEGUE_NAME" sender:nil];
}
For now, clean out all the code in your prepareForSegue method and just get the transition down first.
In addition to Flea's answer, if you need to keep the navigation controller, just create a push segue in your storyboard by control dragging from the file owner icon (the yellow box under your view controller's view) of the table view controller to the ServiceViewController you added to the storyboard, this should show a popup window where you can select "push" as the type of the segue. Next, select the segue and in the attribute inspector (the fourth button, next to the one in the snapshot) and in the "Identifier" text field type in a unique identifier for your segue, such as serviceSegue.
At this point, using Flea's code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:#"serviceSegue" sender:nil];
}
And in the code you posted:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
if ([[segue identifier] isEqualToString:#"serviceSegue"])
[segue.destinationViewController setActualNodo:[actualNodo getSonAtIndex:indexPath.row]];
}
I'm not sure what you are trying to do with the other segue "Service1", but if you want to change the view of the TableViewController, segues are not the way to do it. If anything you should do it in the didSelectRowAtIndexPath method depending on the row selected:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (You want to transition to other view controller)
[self performSegueWithIdentifier:#"serviceSegue" sender:nil];
else
Change your view here.
}
I hope this helps!
It sounds like you just have multiple cells in a tableView. Instead of using segues you can simply create different cells with different identifiers and show or hide them based on what services are detected in your services array which is populated from your web service.
I'm pretty nooby, just saying that before I start.
What I'm trying to do is make a table of cells, and when a cell is touched it displays an image depending on which cell was touched. Now, I thought that there would be a way to tell which cell was touched and set the UIImageView image accordingly, or am I going to have as many views as table cells and have loads of segues? Basically what I'm trying to do is get the segue identifier and use it to set the UIImageView image.
You can get the segue identifier with this method, which is called if a segue is pushed:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"YourChoiseMadeInStoryboard"]) {
...
//to access the destination ViewController do this
AViewControllerClass *viewController = segue.destinationViewController;
}
}
UIStoryboardSegue is designed to facilitate the transition between two instances of UIViewController. What you're trying to do doesn't require segues at all. You want to toggle an image view on a cell when it is tapped. You only need to implement the -tableView:didSelectRowAtIndexPath: method on UITableViewDelegate.
Edit I'm assuming you already have an ivar for your UIImageView called imageView. You will also need an ivar for an NSArray that holds all of the images. The image at each index will correspond to each row in the table. Establish your array somewhere like -viewDidLoad and assume that it is called imageArray.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Get the cell at the selected index path
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
// After being tapped, set the image view to some image
self.imageView.image = [self.imageArray objectAtIndex:indexPath.row];
}