How can I trigger one UIViewController of the UITabBarController from another UIViewController? - uitabbarcontroller

I have a project that is a "tab-bar controller" app. The first button is essentially a Home screen. The second one displays a UITableView of content. The third button displays a different UITableView, etc.
From the first view (Home), I have a button on the page that is functionally equivalent to the second-button of the tab controller. It is an alternative path to get to that UITableView. I do not want to send a button press to the AppDelegate's UITabBarController.
The code in HomeViewController that I want is essentially this:
-(IBAction) touchInsideButton:(id)sender {
[self presentModalViewController: [appDelegate secondViewController] animated:YES];
}
or
-(IBAction) touchInsideButton:(id)sender {
AppDelegate *appDelegate = (AppDelegate*) [[UIApplication sharedApplication] delegate];
[appDelegate launchSecondViewController: self];
}
where, "launchSecondViewController" is (uncomment-out one of the two lines)
-(void) launchSecondViewController: (id) sender {
// [self.tabBarController presentModalViewController: secondViewController animated:YES];
// [self.tabBarController.navigationController pushViewController: secondViewController animated:YES];
}
Regardless, all three approaches give the same error:
2013-05-16 12:04:26.977 MyApp[55273:f803] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Application tried to present modally an active controller .'
* First throw call stack:

The problem is that this instance of the second view controller, which you refer to as secondViewController, is already in the interface, as a child of the tab view controller. You cannot have it be there and also present or push it.
The way to manipulate a tab bar controller in code is to set is selectedViewController (or selected index). Try doing that instead.

Related

SWRevealViewController button not work after clicking Back button from another ViewController in Swift

I use SWRevealViewController for my project. My problem is that I can click on the SWRevealView Toggle button at first time and that button does not work after I click on Back button from another view controller and back to that view. Here is the screenshot of my project.
I click on NavigationLeft button from Service View Controller at first and left menu shows up. After that, I click on "Imageview" from that view controller to go to next page.
When I reached to detailed next page, I click on "Back button" and it goes to Service view controller.
At that time , I click on RevealView Toggle button , it does not work. I got error fatal error: unexpectedly found nil while unwrapping an Optional value.
My codes from Service View Controllers are;
override func viewDidLoad() {
super.viewDidLoad()
if self.revealViewController() != nil {
debugPrint("Menu Click")
btnBack.target = self.revealViewController()
btnBack.action = #selector(SWRevealViewController.revealToggle(_:))
self.revealViewController().panGestureRecognizer()
}
else
{
debugPrint("nil")
btnBack.target = self.revealViewController()
btnBack.action = #selector(SWRevealViewController.revealToggle(_:))
// self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
self.revealViewController().panGestureRecognizer()
}
}
When the project runs first time, the code passes to "self.revealViewController() != nil" and I go to detailed view controller and click on Back button. At that time the code passes to " debugPrint("nil")" and it does not show up menu or work.
Codes from Detailed view controller are;
#IBAction func btnBack(_ sender: UIBarButtonItem) {
debugPrint("BtnBack")
self.dismiss(animated: true, completion:nil)
}
Is my code is something wrong or logic wrong ? I have been trying to solve this problem since one week. Please help me ..
On click event of image view in serviceViewController,
let detailVC = self.storyboard?.instantiateViewController(withIdentifier: "Detail") as! DetailVc
self.navigationController?.pushViewController(detailVC, animated: true)
Attach a navigation controller to detail viewcontroller. No need for manual connection between service and detail.
Add a barbutton for goingback event.
self.navigationController?.popViewController(animated: true)
Also add self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer()) instead of ur code in the lastline of adding target for menubutton.
Check whether this works.

How to pop self and then perform a segue from the parent view controller?

I have a tableview view controller named ItemsViewController embedded in a navigation view controller that displays items .
Flow 1 (works as expected)
I have a 'New Item' button on the ItemsViewController which when clicked shows a view controller popup (AddItemViewController) where you can add the item's name and other details. When you click 'Save' the view is popped and the ItemsViewController is displayed showing the newly created item.
Flow 2
While creating a new item if you click 'Save and Open' I want it to pop the AddItem view controller and push the itemDetail view controller showing the newly created item's name and other item details.
So inside the AddItemsView controller's 'Save and open' action I have:
dismiss(animated: true, completion: {
self.performSegue(withIdentifier: "ShowItemList", sender: newItemList)
})
This dismisses the Itemsview controller but then it crashes with thread 1: signal SIGABRT.
EDIT
If I refer to the parent it dismisses the add view controller but doesn't perform the segue
dismiss(animated: true, completion: {
self.parent?.performSegue(withIdentifier: "ShowItemList", sender: newItemList)
})
do following:
1) call dismiss method in addItemViewController
self.dismiss(animated: true, completion: nil)
self.delegate.methodToCall()
you have to make delegate when you back from addItemViewController and implement method in parent class when you back from addItemViewController
2) Then in your itemsViewController immplement that method like
func yourMethodToCall() {
self.perform(#selector(ItemViewController.temp), with:nil, afterDelay: 0.4)
}
func temp(){
// push view controller here
}

How to set initial focus to a button in a viewController from a UITabBarController?

I have a basic application with a UITabBarController which contains 2 UIViewControllers.
The first ViewController has a UIButton in it.
I'm trying to get the tabBar menu hidden and the button focused when the app launches.
I set the tabBar as hidden, and it does not show on launch as expected. Unfortunately, the button doesn't have the focus.
From what I understand from Apple doc, the "focus chain" engine will set focus on the first visible and focusable item in the window hierarchy.
Can anyone help me on this ?
Thank you.
Solution 1.
I think what you can do :
1.Subclass or Customize TabBarController and set
set first launch = true in viewdidload of tabController
> override weak var preferredFocusedView: UIView? { if
> (self.firstLaunch) {
> self.firstLaunch = false;
> return self.selectedViewController!.preferredFocusedView; } else {
> let view = super.preferredFocusedView
> return view; }
Hope it helps.It worked for me though
Your focus engine takes the rootView controller as TabBarController and then asks for preferred focus view which is returned as UITabBarItem we need to unfocus that subclassing the class and returning canBecomeFocus to NO.
if you want to change the focus of the element in the firtsViewController then you can overrirde func preferredFocusView and reutrn the view you want to be focussed else preferredFocusView
Solution 2. Just set the root View controller as the HomeViewController without the TabBarController and embed the TabBarController from the second page. This is because anyways you don't need to use TabBar on the first page why need to take care of its focus.
TabBar is set to hidden if you hide from the AppDelegate or the view which is loaded but it has the focus.

How to jump to tabbarcontroller from uiviewcontroller?

I have a ViewController as initial view controller and TabbarController. There are 3 buttons on view controller and TabbarController has 3 Tabs.
I would like tapping the first button jump to first tab, second button - to the second Tab etc.
How should I do that? I'm working with storyboard
Please Clarify your question if you just want to move your tab with click on button the use selectedatindex method for tab bar.
try this,
step 1 ->import appDelegate class in your ViewController.m
#import "AppDelegate.h"
- (IBAction) BtnOneClicked: (id) sender
{
AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
[appDelegate.tabBarController setSelectedIndex:0];
}
- (IBAction) BtnTwoClicked: (id) sender
{
AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
[appDelegate.tabBarController setSelectedIndex:1];
}
- (IBAction) BtnThreeClicked: (id) sender
{
AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
[appDelegate.tabBarController setSelectedIndex:2];
}
A normal View Controller Button Click Event We can jump On Tab bar Controller as simple as Normal just Crete a cocoatouch class which will we sub class of UitabBarController and present to the View.
#IBAction func goActivityView(_ sender: Any) {
let gotoActivityView = storyboard?.instantiateViewController(withIdentifier: "TabBarViewController") as! TabBarViewController
self.present(gotoActivityView, animated: false, completion: nil)
}

iPhone ModalViewController from First Tab Bar View

I am trying to launch an initial login/registration screen before my TabBarController View loads. I have read that putting a ModalViewController in the First View is a good way to go. This works, but I am trying to add navigation controls to the ModalViewController. I am getting the following issues:
1 - ERROR: Property 'navigationController' not found on object of type 'AppDelegate'
2 - WARNING: Initializing 'AppDelegate *'with an expression of incompatible type 'id'
here is the code on my ModalViewController:
-(IBAction)signUpButtonTapped {
// i need to get the control for main navigation controller
AppDelegate *appDelegate = [[UIApplication sharedApplication]delegate];
[appDelegate.navigationController popToRootViewControllerAnimated:NO];
// create object from app main view to push it
SignUpViewController *signUpViewController = [[SignUpViewController alloc] initWithNibName:#"SignUpViewController" bundle:nil];
[AppDelegate.navigationController pushViewController:signUpViewController animated:YES]; }
Anyone have any ideas? Thanks so much!
There are Two Problems in your code
1) Accessing the OBJECT with class name. It must be appDelegate.nav... (small a for Solving 1 ERROR)
[appDelegate.navigationController pushViewController:signUpViewController animated:YES];
2) Type Casting the assignment (for Solving 2 Warning)
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
So your Complete working Code must go as
-(IBAction)signUpButtonTapped {
// i need to get the control for main navigation controller
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
[appDelegate.navigationController popToRootViewControllerAnimated:NO];
// create object from app main view to push it
SignUpViewController *signUpViewController = [[SignUpViewController alloc] initWithNibName:#"SignUpViewController" bundle:nil];
[appDelegate.navigationController pushViewController:signUpViewController animated:YES];
}
AppDelegate instance declaration is like this:
AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication]delegate];
Change this and u r good to go.
In your Code Modify this Line
AppDelegate *appDelegate = [[UIApplication sharedApplication]delegate];
as
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
and try now
1.make sure your appDelegate have a UINavigationController property called navigationController.
2.Line 2 of your code:
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
3.last line of your code:
[appDelegate.navigat.... NOT:[AppDelegate.navigatio....