Loading a ViewController from nib file owner - ios

I have a design made in nib and in round about all ViewControllers I am loading that nib design.
Now as that was common footer so I managed to used it in the footer of all other view controllers.
Now what I want : I want that whenever User click on a footer it must start a new View Controller that will show what you can say "About us " view controller.
What I am doing:
// ON CLICK OF FOOTER I AM DOING
let mAboutUs = self.storyboard?.instantiateViewController(withIdentifier: "idAboutUs") as! AboutUs
mAboutUs.modalPresentationStyle = .fullScreen
self.present(mAboutUs, animated: true) {
}
but I am getting following error
Value of type 'FooterView' has no member 'storyboard'
My Understanding: I think from nib file we can not start a new ViewController, But I really do not want to do this thing in all other View controllers in which I added this nib (FooterView) as my footer view at bottom of each view controller.
Please help me!!!!

A UIView subclass doesn't contain a storyboard property it's for a vc subclass , You need
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "idAboutUs") as! AboutUs
if you want to present a vc from inisde the view FooterView then add a delegate like
weak var delegate:VCName?
When you create an instance
let ins = FooterView() // or from storyboard
ins.delegate = self
Then use
delegate?.present(mAboutUs, animated: true)
inside the view's class
You can use a delegate that all vcs conforms to but the easiest is to add this extension
extension UIViewController {
func topMostViewController() -> UIViewController {
if let presented = self.presentedViewController {
return presented.topMostViewController()
}
if let navigation = self as? UINavigationController {
return navigation.visibleViewController?.topMostViewController() ?? navigation
}
if let tab = self as? UITabBarController {
return tab.selectedViewController?.topMostViewController() ?? tab
}
return self
}
}
Then
guard let currentVC = (UIApplication.shared.delegate as! AppDelegate).window?.rootViewController.topMostViewController() else { return }
currentVC.present(mAboutUs, animated: true)

Your code should look similar to this:
let vc = UIStoryboard(name: "<Name of the storyboard that contains the About Us VC>", bundle: nil).instantiateViewController(withIdentifier: "idAboutUs") as! AboutUs
self.present(vc, animated: true) {
}

Related

How can i pop back from storyboard of framework?

let storyboardBundle = Bundle(identifier: "SignUPFramework")
let vc = UIStoryboard.init(name: "SignIn", bundle: storyboardBundle).instantiateViewController(withIdentifier: "SignInViewcontroller") as! SignInViewcontroller
navigationController?.pushViewController(vc, animated: true)
I have navigated to storyboard of framework as above.
You own the navigationController. So you can use either popViewController(animated:) (if you are sure that there is only one view controller you wish to pop), or popToViewController(_:animated:), or popToRootViewController(animated:) (if you wish to return to the root).
It does not matter that the storyboard is in a framework. You still own the view hierarchy, the navigation stack and the view controller instance you get from the below line of code
let vc = UIStoryboard.init(name: "SignIn", bundle: storyboardBundle).instantiateViewController(withIdentifier: "SignInViewcontroller") as! SignInViewcontroller
So you can do whatever you want with it in terms of navigation (push it and pop it or present it and dismiss it).
You just need to identify at what point you want to trigger any of these actions.
I think you are using xib so it will not return action first you should do protocol for callback to view controller then you can use popViewController(animated:).
protocol CallBackDelegate: AnyObject {
func back()
}
//Delegate
weak var delegate:CallBackDelegate?
#IBAction func buttonAction(_ sender: Any) {
delegate?.back()
}
Now you can use protocol in view controller
class ViewController: UIViewController, CallBackDelegate {
func back() {
navigationController?.popViewController(animated: true)
}
}
Note :- Confirm delegate variable in cellForRowAtIndexPath i.e.
cell.delegate = self
I have solved it by
let bundle = Bundle(for: SignInViewcontroller.self)
let vc = UIStoryboard.init(name: "SignIn", bundle: bundle).instantiateViewController(withIdentifier: "SignInViewcontroller") as! SignInViewcontroller
in above snippet instead of passing bundle id i have passed viewcontroller itself.

Transition to MainVC gives the empty View without subviews

I'm using this type of transition to UIViewcontroller:
self.navigationController?.popToViewController(MainVC(), animated: false)
And in result i want to receive the MainVC with all subviews... but i receive only empty main View without any subviews. What i did wrong?
Update:
I have the transition to MainVC, but it's empty, only initial View, without all subviews. What is the reason?
You should pass object of MainVC()
like below
let objOfMainVC = MainVC()
self.navigationController?.popToViewController(objOfMainVC, animated: false)
If you are using storyboard then
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let main = storyBoard.instantiateViewController(withIdentifier: "MainVC") as! MainVC // set withIdentifier to your identifier that was set in your storyboard.
self.navigationController?.pushViewController(main, animated: false)
You need the reference of MainVC. You can't just create a new instance of MainVC()
if let viewControllers = self.navigationController?.viewControllers {
for vc in viewControllers {
if let _ = vc as? MainVC {
self.navigationController?.popToViewController(vc, animated: true)
break
}
}
}
Or if your MainVC is root view controller of navigation controller.
self.navigationController?.popToRootViewController(animated: true)

Show ViewController after LaunchScreen loaded

I'm trying to create a walkthrough(intro) for my app. I am using BWWalkthrough to do it. If want to open this view controller after clicked a button, it works(as you can see in below codes). But I don't want to do this. I want to open this view controller after launch screen loaded.
When I clicked "is initial View Controller" for the master page and added below code in viewDidLoad method, I can see only master page but I can't see view controllers(page_one, page_two ...) attached to master page. Probably I must write some codes in AppDelegate but I don't know how is it
How can I solve this problem?
#IBAction func testButton(_ sender: Any) {
let goStoryboard = UIStoryboard(name: "Main", bundle: nil)
let walkthrough = goStoryboard.instantiateViewController(withIdentifier: "master") as! BWWalkthroughViewController
let page_one = goStoryboard.instantiateViewController(withIdentifier: "page1") as UIViewController
let page_two = goStoryboard.instantiateViewController(withIdentifier: "page2")as UIViewController
let page_three = goStoryboard.instantiateViewController(withIdentifier: "page3")as UIViewController
**// Attach the pages to the master**
walkthrough.delegate = self
walkthrough.add(viewController:page_one)
walkthrough.add(viewController:page_two)
walkthrough.add(viewController:page_three)
self.present(walkthrough, animated: true, completion: nil)
}
First of all, go to your Main storyboard and create a new view controller. You should also create a view controller class. This is going to be your Home screen storyboard and you're going to set it as your Initial View Controller.
In the class that you previously created, you can put this:
class HomeViewController: UIViewController {
override viewDidLoad(){
super.viewDidLoad()
let goStoryboard = UIStoryboard(name: "Main", bundle: nil)
let walkthrough = goStoryboard.instantiateViewController(withIdentifier: "master") as! BWWalkthroughViewController
let page_one = goStoryboard.instantiateViewController(withIdentifier: "page1") as UIViewController
let page_two = goStoryboard.instantiateViewController(withIdentifier: "page2")as UIViewController
let page_three = goStoryboard.instantiateViewController(withIdentifier: "page3")as UIViewController
// Attach the pages to the master
walkthrough.delegate = self
walkthrough.add(viewController:page_one)
walkthrough.add(viewController:page_two)
walkthrough.add(viewController:page_three)
self.present(walkthrough, animated: true, completion: nil)
}
}

How do I present a new UIViewController when Storyboard Refrences are used

So I am using some Storyboard References to bring in some structure. Now I am trying to change the ViewController from code, but I am not able to use a ViewController from a different Storyboard. My Code is currently looking like that:
func showCommunityDetail(){
let storyBoard : UIStoryboard = UIStoryboard(name: "community", bundle:nil)
let nextViewController = storyBoard.instantiateViewController(withIdentifier: "communityDetail") as! CommunityViewController
self.present(nextViewController, animated:true, completion:nil)
}
The community Storyboard contains the communityDetail controller, but the view which is shown at the moment this code is executed, is in a different storyboard.
How can I present between different Storyboards?
Update
I updated my code to the following line:
let detailViewController = UIStoryboard(name: "community", bundle: nil).instantiateViewController(withIdentifier: "communityDetail");
However, now i get a new error: whose view is not in the window hierarchy!
To present a view controller in a different storyboard.
1) Make sure the "Initial View Controller" property is set for the entry ViewController in each of the storyboards.
Present it:
let vcToPresent = UIStoryboard(name: "StoryboardName", bundle: nil).instantiateInitialViewController();
// Ensure its of the type that you want, so that you can pass info to it
guard let specialVC = vcToPresent as? SpecialViewController else {
return
}
specialVC.someProperty = somePropertyToPass
self.present(specialVC, animated: true, completion: nil)
Edit:
To instantiate a different viewcontroller (other than the one who is marked as initial) the following method can be used:
func instantiateViewController(withIdentifier identifier: String) -> UIViewController
Link to the documentation: https://developer.apple.com/reference/uikit/uistoryboard/1616214-instantiateviewcontroller
Note that you MUST set an identifier on the interface builder for the viewcontroller you want to use this method with.
Just worked on the requirement you asked for and it is in swift 2.2. Try it out it works this way.
var nextViewController : CommunityViewController!
func showCommunityDetail() {
let mainStoryboard = UIStoryboard(name: "community", bundle: nil)
nextViewController = mainStoryboard.instantiateViewControllerWithIdentifier("communityDetail") as! CommunityViewController
addChildViewController(nextViewController)
// Optionally you can change the frame of the view controller to be added
nextViewController.view.frame = CGRect(x: 0, y: 0 , width: view.frame.width, height: view.frame.height)
view.addSubview(nextViewController.view)
nextViewController.didMoveToParentViewController(self)
}

Push another Viewcontroller from action button in xib file

I have a viewcontroller that presents from a .xib.
Inside the .xib there is a button; I want the button to pushviewcontroller to an other viewcontroller (ViewControllerPeopleNew).
I use an action button:
#IBAction func _hitPeople(sender: AnyObject) {
let mapViewControllerObejct = self.storyboard?.instantiateViewControllerWithIdentifier("peoplenew") as? ViewControllerPeopleNew
self.navigationController?.pushViewController(mapViewControllerObejct!, animated: false)
}
But got an error:
Signal SIGABRT
unrecognized selector sent to instance
I already checked all about name identifier viewcontroller and all is right.
From view controller present with XIB you can not get storyboad use below code
#IBAction func _hitPeople(sender: AnyObject) {
let storyboard = UIStoryboard(name: "storyboadname", bundle: nil)
let mapViewControllerObejct = storyboard.instantiateViewControllerWithIdentifier("peoplenew") as? ViewControllerPeopleNew
self.navigationController?.pushViewController(mapViewControllerObejct!, animated: false)
}
Always remember that you can only use self.storyBoard to instantiate a view controller when both the view controllers (To and From view controllers) belong to the same storyboard. If not then you need to first get a reference to the storyboard your To view controller belongs to. So you need to do this:
#IBAction func _hitPeople(sender: AnyObject) {
let stotyboard = UIStoryboard(name: "YourStoryboard", bundle: nil)
let mapViewControllerObejct = storyboard?.instantiateViewControllerWithIdentifier("peoplenew") as? ViewControllerPeopleNew
self.navigationController?.pushViewController(mapViewControllerObejct!, animated: false)
}
PS: Just be sure that your From view controller is in the navigation stack i.e. self.navigationController is not nil.

Resources