Change ViewController if user logged on - ios

There is such code, if user logged on - ViewController changes :
func ifLogged() {
let preferences = UserDefaults.standard
let token = "token"
if preferences.object(forKey: token) == nil {
// Doesn't exist and stop at the same viewController
} else {
let newViewController = GeneralChooser()
self.navigationController?.pushViewController(newViewController, animated: false)
// push new generalChooser when logged
}
}
But in this case I do not see view elements, just background color from ViewHelper class
class GeneralChooser: UIViewController{
override func viewDidLoad() {
super.viewDidLoad()
ViewHelper.BackGroundColor(view: self.view)
There is BackgroundColor func below
class func BackGroundColor(view: UIView){
let startColor = UIColor(red:0.15, green:0.50, blue:0.70, alpha:1.0)
let endColor = UIColor(red:0.58, green:0.65, blue:0.81, alpha:1.0)
let newLayer = CAGradientLayer()
newLayer.colors = [startColor.cgColor,endColor.cgColor]
newLayer.zPosition = -1
newLayer.frame = view.frame
view.layer.addSublayer(newLayer)
If i do not call this function in GeneralChooser class, the screen is black and there are not view elements, but in initial ViewController i see view elements, just background color is default.
What am I doing wrong. Thanks for all.

The problem is in this line
let newViewController = GeneralChooser()
this line doesn't load xib or reference the storyboard object associated with that class
Use instantiateViewController and give the viewController storyboard ID in storyboard say GeneralChooserView
let vc = self.storyboard?.instantiateViewController(withIdentifier:"GeneralChooserView")
self.navigationController?.pushViewController(vc!, animated: true)
Or if you are using xibs with GeneralChooser as xib file for GeneralChooser class
let vc = GeneralChooser(nibName: "GeneralChooser", bundle: nil)
self.navigationController?.pushViewController(vc, animated: true)

Related

Add UIViewController made via storyboard to TabBarController.setViewControllers

I am failing to understand the fundamentals of what is needed to add my HomeViewController (UIViewController) as one of the tabs in my homeTabBarController (UITabBarController) using the setViewControllers method.
I have tried initializing this and simply adding it as a param in the method. There seems to be a difference between a view controller created via storyboard and one created programmatically because when I tried adding a viewcontroller:UIViewController programmatically to the setViewControllers method, it worked fine.
My code below compiles however I get a runtime exception Thread 1: EXC_BAD_ACCESS (code=2, address=0x7ff7b8491598) at the line when homeTabBarController.setViewControllers is called
`
func loadTabBar() {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let homeViewController = storyboard.instantiateViewController(identifier: Constants.Storyboard.homeViewController) as? HomeViewController
homeViewController!.title = "Home"
homeTabBarController.setViewControllers([homeViewController!], animated: false)
homeTabBarController.modalPresentationStyle = .fullScreen
present(homeTabBarController, animated: true)
}
`
//MARK: - Create the instances of ViewControllers
let grayViewController = HomeViewController()
let blueViewController = FirstViewController()
let brownViewController = SecondViewController()
override func viewDidLoad() {
super.viewDidLoad()
//set title of the viewcontrollers
grayViewController.title = "home"
blueViewController.title = "first"
brownViewController.title = "second"
//Assigne the viewcontrollers to the TabBarViewController
self.setViewControllers([ grayViewController, blueViewController, brownViewController], animated: false)
//set system images to each tabBars
guard let items = self.tabBar.items else {
return
}
let images = ["house.fill", "star.fill", "bell.fill"]
for i in 0...2 {
items[i].image = UIImage(systemName: images[i])
}
self.tabBar.tintColor = .black
}
// You can download the project from the below github link
https://github.com/ahmetbostanciklioglu/AddingTabBarControllerProgrammatically.git

SWIFT: If I implement the UITAB bar programmatically, is it possible to edit the different tabItems inside the storyBoard

I have implemented a tabBar programmatically:
class ViewController: UIViewController {
let tabBarCnt = UITabBarController()
override func viewDidLoad() {
super.viewDidLoad()
tabBarCnt.tabBar.tintColor = UIColor.black
createTabBarController()
}
func createTabBarController() {
let firstVc = UIViewController()
let downloadViewController = DownloadsViewController()
downloadViewController.tabBarItem = UITabBarItem(tabBarSystemItem: .downloads, tag: 0)
let bookmarkViewController = BookmarksViewController()
bookmarkViewController.tabBarItem = UITabBarItem(tabBarSystemItem: .bookmarks, tag: 1)
let favoritesViewControllers = FavoritesViewController()
favoritesViewControllers.tabBarItem = UITabBarItem(tabBarSystemItem: .favorites, tag: 2)
// Adding navigationControllers
let controllerArray = [downloadViewController, bookmarkViewController, favoritesViewControllers]
// For somereason this made the word Home appear in first tab
tabBarCnt.viewControllers = controllerArray.map{ UINavigationController.init(rootViewController: $0)}
self.view.addSubview(tabBarCnt.view)
}
}
DownloadViewController.swift
class DownloadsViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.green
self.title = "Downloads"
}
}
This is the result:
MY QUESTION IS:
Do I have to implement all the layouts of the different viewControllers downloadViewController, bookmarkViewController, favoritesViewControllers programmatically?
Can't I use the storyboard and associate a viewController and do all the UI design and implementation there like this:
The problem here is that if I will implement all the layout programmatically, it won't be an obvious or a practical thing to do.
And assigning DownloadsViewController to that storyboard ViewController, doesn't make it get display it when I navigate to DownloadsTab in the UITabBar.
Yes, you can do that currently your creating view controller instance programmatically, instead of that you have to load/get viewController instance from storyBoard like this.
UIStoryboard(name: "Main", bundle: Bundle.main).instantiateViewController(identifier: "downloadsVC") as! DownloadsViewController
before calling this method set viewController StoryboardID

How could I pass data to childView

About
I'm developping ios app with MXParallaxHeader.
I use it in order to create twitter-like UI.
However, I don't know how to pass data from MXScrollView to childViewController when I go MXScrollView page.
Question
How could I pass data from MXScrollView to childViewController?
Sample Code
PreviousViewController
//MXScrollViewController=ParentVC of MarkerInfoTabViewController
class PreviousViewController:UIViewController {
.
.
#IBAction func goMXScrollView(_ sender: Any) {
let nextView = self.storyboard?.instantiateViewController(withIdentifier: "MXScrollViewController") as! MXScrollViewController
self.navigationController?.pushViewController(nextView, animated: true)
}
}
childViewController
//MarkerInfoTabViewController(=childVC of MXScrollView)
import Tabman
import UIKit
import MXParallaxHeader
class MarkerInfoTabViewController: TabmanViewController {
var marker:Marker!
private var viewControllers = [UIViewController?]()
override func viewDidLoad() {
super.viewDidLoad()
let leftView = self.storyboard?.instantiateViewController(withIdentifier: "MarkerInfoLeftViewController") as! MarkerInfoLeftViewController
let rightView = self.storyboard?.instantiateViewController(withIdentifier: "MarkerInfoRightViewController") as! MarkerInfoRightViewController
//↓I want to pass data here
leftView.marker = marker
viewControllers = [leftView, rightView]
self.dataSource = self
// Create bar
let bar = TMBar.ButtonBar()
bar.layout.transitionStyle = .snap // Customize
// Add to view
addBar(bar, dataSource: self, at: .top)
}
}
My App Image
・storyboard
・segue to header
・segue to childVC
Reference
My app is mostly the same as this app.
Just define a property in the child controller class
class ChildViewController {
var passedData: MY_DATA_TYPE
...
and set it after the instantiation
let nextView = self.storyboard?.instantiateViewController(withIdentifier: "ChildViewController") as! ChildViewController
nextView.passedData = MY_PASSED_DATA
self.navigationController?.pushViewController(nextView, animated: true)

Swift:Updating UILabel from AppDelegate label doesn't update

I'm trying to update UILabel from appDelegate but the label never change the text. Here is my code:
ViewController:
#IBOutlet weak var lblToUpdate: UILabel?
Here is my app delegate:
DispatchQueue.main.async{
let storyboard = UIStoryboard(name:"Main", bundle:nil)
let myVC = storyboard.instantiateViewController(withIdentifier: "myVC") as! myViewController
if let text = newText{
myVC.text?.text = text
}
}
I have no errors of any kind but the the label never updates.
Any of you knows why the label never gets updated?
I'll really appreciate your help.
The problem is that this VC
let myVC = storyboard.instantiateViewController(withIdentifier: "myVC") as! myViewController
is not the presented one you have to query the window for it and change it's label as you currently play with another one
its not working because the label doesn't exists in the time, just pass the value to a variable in your next controller and then in some of the methods for example :
viewdidload you can update your label with the value of the variable for example :
DispatchQueue.main.async{
let storyboard = UIStoryboard(name:"Main", bundle:nil)
let myVC = storyboard.instantiateViewController(withIdentifier: "myVC") as! myViewController
if let text = newText{
myVC.theVariable = text
}
}
class NextViewController: UIViewController {
var theVariable = ""
override func viewDidLoad() {
super.viewDidLoad()
lblToUpdate.text = theVariable
}
You shouldn't create new instance because is other viewcontroller, this already exist.
You should access to rootViewcontroller and follow window hierarchy
DispatchQueue.main.async{
if let vcroot = self.window!.rootViewController {
if let text = newText{
vcroot.text?.text = text
}
}
}
This code above is example to refer you question.
If you have navigationcontroller is for example:
DispatchQueue.main.async{
if let navroot = self.window!.rootViewController as? NavigationController{
if let childvc = navroot.childviewcontrollers.first {
if let text = newText{
childvc.text?.text = text
}
}
}
}
If have severals viewcontroller in navigation controller you will access using for loop and check and arrive to the viewcontroller that wish change value property or set values

How to display custom size (using preferredContentSize) popup from a "custom" table cell (UITableViewCell)

Summary:
I am able to get a full-screen popover but NOT a custom-size popover through a button action within a custom table cell. I am able to get it working though when the button is not within a custom cell. Upon debugging it seems that when the button is within the custom table cell the delegate object of the popoverPresentationController is not being called which is the one that resizes the popover window.
Details:
Following is the code that works when button is outside of UITableViewCell:
import UIKit
import AVKit
import CoreGraphics
class ViewController: UIViewController, UIPopoverPresentationControllerDelegate {
func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
// This delegate function ensures that popup size is constrained to
// what's specified in preferredContentSize earlier.
return UIModalPresentationStyle.none
}
// This is triggered by a button in UIViewController.. nothing to do
// with the UITable here. This implementation works.
#IBAction func buttonpressed(_ sender: AnyObject) {
let sb = self.storyboard
let vc: AnyObject! = sb!.instantiateViewController(withIdentifier: "popover")
let pc = vc as! PopOverWindow
pc.modalPresentationStyle = UIModalPresentationStyle.popover
pc.preferredContentSize = CGSize(width: 100, height: 100)
// Needs to be called BEFORE we access
// popoverPresentationController below. Counter-intuitive but this
// is how apple docs recommend it
self.present(pc, animated: true, completion: nil)
let popover = pc.popoverPresentationController
popover?.permittedArrowDirections = UIPopoverArrowDirection.any
popover?.delegate = self
let button = sender as! UIButton
// Need both statements below so that popover knows where to be
// tethered
popover?.sourceView = sender as? UIView
// the position of the popover where it's showed
// do not use buttons.frame
popover?.sourceRect = button.bounds
}
Important function here is adaptivePresentationStyle() which makes sure that the popup is not full screen.
Now, let's try to the same in a custom UITableViewCell. Biggest change here is that UITableViewCell is NOT a descendant of UIViewController
#IBAction func infoButtonTouchDown(sender: AnyObject) {
let sb = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())
let vc: AnyObject! = sb.instantiateViewControllerWithIdentifier("popover")
let pc = vc as! PopOverWindow
pc.modalPresentationStyle = .Popover
pc.preferredContentSize = CGSizeMake(50,100)
// Custom View Cell is not UIViewController so I need to following
// to be able to call presentViewController later
// I could have also done
//self.window!.rootViewController?.presentViewController(..)
// but the results were the same
let t = self.window?.rootViewController as! UITabBarController
let n = t.selectedViewController as! UINavigationController
let m = n.visibleViewController as! MyTableViewController
// Important: this needs to be called BEFORE we access
// pc.popoverPresentationController object. Apple Docs say it.
m.presentViewController(pc, animated: true, completion: nil)
let popover = pc.popoverPresentationController
popover?.permittedArrowDirections = UIPopoverArrowDirection.Any
// I tried doing popover?.delegate = d to make the underlying table
// as the delegate object but the results were same
popover?.delegate = self
let viewForSource = sender as! UIView
popover?.sourceView = m.view
// the position of the popover where it's showed
// just some random position in view.
popover?.sourceRect = CGRectMake(100,100,1,1)
}
The TROUBLE in above code is that the delegate function adaptivePresentationStyle() is not being called and consequently I end up getting a full-screen popover and not a half-screen.
Any help is hugely appreciated!

Resources