Losing Segue Action when adding custom image in navigation bar button item - objective-c

I`m developing a app using Storyboards.
In one ViewController I have a button on navigationBar that links to the second ViewController. This transiction is defined in the storyboard (in this case I have defined a push segue to link the two ViewControllers)
I have changed the image of the button following this post in Stackoverflow.
But the problem is: That change in the View of the button breaks the push segue that I have defined in the storyboard. So the question is: How to still change the background of the BarButton without killing the segue action?
I dont want to programmatically reset the segue using performSegueWithIdentifier. This makes no sense since I already have defined it on the storyboard, so I think that must be another solution.

I think this is going to be your best solution:
In viewDidLoad:
self.navButton = [UIButton buttonWithType:UIButtonTypeCustom];
self.navButton.frame = CGRectMake(0, 0, 30, 30);
[self.navButton setImage:[UIImage imageNamed:#"yourImage"] forState:UIControlStateNormal];
[self.navButton addTarget:self action:#selector(yourNavButtonAction) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *logOutBarButton = [[UIBarButtonItem alloc] initWithCustomView:self.navButton];
[self.navigationItem setRightBarButtonItems:[NSArray arrayWithObject:navButton, nil]];
And in the method handling your navButton tap (yourNavButtonAction from above)
[self performSegueWithIdentifier:#"yourSegueIdentifier" sender:self];
**Note that this will require you to create a storyboard segue that originates from your ViewController itself, as opposed to a button on that ViewController. Control drag from your ViewController to the target ViewController, give the resulting segue an identifier (yourSegueIdentifier above) and you're set.

You cannot use the quoted code and use the segue at the same time. The code introduced a new object, a UIButton that gets the click, so your storyboard object will not get it any more.
You could try adding a standard custom UIButton in storyboard and change the code as follows:
// instead of
UIButton *someButton = [[UIButton alloc] initWithFrame:frameimg];
// use
_someButton.frame = frameimg;
Assuming that your _someButton is the name for the IBOutlet of the button from storyboard.
If this does not work, you should go with performSegueWithIdentifier. I do not see the problem with this, either. You anyway include a #selector with the custom UIButton. Just use it to initiate the segue. You can still configure the segue, etc., in the storyboard, so nothing is lost, right? In fact, the refactoring above seems like more work.

Related

Disable UIButton in another UIViewController

I'd like to disable an UIButton in a UITableview in another ViewController:
I tried, inside the SecondViewController, but it only disable the _buttonDesc, buttonCell still is enabled:
buttonCell is the Button inside of UITableView.
buttonDesc is the Button Comprar, inside the SecondViewController.
.
-(IBAction)comprar
{
[_buttonDesc setTitleColor:[UIColor grayColor] forState:UIControlStateDisabled];
[_buttonDesc setEnabled:NO];
LivroCell *lvc = [[LivroCell alloc]init];
[lvc.buttonCell setEnabled:NO];
}
You need a reference to the actual buttonCell you want to disable. Creating a new instance of LivroCell will not help you.
The easiest way to do this is when someone clicks the "Buy" button, and you create the new UIViewController, pass a reference to the buy button (if "Buy" calls an IBAction then pass sender to the child view controller you create). So make a property on your child view controller to store the button, set that property when you do alloc/init, then it's easy to disable later.

Pass data from Viewcontroller to a Label [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Passing Data between View Controllers
iOS dev noob here..
I have a bunch of buttons on my main ViewController, what I want to happen is when the user clicks on one of those buttons, I want it to take them to a separate view that has a label and I want the text in that label to change according to which button they press.
So basically I want to be able to pass data from a button press on the main ViewController to a label in a second view.
That might be a bit confusing and I apologize, but any help would be greatly appreciated.
I would suggest you use a storyboard if possible. You then can ctrl drag from each button to a new viewcontroller that you drag out onto the storyboard. This will setup a segue and you can use the method prepareforseguie to pass the data you need to use in the new view controller.
Assuming your view controller with the buttons is in a navigation controller - presumably at the root...
What you would do is, add a target to each of your buttons, in code this can be done with the method addTarget:action:forControlEvents: of your UIButton
For example:
[myBtn addTarget:self action:#selector(tappedButton:) forControlEvents:UIControlEventTouchUpInside];
The method tappedButton will be messaged with the button that was tapped:
- (void)tappedButton:(UIButton*)sender{
// exploit the button
}
Inside this method you can get the title of the button - myBtn.titleLabel.text
You can then create a new view controller (let's keep things simple and say you have your own UIViewController subclass called MySimpleViewController.
In this class you have a cameFrom property which you can set the button's title on, and in viewDidLoad of MySimpleViewController, you would get the property value of cameFrom, this could be the method implementation.
- (void)tappedButton:(UIButton*)sender{
MySimpleViewController *detail = [[MySimpleViewController alloc] init];
detail.cameFrom = sender.titleLabel.text;
[self.navigationController pushViewController:detail
animated:YES];
[detail release];
}
So over in your MySimpleViewController's viewDidLoad, you create a UILabel, give the text property the value of self.cameFrom and add it to the view with addSubview:

Replacing Storyboard Segue with pushViewController causes strange behaviour

I can't seem to figure this out for the life of me. I have a custom table view cell, in that cell I have a few buttons configured. Each button connects to other view controllers via a storyboard segue. I've recently removed these segues and put a pushViewController method in place. Transition back and forth across the various views works as expected however the destination view controller is not displaying anything! I have some code below as an example.
Buttons have this method set:
[cell.spotButton1 addTarget:self action:#selector(showSpotDetails:) forControlEvents:UIControlEventTouchUpInside];
// etc...
[cell.spotButton4 addTarget:self action:#selector(showSpotDetails:) forControlEvents:UIControlEventTouchUpInside];
// etc...
showSpotDetails Method contains this code:
- (void)showSpotDetails:(id)sender
{
// determine which button (spot) was selected, then use its tag parameter to determine the spot.
UIButton *selectedButton = (UIButton *)sender;
Spot *spot = (Spot *)[spotsArray_ objectAtIndex:selectedButton.tag];
SpotDetails *spotDetails = [[SpotDetails alloc] init];
[spotDetails setSpotDetailsObject:spot];
[self.navigationController pushViewController:spotDetails animated:YES];
}
The details VC does receive the object data.
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"spotDetailsObject %#", spotDetailsObject_.name);
}
The NSLog method below does output the passed object. Also, everything in the details view controller is as it was. Nothing has changed on the details VC. It just does not render anything ever since I removed the segue and added the pushViewController method. Perhaps I am missing something on the pushViewController method? I never really do things this way, I try to always use segues...
Any suggestions?
Welcome to the real world. Previously, the storyboard was a crutch; you were hiding from yourself the true facts about how view controllers work. Now you are trying to throw away that crutch. Good! But now you must learn to walk. :) The key here is this line:
SpotDetails *spotDetails = [[SpotDetails alloc] init];
SpotDetails is a UIViewController subclass. You are not doing anything here that would cause this UIViewController to have a view. Thus you are ending up a with blank generic view! If you want a UIViewController to have a view, you need to give it a view somehow. For example, you could draw the view in a nib called SpotDetails.xib where the File's Owner is an SpotDetails instance. Or you could construct the view's contents in code in your override of viewDidLoad. The details are in the UIViewController documentation, or, even better, read my book which tells you all about how a view controller gets its view:
http://www.apeth.com/iOSBook/ch19.html
The reason this problem didn't arise before is that you drew the view in the same nib as the view controller (i.e. the storyboard file). But when you alloc-init a SpotDetails, that is not the same instance as the one in the storyboard file, so you don't get that view. Thus, one solution could be to load the storyboard and fetch that SpotDetails instance, the one in the storyboard (by calling instantiateViewControllerWithIdentifier:). I explain how to do that here:
http://www.apeth.com/iOSBook/ch19.html#SECsivc

How to wire a Button in a UITableViewCell with its action method

How can I connect a Button in a UITableViewCell with its action method in the UITableViewCell in xcode.
Crtl-Draging from the button to the source doesn´t work.
Create a subclass of UITableViewCell. Then you can hook up your button to an action in your sublass. Connect your button to your own subclass instead of the file's owner.
When dealing with custom cells, note that your "source" is now not the "Files Owner" but rather the "UITableViewCell" object. Hope this does the trick, if not - something is wired wrong in your code / XIB
Do it programmatically. It is the simplest believe me. Every tableViewCell has got a contentView. So all you do is for your specific row in section in -tableView:cellForRowAtIndexPath:
UIButton* cellButton= [UIButton buttonWithType:UIButtonTypeRoundedRect]; // Cane be custom as well
[cellButton addTarget:addTarget:self action:#selector(handleCellButton:) forControlEvents:UIControlEventTouchDown];
// Further changes such as text color whatever ...
[cell.contentView addSubView:cellButton];
//add a handler method for the button
-(void)handleCellButton:(id)sender{}

How do I add a navigation bar's Done button to a popover's passthroughViews?

I'm working in an iPad app that has a split view with a navigation controller in the detail view. The deepest view that can be in the navigation stack is an edit view where the user can edit data. I put an edit button as the rightBarButtonItem and when editing starts, change it to a done button.
When editing commences and the user touches on a particular field, I present a popoverview with a list of possible choices filtered by what they are typing - a form of autofill based on all the values of that field in all other objects.
This works fine, except if you try touching on the done button. The popover eats this touch and dismisses itself. So the user has to touch done again.
I tried using the uipopovercontroller's passthroughViews property, but UIBarButtonItem is not a view and there is no documented way to get the view for the done button or even the navigation bar. I can access the variable in gdb, but it isn't accessible via KVC.
Any ideas on how I can prevent the need to tap done twice?
I've thought about a gesture recognizer on the window, but that seems messy and I'd have to handle rotation.
In case anyone gets here from google, copypaste from other question:
The only solution I found for now is to create UIBarButtonItem with custom UIButton using
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
//code for styling button
UIBarButtonItem *b = [[[UIBarButtonItem alloc]
initWithCustomView:button]
autorelease]
and then
popoverController.passthroughViews = [NSArray arrayWithObject:b.customView];
But be prepared - you cannot create UIButton that looks like UIBarButtoItem. I ended up with creating image that reassembled UIBarButtonItem.