Swift - TabViewController with SwipeViewControler in one of its tabs - swift

Another newbie to swift here. I want my application to have four tabs on the bottom and inside one of the tabs I want to be able to swipe between two 'pager' style tabs.
I have been able to make the four tabs work at the bottom by starting a new tabbed app and adding two additional view controllers.
Then I tried adding a SwipeViewController (https://github.com/fortmarek/SwipeViewController) to one of the tabs and it worked but it overrode the entry point so all I see is the two SwipeView tabs without the TabController tabs on the bottom.
!I want this inside of the Home tab]1
I think the problem is in my delegate code as it is setting self.window?.rootViewController to the SwipViewController. Getting rid of that assignment makes the Tab Bar show back up, but it is black inside of the Home tab so it is still not working.
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
let pageController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
let navigationController = SecondViewController(rootViewController: pageController)
self.window?.rootViewController = navigationController
self.window?.makeKeyAndVisible()
return true
}
I also tried getting the corresponding window for the "Home" tab from the storyboard and setting the navigation controller to that.
let secondViewControllerWindow = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "Home").view.window
secondViewControllerWindow?.rootViewController = navigationController
secondViewControllerWindow?.makeKeyAndVisible()
But Home is still empty. Here is the ViewController code that is represented by the Home tab and should control the SwipViewController
import UIKit
class SecondViewController: SwipeViewController {
override func viewDidLoad() {
super.viewDidLoad()
let stb = UIStoryboard(name: "Main", bundle: nil)
let page_one = stb.instantiateViewController(withIdentifier: "nba") as UIViewController
let page_two = stb.instantiateViewController(withIdentifier: "mlb") as UIViewController
setViewControllerArray([page_one, page_two])
page_one.title = "NBA"
page_two.title = "MLB"
setFirstViewController(0)
equalSpaces = true
//setButtons(UIFont.systemFontOfSize(18), color: UIColor.blackColor())
//setSelectionBar(80, height: 3, color: UIColor.blackColor())
setButtonsOffset(40, bottomOffset: 5)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
My questions is similar to these other questions but I did not find an answer.
Using Page View Controller inside Tab Swift
Xcode 6 - Swift - Custom Tabbar with Navigation

I faced the same problem recently, and I found the solution here.
https://github.com/fortmarek/SwipeViewController/issues/26
I didn't put the code in didFinishLaunchingWithOptions.
I tried to work on main.storyboard.
I dragged a PageViewController in and set it as your(SecondViewController)'s RootView.
It worked for me.

Related

Safe area not working in custom TabBarController's ViewController

In the didFinishLaunchingWithOptions of my app's AppDelegate, after initializing my UIWindow property, I set the root controller to a subclass of UITabBarController, in which I set the view controllers (and some other custom behaviour).
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = TabBarController() // a subclass of UITabBarController
self.window?.makeKeyAndVisible()
return true
}
The issue I have is that the safe areas in the TabBarController's view controllers does not seem to work properly.
eg: sticking a view to the bottom of a view controller's view, using it's safeAreaLayoutGuide, goes behind the tab bar.
self.bottomView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor)
The custom behaviour (such as set tint colors, set the viewControllers and their tab bar items, or set the tabBarController's delegate - nothing crazy here) setup is made in it's viewDidLoad.
NB: I work in code only, I do not use interface builder.
The issue was the way I presented programmatically the tab bar controller.
What I did in the AppDelegate's didFinishLaunchingWithOptions was :
self.window?.rootViewController = MyTabBarController()
self.window?.makeKeyAndVisible()
I fixed the issue buy putting the tabbar in in a NavigationController :
let navigationController = UINavigationController(rootViewController: MyTabBarController())
self.window?.rootViewController = navigationController
self.window?.makeKeyAndVisible()
Can't reproduce. Here's the complete code for a view controller in a project that does what you seem to describe:
class FirstViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let v = UIView()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .red
self.view.addSubview(v)
v.widthAnchor.constraint(equalToConstant: 100).isActive = true
v.heightAnchor.constraint(equalToConstant: 100).isActive = true
v.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
v.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor).isActive = true
}
}
And here's the result; the red square appears exactly where we expect to see it, pinned to the top of the tab bar:

Height of view as a modal popup - Swift

In the app that I am creating with XCode I created a view that opens as a modal popup. I used this code:
#IBAction func open_view(_ sender: Any) {
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let VC_test_object = storyBoard.instantiateViewController(withIdentifier: "VC_Test")
VC_test_object.modalPresentationStyle = .popover;
self.present(VC_test_object, animated: true, completion: nil)
}
VC_Test is the ViewController in Storyboard. This is the result:
However, I would like to manage the height of the view to create a sort of menu.
As in this example screenshot (from the Documents app):
I can't understand how to do it.
Could you tell me how to manage the height of the popup?
Thanks for your help.
For a code-your-self version this SO link and the answers below it is what you need: Present modal view controller in half size parent controller
However, I would rather use this third party library : Presentr

Launching ViewController as sheet from windowDidLoad

I'm trying to show a storyboard as a sheet right after the window has loaded.
override func windowDidLoad() {
super.windowDidLoad()
let storyboard = NSStoryboard(name: NSStoryboard.Name(rawValue: "Init"), bundle: nil)
let controller = storyboard.instantiateInitialController() as! NSViewController
self.window!.contentViewController?.presentViewControllerAsSheet(controller)
}
Unfortunately, the sheet is shown out of position and behind the window.
When I run the same code inside a button, everything works fine.
Screenshot
How do i correctly show a storyboard sheet after loading a window?
I have more knowledge of the iOS ecosystem but I suppose that you should show new windows only after the origin window has been shown. windowDidLoad is called when the view has been loaded, not when it has been shown.
Therefore, you should probably put your code into viewDidAppear of the contentViewController.

Xcode 8, adding UIButtons to NavigationBar for non initial view controllers

I'm trying to achieve what I think would be a simple task, but despite similar posts on here being answered, the solution eludes me....
I'm using Main.storyboard in Xcode 8/swift 3 to create an application with the initial ViewController being a UINavigationController. I then want to push to UITabBarController which has two view controllers which it holds a relationship with:
override func viewDidLoad() {
super.viewDidLoad()
let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
if let vc = mainStoryboard.instantiateViewController(withIdentifier: "test") as? UITabBarController {
self.navigationController?.pushViewController(vc, animated: true)
}
}
When launching the app, the initial ViewController successfully 'pushes' to the TabBarController/it's ViewControllers (image below). The issue I'm having is after adding navigation items/buttons in the TabBarController ViewControllers (either in Storyboard or programmatically) the buttons / nav items never show.
Storyboard setup
Simulator screenshot
I have seen a few posts such as the below links and have followed the suggested steps verbatim, but nothing has solved the problem. Any help would be greatly appreciated!
Adding buttons to navigation controllers
How to add buttons to navigation controller visible after segueing?
It's does not show, because your TabBarController also have his own UINavigationBar. ViewControllers are inside TabBarController
you can create custom TabBarController and handle tabs actions
Try this code:
class TabBarController: UITabBarController {
override var selectedViewController: UIViewController? {
didSet {
switch self.selectedViewController {
case self.selectedViewController is FirstViewController:
self.navigationItem.rightBarButtonItem = self.firstButton
case self.selectedViewController is SecondViewControlller:
self.navigationItem.rightBarButtonItem = self.secondButton
default:
break
}
}
}
}

How does the SignIn screen get called in Cannonball for iOS?

I'm new to Digits for iOS. I got the authentication part working, and now I'm trying to integrate the sign-in with the rest of my app.
One thing that really puzzles me is that in Cannonball, the Initial View Controller is the main screen. However, when running Cannonball, the first screen I see is the Sign In screen.
I don't see any segue from the Navigation Controller to the Sign In. Also, I've looked at the code in the Theme Chooser View Controller, and don't see any reference to the Sign In's View Controller.
So, how does the Sign In screen actually get executed? Where is that logic happening? Thanks.
The answer is that the AppDelegate.swift file does the logic. The code below were copy/pasted from Cannonball's. I went ahead and added comments (some came with Cannonball).
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool {
// Developers: Welcome! Get started with Fabric.app.
let welcome = "Welcome to Cannonball! Please onboard with the Fabric Mac app. Check the instructions in the README file."
assert(NSBundle.mainBundle().objectForInfoDictionaryKey("Fabric") != nil, welcome)
// Register Crashlytics, Twitter, Digits and MoPub with Fabric.
//Fabric.with([Crashlytics(), Twitter(), Digits(), MoPub()])
Fabric.with([Digits()])
// Check for an existing Twitter or Digits session before presenting the sign in screen.
// Detect if the Digits session is nil
// if true, set the root view controller to the Sign In's view controller
if Twitter.sharedInstance().session() == nil && Digits.sharedInstance().session() == nil {
//Main corresponds to Main.storyboard
let storyboard = UIStoryboard(name: "Main", bundle: nil)
//Sign In's View Controller
let signInViewController: AnyObject! = storyboard.instantiateViewControllerWithIdentifier("SignInViewController")
//Set the UIWindow's ViewController to the SignIn's ViewController
window?.rootViewController = signInViewController as? UIViewController
}
return true
}