Push View Controller From Child View Controller - ios

I have an app where there is a "DadViewController" which contains a UIScrollView that has paging enabled. Each page is populated with a different UIViewController.
How Do I push a new UIViewController, from a button tap, within one of the controllers contained in the UIScrollView?
class DadView: UIView {
let model = DadModel()
let scrollView: UIScrollView = {
let view = UIScrollView()
view.isPagingEnabled = true
// Additional setup...
return view
}()
override init(frame: CGRect) {
super.init(frame: frame)
setupScrollView()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
fileprivate func setupScrollView() {
self.addSubview(scrollView)
// Autolayout code to pin scrollview to all 4 sides
let vc1 = VC1()
scrollView.addSubview(vc1.view)
vc1.view.frame = CGRect(x: 0, y: 0, width: SCREEN_WIDTH, height: SCREEN_HEIGHT)
// Add additional view controller views with the appropriate frames...
}
}
class DadController: UIViewController {
var dadView: DadView!
override func loadView() {
super.loadView()
dadView = DadView()
view = dadView
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
class VC1: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .green
}
}

Change your DadView setupScrollView to accept a UIViewController instance as argument. And don't call this method in init
class DadView: UIView {
let model = DadModel()
let scrollView: UIScrollView = {
let view = UIScrollView()
view.isPagingEnabled = true
// Additional setup...
return view
}()
override init(frame: CGRect) {
super.init(frame: frame)
// setupScrollView()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
fileprivate func setupScrollView(_ parentVC: UIViewController) {
self.addSubview(scrollView)
// Autolayout code to pin scrollview to all 4 sides
let vc1 = VC1()
vc1.view.frame = CGRect(x: 0, y: 0, width: SCREEN_WIDTH, height: SCREEN_HEIGHT)
parentVC.addChild(vc1)
scrollView.addSubview(vc1.view)
vc1.didMove(toParent: parentVC)
// Add additional view controller views with the appropriate frames...
}
}
In DadViewController after creating DadView instance call setupScrollView method with self
class DadController: UIViewController {
var dadView: DadView!
override func loadView() {
super.loadView()
dadView = DadView()
dadView.setupScrollView(self)
view = dadView
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
Then you can get parent view controller from child viewcontroller and perform push
class VC1: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .green
}
#IBAction func buttonAction(_ sender: UIButton) {
self.parent?.navigationController?.pushViewController(NewVC(), animated: true)
}
}

Related

Add CAGradientLayer to view

I have this custom UIView
import UIKit
class LoginView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
setupBackground()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupBackground()
}
private func setupBackground() {
let gradientLayer = CAGradientLayer()
gradientLayer.colors = [
UIColor(r: 0, g: 17, b: 214).cgColor,
UIColor(r: 0, g: 9, b: 119).cgColor
]
gradientLayer.locations = [0, 1]
gradientLayer.frame = bounds
layer.addSublayer(gradientLayer)
}
}
And this is my UIViewController
import UIKit
class LoginController: UIViewController {
let loginView = LoginView()
override func viewDidLoad() {
super.viewDidLoad()
view = loginView
}
override var preferredStatusBarStyle : UIStatusBarStyle {
return .lightContent
}
}
The problem is that the GradientLayer doesn't show on the screen, the background is still black.
Thanks for the help!
If you like to use in viewDidLoad (Load once), just declare your custom view inside like following code:
override func viewDidLoad() {
super.viewDidLoad()
let loginView = LoginView(frame: self.view.bounds)
self.view = loginView
}
You need to init LoginView correctly at right time.
class LoginController: UIViewController {
var loginView : LoginView!
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
view = LoginView.init(frame: view.bounds)
}
override func viewDidLoad() {
super.viewDidLoad()
}
override var preferredStatusBarStyle : UIStatusBarStyle {
return .lightContent
}
}

UIActivityIndicatorView not showing in webview

I have a UINavigationController that I am adding a UIViewController to. Inside my UIViewController I have a webview and also trying to set a UIActivityIndicatorView. However I can't seem to get the UIActivityIndicatorView to show up. Any help would be great!
class TestWebViewController: UIViewController {
var loadSpinner: UIActivityIndicatorView!
var webView: UIWebView!
var title: String?
init(title: String?) {
self.title = title
self.webView = UIWebView(frame: CGRect.zero)
super.init(nibName: nil, bundle: nil)
commonInit()
}
func commonInit() {
loadSpinner = UIActivityIndicatorView(activityIndicatorStyle: .gray)
loadSpinner.center = webView.center
view.addSubview(loadSpinner)
webView.delegate = self
view = webView
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
UINavigationController(rootViewController: testWebViewController)
Even when I try to add the loadSpinner to the webView it does not appear webView.addSubview(loadSpinner)
Result:
Code:
class ViewController: UIViewController {
var loadSpinner: UIActivityIndicatorView!
var webView: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
self.webView = UIWebView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
loadSpinner = UIActivityIndicatorView(activityIndicatorStyle: .gray)
webView.addSubview(loadSpinner)
view = webView
loadSpinner.startAnimating()
}
override func viewDidLayoutSubviews() {
loadSpinner.center = webView.center
}
}
Your primary issue is that you first add the activity indicator to the view controller's view but two lines later you replace the view controller's view with the web view.
If you are going to replace the view controller's view you should do that in loadView. You should also setup other views in viewDidLoad, not in an init method.
The simplest change is to get rid of your commonInit method and put all of that code in viewDidLoad. Then in viewDidLoad, setup the web view first, then setup the activity indicator.
class TestWebViewController: UIViewController {
var loadSpinner: UIActivityIndicatorView!
var webView: UIWebView!
var title: String?
init(title: String?) {
self.title = title
super.init(nibName: nil, bundle: nil)
}
override func loadView() {
// don't call super
webView = UIWebView(frame: CGRect.zero)
webView.delegate = self
view = webView
}
override func viewDidLoad() {
super.viewDidLoad()
loadSpinner = UIActivityIndicatorView(activityIndicatorStyle: .gray)
loadSpinner.center = view.center
// Keep it in the center
loadSpinner.autoresizingMask = [.flexibleWidth, .flexibleLeftMargin, .flexibleRightMargin]
view.addSubview(loadSpinner)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
You also have an issue with title. UIViewController already has a title property. You should not add your own.
You need to refactor your code like this inside viewDidLoad
class TestWebViewController: UIViewController {
var loadSpinner: UIActivityIndicatorView!
var webView: UIWebView!
var title: String?
override func viewDidLoad()
{
super.viewDidLoad()
webView = UIWebView(frame:self.view.frame)
webView.delegate = self
self.view.addSubview(webview)
loadSpinner = UIActivityIndicatorView(activityIndicatorStyle: .gray)
self.view.addSubview(loadSpinner)
loadSpinner.center = self.view.center
loadSpinner.startAnimating()
}
}

UIsearchBar input Keyboard Type

Does anyone know how to change the input keyboard type for the searchbar? The code
searchController.searchBar.inputView = input
doesn't work like in a text field. I have read that the subview of the searchBar is a textfield but I don't know how to access that subview to change the inputView.
I think you want to display different keyboard than standard,
Make sure you have assign delegate to keyboard.
class ViewController: UIViewController, UISearchBarDelegate, KeyboardDelegate
{
#IBOutlet weak var searchBar: UISearchBar!
override func viewDidLoad() {
let keyboardView = KeyboardView(frame: CGRect(x: 0, y: 0, width: 375, height: 165))
keyboardView.delegate = self
let searchTextField = searchBar.value(forKey: "_searchField") as! UITextField
searchTextField.inputView = keyboardView
}
func keyWasTapped(text: String) {
searchBar.text = text
}
}
My Custom Keyboard Class
protocol KeyboardDelegate: class {
func keyWasTapped(text: String)
}
class KeyboardView: UIView {
// This variable will be set as the view controller so that
// the keyboard can send messages to the view controller.
weak var delegate: KeyboardDelegate?
// MARK:- keyboard initialization
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
initializeSubviews()
}
override init(frame: CGRect) {
super.init(frame: frame)
initializeSubviews()
}
func initializeSubviews() {
let xibFileName = "KeyboardView" // xib extention not included
let view = Bundle.main.loadNibNamed(xibFileName, owner: self, options: nil)?[0] as! UIView
self.addSubview(view)
view.frame = self.bounds
}
// MARK:- Button actions from .xib file
#IBAction func keyTapped(_ sender: UIButton) {
// When a button is tapped, send that information to the
// delegate (ie, the view controller)
self.delegate?.keyWasTapped(text: sender.titleLabel!.text!) // could alternatively send a tag value
}
}
You have to access like this :
if let searchBarTxtField = searchController.searchBar.valueForKey("_searchField") as UITextField {
searchBarTxtField.inputView = input
}

Swift UIGestureRecognizer not working when added in initWithCoder

I have a custom UIView subclass with UI designed in xib.
class MyView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
loadView()
commonInit()
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
loadView()
commonInit()
}
func commonInit() {
let rightSwipeRecognizer = UISwipeGestureRecognizer(target: self, action: Selector("swipe"))
rightSwipeRecognizer.direction = .Right
dayInfoView.addGestureRecognizer(rightSwipeRecognizer)
}
func swipe() {
println("swiped")
}
private func loadView() {
let mainBundle = NSBundle.mainBundle()
let views = mainBundle.loadNibNamed("MyView", owner: self, options: nil)
let view = views.first as? UIView
addSubview(view!)
}
}
In my storyboard, I've added a view to VC and ensured that user interaction is enabled on that view. The result: no swipe handling
In case I add my view manually everything works fine:
override func viewDidLoad() {
super.viewDidLoad()
let myView = MyViewframe: CGRectMake(0, 300, 320, 200))
view.addSubview(myView)
}
What am I doing wrong?

Create a PopUp in Swift using a custom UIView

I am trying to create a custom UIView and display it as a pop up in my main View using Swift.
My Custom UIView code is
class DatePopUpView: UIView {
var uiView:UIView?
override init() {
super.init()
self.uiView = NSBundle.mainBundle().loadNibNamed("DatePopUpView", owner: self, options: nil)[0] as? UIView
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
required override init(frame: CGRect) {
super.init(frame: frame)
}
}
And I am Calling it in my main view as:
#IBAction func date_button_pressed (sender : AnyObject?) {
var popUpView = DatePopUpView()
var centre : CGPoint = CGPoint(x: self.view.center.x, y: self.view.center.y)
popUpView.center = centre
popUpView.layer.cornerRadius = 10.0
let trans = CGAffineTransformScale(popUpView.transform, 0.01, 0.01)
popUpView.transform = trans
self.view .addSubview(popUpView)
UIView .animateWithDuration(0.5, delay: 0.0, options: UIViewAnimationOptions.CurveEaseInOut, animations: {
popUpView.transform = CGAffineTransformScale(popUpView.transform, 100.0, 100.0)
}, completion: {
(value: Bool) in
})
}
But popUp is not Coming. I used breakpoint and noticed that value is getting assigned to my popUpView but still it is not displayed on my main View. Please Help
Please Note: I am using StoryBoard for my mainView and custom View i have made using xib.
Without additional description on what you are attempting to do, may I suggest something like the code below? Basically, you can use .hidden feature of a view (or any other control) to show/hide the view. You can set the size and positioning of the view to be popped by using the layout editor.
import UIKit
class ViewController: UIViewController {
var popped = false
var popupBtnTitle = "Show Popup"
#IBAction func popupButton(sender: UIButton) {
popped = !popped
anotherView.hidden = !popped
popupBtnTitle = popped ? "Hide Popup" : "Show Popup"
popupButtonOutlet.setTitle(popupBtnTitle, forState: UIControlState.Normal)
}
#IBOutlet weak var popupButtonOutlet: UIButton!
#IBOutlet weak var anotherView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
popped = false
anotherView.hidden = !popped
popupButtonOutlet.setTitle(popupBtnTitle, forState: UIControlState.Normal)
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

Resources