I have a use case where essentially I have a image in a customized table view cell. When the user selects the image we want to send them to a Profile page.
Normally, I'd do this by
- (IBAction)userClickedProfilePic:(id)sender {
ProfileViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"Profile"];
vc.postInfo = self.newsfeedData.newsFeedPosts[indexPath.row];
[[self navigationController] pushViewController:vc animated:YES];
}
But self != have a storyboard reference in this case since it's a UITableViewCell class. Is there a way to pop or push a new viewController from a tableviewcell action?
You have plenty of options. What I usually do is that I will create IBAction in viewcontroller which "contains" tableview with its cells. You can create IBOutlets or IBActions in all parents viewcontrollers through IB in a same way you would do it for cell..you might didn't know that.
But you want to click event on uiimageview which is not so straitforward. You have to do it programatically but it's not that hard just do something like this in cellForRowAtIndexPath and implement actionMethod:
UITapGestureRecognizer *actionMethod = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(actionMethod:)];
[cell.yourImageView addGestureRecognizer:actionMethod];
By the way instead of self.storyboard you can use this in case your storyboard is named Main.storyboard.
[UIStoryboard storyboardWithName:#"Main" bundle:nil]
Related
I have a social app that requires login/sign-up. This is done with the ParseUI library that present a custom window for user validation.
When a user signs up, I want to display a CollectionView where users choose some preferences (each as a cell) and proceed to the app.
In the Sign-Up View Controller I have this:
- (void)signUpViewController:(PFSignUpViewController *)signUpController didSignUpUser:(PFUser *)user {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
ChooseLeagueCollectionViewController *clvc = [storyboard instantiateViewControllerWithIdentifier:#"ChooseLeagueViewController"];
[self dismissViewControllerAnimated:YES completion:NULL];
[self presentViewController:clvc animated:NO completion:NULL];
}
Do I need to alloc and init a flowLayout object even though it is already present in my storyboard?
In my storyboard I have a CollectionViewController containing one cell linked to a subclass of UICollectionViewCell with an ImageView and a Label. This storyboard file has as custom class 'ChooseLeagueViewController' which is a subclass of CollectionViewController, and is also data source and delegate.
In the .h file I have:
#interface ChooseLeagueCollectionViewController : UICollectionViewController <UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>
In the .m file I implement all the required methods that the datasource and delegate protocols require. In cellForItemAtIndexPath I populate the cell (subclass of CollectionviewCell), change the label text and text color, the image, and than return it.
Also I am not sure why I am asked to register my cell like below, even though my cell has a reusable identifier in the storyboard.
[self.collectionView registerClass:[LeagueCollectionViewCell class]forCellWithReuseIdentifier:#"leagueCell"];
Anyway when I run the app, after signing up, i am brought to a completly black screen but the battery. the app does not crash and all the 'data source' methods are called correctly.
I think that there is something wrong in the way I am trying to show this View.
Any guess on how I could improve my segue or what the mistake is?
thanks in advance
Simply alloc,init will give you blank controller with no view associated with it. You have to initialise it through storyboard like this, then you will not have to provide any custom init/alloc,
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
ChooseLeagueCollectionViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"yourViewControllerIdentifier"];
[self presentViewController:vc animated:NO completion:NULL];
You specify viewController identifier in storyboard by selecting your viewController and in identity Inspector in storyboard id. :)
I have a UIToolbarButton which has a UIButton to hold the image. Now, when I click on this UIToolbarButton, I want to open another view in the current view.
My Code :
- (IBAction)btnNowPlaying:(id)sender
{
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(openPlaying:)];
[self.view addGestureRecognizer:tap];
}
- (void)openPlaying:(UIGestureRecognizer *)sender
{
NewMainViewController *vc = [[UIStoryboard storyboardWithName:#"Main" bundle:nil] instantiateViewControllerWithIdentifier:#"Center"];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController * npvc = [storyboard instantiateViewControllerWithIdentifier:#"NowPlayingVC"];
[vc.containerView addSubview:npvc.view];
}
This action, btnNowPlaying is on the UIButton.
It sounds like you simply want to navigate from one view controller to another. Just control-drag from your bar button item to the view controller you'd like to navigate to in your storyboard. Then, click the segue between the two view controllers and set its identifier in the Attributes inspector. After that, all you need to do is implement prepareForSegue::
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"THE_IDENTIFIER_YOU_ENTERED_IN_THE_ATTRIBUTES_INSPECTOR"]) {
if ([segue.destinationViewController isKindOfClass:[NEWViewController class]]) {
NEWViewController *vc = (NEWViewController *)segue.destinationViewController;
// Any preparation you need to do for next view controller
vc.someProperty = someValue;
}
}
}
It's a little strange to open a new view controller inside the current view controller. Why not just segue to it?
Another option would be to alloc-init a UIView instead of a view controller and simply addSubview:.
First of all, you can use default UIBarButton item with Custom style and setter Image property instead of creating UIButton.
You don't need to create additional gesture recogniser. If you have connect IBAction with button in Interface Builder, you can put your transition code inside btnNowPlaying method.
Another way is to create IBOutlet, connect it with your button and create UIGestureRecognizer in - (void)viewDidLoad method.
I am developing one iPad application using storyboard. In my application i have 2 view controllers(First view controller and Modal view controller). In my first view controller I have one table view with cell containing one button. If I click the button in each cell I need to go to modal view controller. I connected the modal view controller and button by using a segue. Segue is working perfectly when style is modal but I need style Popover. When I am trying to change the segue style popover the storyboard error occurs and compilation failed comes. How can I solve this issue.
Follow the steps in the image. hope I will help you.
If the error is "Couldn't compile connection..." the problem is how XCode handles an outlet inside a dynamic table cell view.
I suggest you 2 alternatives:
1) The error doesn't come if you can use a "static" table view, in this way the table view must live inside a UITableViewController.
2) If you need a dynamic table, subclass the cell view and in your class (say MyUITableCellView) put an outlet:
#property (weak, nonatomic) IBOutlet UIButton *segueButton;
Then in your storyboard create an outlet from the prototype cell (of class MyUITableCellView) to the button inside the cell (do not create the segue in the storyboard, create only the destination view controller).
Then in the "cellForRowAtIndexPath" do the following:
MyUITableCellView *cell = (MyUITableCellView*)[tableView dequeueReusableCellWithIdentifier:#"MyCell"];
/* IMP: Here you should check if button has already this action (reused) */
[cell.segueButton addTarget:self action:#selector(showPopover:) forControlEvents:UIControlEventTouchUpInside];
and then add the action:
- (void)showPopover:(UIButton*)sender
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *secondVC = [storyboard instantiateViewControllerWithIdentifier:#"secondVC"]; // this is the storyboard id
self.popover = [[UIPopoverController alloc] initWithContentViewController:secondVC];
CGRect fromRect = [self.view convertRect:sender.frame fromView:sender.superview];
[self.popover presentPopoverFromRect:fromRect inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
Hope this has helped.
Have you included the <UIPopoverControllerDelegate> and implemented it? That's easy to forget the first times.
May be you might have not connected the Anchor, put UIView in your Viewcontroller view somewhere with background colour clear and set Anchor point of the Segue to that view.....
In Xcode 4.5 you can change views from a segue, But I want to programatically change views in Mainstoryboard. I Know in Xib. we use this method:
SecondViewController *Second = [[SecondViewController alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:Second animated:YES];
I want to change the view when the user clicks done in the textfield (This code detects if user clicks done):
-(IBAction)hidekeyboard {
[sender resignFirstResponder];
}
You create a segue in your storyboard that goes from the view that has the text field in question and goes to your SecondViewController. You have to assign an identifier to it (also in the storyboard, click on the line connecting the two view controllers), let's call it "segueToSecondViewController". Then, you can manually call the segue using:
[self.storyboard performSegueWithIdentifier:#"segueToSecondViewController" sender:self];
An alternative to segueing is to instantiate the viewController from the storyboard.
First you assign a Storyboard ID to the viewController in the storyboard.
Then you instantiate that viewController, and present it.
MBTagEditorViewController *tagEditor = [self.storyboard instantiateViewControllerWithIdentifier:#"TagEditor"];
[self presentModalViewController:tagEditor animated:YES];
I am trying to make a mechanism to drill down a file / folder list. The idea is to show the same file list view controller every time the user selects a folder, and show a file detail view controller if he/she selects a file.
So far, I have created a segue from the file list view controller to the file detail view controller, and a segue from the file list table view cell to the the file list table view controller:
The issue with this is that as soon as the user taps the cell, the segue is executed. I would like to remove the segue from the table view cell and make one from the file list view controller to itself. That way, I could trigger the right segue programmatically when the user tapped the cell.
So, my question is: Is it possible to create a segue from a view controller to itself in Interface Builder?
If you are using a navigation controller you need to push the ViewController into the nav stack. In this example, i named my ViewController "VDI" in my Storyboard ID setting.
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle: nil];
YourVC *dest = [storyboard instantiateViewControllerWithIdentifier:#"VDI"];
[self.navigationController pushViewController:dest animated:YES];
If you don't want the NavigationController to keep adding itself into your "Back" history you can pop the stack before adding to it like so.
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle: nil];
YourVC *dest = [storyboard instantiateViewControllerWithIdentifier:#"VDI"];
UINavigationController *navController = self.navigationController;
[navController popViewControllerAnimated:NO];
[navController pushViewController:dest animated:YES];
Using Xcode 5 there is a much simpler solution.
Click the table cell in the storyboard
Open the Connections Inspector (right arrow icon in the upper right)
Under "triggered segues" you see "selection"
Drag from the circle next to "selection" to the cell in the storyboard
That's it.
I developed a method to create a segue using a phantom button. I believe it will solve your problem. You can read about it in my answer here.
Instead of performing a segue to the same controller, you can instantiate a view controller (the same one) from storyboard, and then push that onto the navigation controller.
Interface Builder approach: Just segue to a storyboard reference which refers back to the presenting view controller.
The correct answer is to use a Storyboard Reference that is referencing the UIViewController you want to segue to itself and then point the segue at it.
In IOS 6, there is a cleaner solution than using a phantom button. You can still define the segue from the table cell to the view controller, and look at the sender to cancel the automatically triggered segue:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//storyboards should use segues and override prepareForSegue instead
//but here we need custom logic to determine which segue to use
id item = [self.fetchedResultsController objectAtIndexPath:indexPath];
if (item meets condition) {
[self performSegueWithIdentifier:#"segue1" sender:self];
} else {
[self performSegueWithIdentifier:#"segue2" sender:self];
}
}
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender {
//ignore segue from cell since we we are calling manually in didSelectRowAtIndexPath
return (sender == self);
}
Here's how you can push another instance of the current view controller without defining a segue or hardcoding its own identifier:
SameViewController *same = [self.storyboard instantiateViewControllerWithIdentifier: self.restorationIdentifier];
[self.navigationController pushViewController: same animated: YES];
You just need to set the Restoration ID to be the same as Storyboard ID (there's a checkbox for that in IB).
Hope this helps.
I found that you can create multiple prototype cells.
Than you can link every cell (in the Storyboard) to a different View.
Something like this:
NSString *CellIdentifier = #"Cell";
if (Condition2 ){
CellIdentifier = #"Cell2"; }
if (Condition3 ){
CellIdentifier = #"Cell3"; }