My ipad project is master-detail view based. There is a button on detail view's toolbar, when user tap on the button, it popup a popover view to show four buttons (as menu). Three of buttons' actions are like the following (the three buttons show three different model form sheets):
- (void) showOnlineSgf
{
NSLog(#"showOnlineSgf");
TGOOnlineSgfViewController *dlg =
[[TGOOnlineSgfViewController alloc] initWithNibName:#"TGOOnlineSgfViewController"
bundle:nil];
UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:dlg];
[nav setModalPresentationStyle:UIModalPresentationFormSheet];
[self presentViewController:nav animated:YES completion:nil];
dlg = nil;
nav = nil;
}
The other button's action is to show a MFMailComposeViewController. Code is like the following:
- (void) emailCurrentGame
{
NSLog(#"email current game");
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self;
[self presentModalViewController:picker animated:YES];
picker = nil;
}
The weird behavior is that when I tap the button what should execute showOnlineSgf(), but emailCurrentGame() is actually executed. When I set a breakpoint in showOnlineSgf(), it's hit, and step by step, each statement in showOnlineSgf() is executed. But the result on screen is a MFMainComposeViewController shows up.
I know this question is hard to answer. Any idea is appreciated.
Check your outlet connection of your UIButton that triggers showOnlineSgf. Most likely you copy pasted your UIButton in Interface Builder, which causes it to copy its assigned action as well. Then you've connected your other action, resulting in your UIButton having two actions.
To resolve the problem, simply disconnect your UIButton that triggers showOnlineSgf from the emailCurrentGame action.
Sounds like you copy pasted in the interface builder an already connected button. Check if the button has more than one action assigned.
Related
Note: Problem solved.
Here comes the story. I am using RevealViewController in my project. I am also hiding the navigationBars:
[self.navigationController setNavigationBarHidden];
My project can be seen in the picture below and the "menuButton" is implemented in the tabBarViewController.
Since the navigationBar is hidden due to my interface looks, all tabViews (HomeViewController) will not show the menuButton and the navigationBar as supposed to. I am not using panGestureRecognizer to trigger the menu aswell.
This means I have a problem to trigger the menu via a normal button in HomeViewController. The menuButton-event is placed in tabBarViewController.m:
_menuButton.target = self.revealViewController;
_menuButton.action = #selector(revealToggle:);
So I tried to call a method from HomeViewController to fire the button in tabBarViewController like this:
HomeViewController.m
- (IBAction) onMenuClicked: (id)sender{
tabBar = [[tabBarViewController alloc] init];
[tabBar setupMenu]:
}
tabBarViewController.m
-(void) setupMenu{
[_realMenuButton sendActionForControlEvents:UIControlEventTouchUpInside];
[_realMenuButton addTarget:self.revealViewController action:#selector(revealToggle:) UIControlEventTouchUpInside];
}
In this example I tried to make the realMenuButton and normal UIButton. Ive also tried as a UIBarButtonItem just to trigger the #selector(revealToggle:) But nothing happens in the app when I try to trigger the button from HomeViewController.
Not sure how I shall make this work. Any other Ideas or tricks? Please be specific if so! Regards
Yes, it will still work.
SWRevealViewController is just a subclass of a UIViewController, so you can use it at any point in the app:
By calling presentViewController:animated at some point.
By using it in a navigation stack etc.
Note that you can add gestures from SWRevealViewController to its content view controllers, which will alter the behaviour of used in a navigation view controller, but that's to be expected, and you still have full control over its behaviour.
Edit
The UI structure of your app is still not clear to me - it looks like you're trying to call revealToggle on an instance of SWRevealViewController when the VC in view is infact HomeViewController? How would this work, when SWVC is not even in view?
My best guess is that your UI structure should be as follows:
TabBarController --->(root)UINavigationController --->(root)SWRevealViewController.
Then, on your SWRevealViewController, set HomeViewController as the front view controller, and the TableViewController as the right or left view controller.
Do you mean like this?
it is possible. you can set the menu button in your tabBarController.m, like this :
UIBarButtonItem *menu = [[UIBarButtonItem alloc]initWithImage:[UIImage imageNamed:#"menu.png"] style:UIBarButtonItemStylePlain target:revealController action:#selector(revealToggle:)];
self.navigationItem.leftBarButtonItem = menu;
self.delegate = self;
For me, my initial view controller is the login screen (obviously I don't need reveal any VC here...). then when user tap the login button,
UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:yourRootVC];
LeftMenuViewController *leftMenuVC = [[LeftMenuViewController alloc]init];
SWRevealViewController *revealController = [[SWRevealViewController alloc]initWithRearViewController:leftMenuVC frontViewController:nav];
revealController.delegate = self;
[self presentViewController:revealController animated:YES completion:nil];
I've tried it and it should work as normal. Even it isn't initial view controller
I developed app for iOS and i trie catch the event in a button, that button is in a xib and i create a method when touch up inside.
and i present de view the following form
DetailNoticiaController *detail = [[DetailNoticiaController alloc] init];
[self.view addSubview:detail.view];
detail.view contain the button, when the button is pressed, the app crashed and not show the error.
The problem is that detail deallocates as you don't save it somewhere. You may try code below:
DetailNoticiaController *detail = [[DetailNoticiaController alloc] init];
[self addChildViewController:detail];
[self.view addSubview:detail.view];
Helpful link - "Creating Custom Container View Controllers"
- (void)createBarButtons
{
UIBarButtonItem *myCheckButton = [[UIBarButtonItem alloc] initWithTitle:#"Check Records" style:UIBarButtonItemStylePlain target:self action:#selector(checkRecordsAction)];
UIBarButtonItem *mySaveButton = [[UIBarButtonItem alloc] initWithTitle:#"Save" style:UIBarButtonItemStylePlain target:self action:#selector(saveAction)];
[mySaveButton setTintColor:[UIColor colorWithRed:34.0/255.0 green:97.0/255.0 blue:221.0/255.0 alpha:1]];
NSArray *myButtonArray = [[NSArray alloc]initWithObjects:mySaveButton, myCheckButton,nil];
self.navigationItem.rightBarButtonItems = myButtonArray;
}
I dont know if this question falls under too localized category. But help me out here.So like you see i have created two bar button items. Save is just saving the data onto CoreData,works just fine. But the check records should launch a new UITableviewcontroller.
- (void)checkRecordsAction
{
NSLog(#"the new stack action");
ITMSyncRecordsTVC *syncRecords = [[ITMSyncRecordsTVC alloc]init];
// [self presentViewController:syncRecords animated:YES completion:^{
// self.navigationController.view.superview.bounds = CGRectMake(0, 0, 250, 250);}];
[self.navigationController pushViewController:syncRecords animated:YES];
}
ITMSyncRecordsTVC is a TableViewController with a "Back" button on it.So when i click the check records it launches a tableview controller but no values in it and it does not show the "Back" bar button i put on it. Until now i have been using segues and storyboards just fine. But how do i launch a new view controller without them i dont know. My first leap into ios is ios6. I am missing something I dont know. So let me know how to call/launch a new TableViewController. In android we had intents that did the trick. Please let me know if you need more information. Thanks...
EDIT: So i edited my checkRecordsAction code.
EDIT :
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
ITMOrdersVC *ordersVC = [[ITMOrdersVC alloc]init];
NSLog(#"at line 188 %d",indexPath.row);
if(indexPath.row < self.salesOrdersArray.count)
{
ordersVC.salesOrder = [self.salesOrdersArray objectAtIndex:indexPath.row];
NSLog(#"the sales purchase order number is %#",ordersVC.salesOrder.purchaseOrderNumber);
NSLog(#"done - 140");
[self.navigationController pushViewController:ordersVC animated:YES];
}
}
So on selecting a row on ITMSyncRecordsTVC table view controller it does the above. I get a new ITMOrdersVC screen with "Back" bar button at the left and 2 dynamically generated bar buttons.I get the 2 dynamically generated bar buttons but not the back. I thought once i click the row it will "go back" to previous screen to which i am passing the salesOrder object. My next step was to check if i get the salesorder object from the TVC then load it. So basically 2 screens only. First screen (save,check sync records). Second screen click a.) back(go to first screen..do nothing) or b.)click a row in second screen and populate first screen without the bar button.If it is not clear please ask me.
To launch a new table view controller using storyboards, you want to:
Have your main scene embedded in a navigation controller.
You want to have a push segue from the main controller to the second one. So control-drag from the view controller icon (in the bar below the main scene) to the next scene:
It should then look like (note the appearance of the navigation bar in the destination table view):
Then select the segue and give it a "storyboard identifier":
And now, your code to transition to that scene would look like:
The checkRecordsAction:
- (void)checkRecordsAction
{
NSLog(#"the new stack action");
[self performSegueWithIdentifier:#"PushSegue" sender:self];
}
Update:
By the way, in the interest of full disclosure, there's an alternative to the push segue. If you give that next scene, itself, a "storyboard id", you can use the following code (obviously replacing "insertNextScenesStoryboardIdHere" with the identifier you give your next scene:
- (void)checkRecordsAction
{
NSLog(#"the new stack action");
UIViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"insertNextScenesStoryboardIdHere"];
[self.navigationController pushViewController:controller animated:YES];
}
I personally don't like this as much, as your storyboard now has a scene floating out there without any segue, your code now has dictated the nature of the transition between view controllers vs having everything in the storyboard, etc., but it is another approach.
I asked a question similiar to this before and got many answers first of all thanks for them but because of the complexity of the project I didnt understand the answer so I decided to ask it again this time in a very simple form.
I have one button in viewcontrollerA and I want that button to write on a Label which is in viewcontrollerB.Its simple a button at A will set the Label text on B.
Example
User opens the app
Clicks the button at page A
Second Page comes up and in that page label text is set by the label.text code came from viewcontroller A it calls the code
Or maybe I can call the code of A from B its not important as long as I make it.I can make butons to open another viewcontrolers so you dont need to explain it.
Also if any other ways around and as long as they are simple I can do them too.Maybe I wrote the code elsewhere and call it from A and B.
Please explain it step by stem cause I have little knowlage about objective C and xcode.
I ask this question to learn about connections between viewcontrollers.In reality I will make that button to display a random number at the second page but its not important rightnow cause if I learn to make simple connection I can do the rest.
In your action, you need to have a reference to the second view controller. For example
- (IBAction)buttonAClicked:(id)sender {
ViewController2 *vc2 = [[ViewController2 alloc] initWithNibName:#"ViewController2" bundle:nil];
[self.navigationController pushViewController:vc2 animated:YES];
vc2.someVariable = #"This is random text";
[vc2.someButton setTitle:#"Some button text" forControlState:UIControlStateNormal];
}
This shows how you would create a second view controller, change two properties, and then push it.
In your second view controller create a property called theText that is an NSString and then in the viewDidLoad assign the label.text to the NSString;
- (void)viewDidLoad
{
if(self.theText)
self.label.text = self.theText;
}
Now use your first view controller to set theText in the second view controller.
If you are using a segue use prepareForSegue:
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([[segue identifier] isEqualToString:#"Second View Segue"])
{
SecondViewController *theController = segue.destinationViewController;
theController.theText = #"Some text";
}
}
If you are using some sort of modal presentation:
SecondViewController *theController = [[SecondViewController alloc] init];
theController.theText = #"Some text";
[self presentModalViewController:theController animated:YES];
or if you are using a navigation controller:
SecondViewController *theController = [[SecondViewController alloc] init];
theController.theText = #"Some text";
[self.navigationController pushViewController:theController animated:YES];
So your first view controller will set the NSString property in the second, then the second will set the UILabel equal to the NSString during it's load. You can not set the text of a UILabel before the second view controller is loaded, so something like:
SecondViewController *theController = [[SecondViewController alloc] init];
theController.label.text = #"Some text";
[self.navigationController pushViewController:theController animated:YES];
will not work correctly, because you can't set the text for the label until the view is loaded.
Hope that helps.
I'm attempting to embed an editable UITextView inside a UIPopoverController, with... strange results. The steps I've taken are:
Create a custom UIViewController class, and create a .xib file with that controller with a UITextView inside it.
When the UI action that should bring up the controller occurs (touch up inside), I instantiate the controller and its view from the .xib file.
I create a new UIPopoverController, with the view controller I just instantiated as the content view.
I present it with presentPopoverFromRect:inView:permittedArrowDirections:animated:
Here's some example code:
- (void)noteButtonPressed:(id)sender {
self.noteview = [[MyTextPopupViewController alloc] initWithNibName:#"MyTextPopupViewController" bundle:nil ];
UIPopoverController *popoverController = [[UIPopoverController alloc] initWithContentViewController:self.noteview];
self.popover = popoverController;
self.popover.delegate = self;
[self.popover presentPopoverFromRect:((UIView*)sender).frame
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
}
Then, inside MyTextPopupViewController, I make sure the the text view is the first responder to bring up the keyboard:
- (void)viewDidAppear:(BOOL)animated {
[self.view becomeFirstResponder];
[super viewDidAppear:animated];
}
And that all works... right until it doesn't. Sometimes, it works perfectly; other times, either immediately or after a few keystrokes, the application crashes by exiting the main event loop (!). No exception is thrown (at least not that the lldb catches), but the application simply stops, both on the simulator and on hardware.
Any thoughts? Has anyone gotten this working successfully, or knows for sure that it does not?
I think the UIPopoverController instance needs to be a property in your code.