How to create Onboarding\Walkthrough swift - ios

I'm trying to create a welcome onboarding for the first time users but none of the views are loafing in the simulator, all I'm getting is a red background when the onboardingVC gets presented. Can anyone see the issue as to why the titles, buttons, and images won't appear?
This is the message I'm getting in the console:
Warning: Attempt to present <EMA.WalkthroughVC: 0x7faa2401e5b0> on <EMA.HomeVC: 0x7faa22407e00> whose view is not in the window hierarchy!
FOUND ALL!!
let holderView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = true
view.backgroundColor = .darkGray
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.white
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
view.backgroundColor = UIColor.red
configure()
}
private func configure() {
let scrollView = UIScrollView(frame: holderView.bounds)
holderView.addSubview(scrollView)
let titles = ["Hi","Welcome","real nigga"]
for x in 0..<3 {
let pageView = UIView(frame: CGRect(x: CGFloat(x) * holderView.frame.size.width, y: 0, width: holderView.frame.size.width, height: holderView.frame.size.height))
scrollView.addSubview(pageView)
let label = UILabel(frame: CGRect(x: 10, y: 10, width: pageView.frame.size.width-20, height: 120))
let imageView = UIImageView(frame: CGRect(x: 10, y: 10+120+10, width: pageView.frame.size.width-20, height: pageView.frame.size.height - 60 - 130 - 15))
let button = UIButton(frame: CGRect(x: 10, y: pageView.frame.size.height - 60, width: pageView.frame.size.width-20, height: 50))
label.textAlignment = .center
label.font = UIFont.systemFont(ofSize: 16, weight: .semibold)
pageView.addSubview(label)
label.text = titles[x]
imageView.contentMode = .scaleAspectFill
imageView.image = UIImage(named: "BankCard\(x)")
pageView.addSubview(imageView)
button.setTitleColor(.red, for: .normal)
button.backgroundColor = .black
button.setTitle("Continue", for: .normal)
if x == 2 {
button.setTitle("Get Started", for: .normal)
}
button.addTarget(self, action: #selector(didTapButton), for: .touchUpInside)
pageView.addSubview(button)
}
}
#objc func didTapButton(_ button: UIButton) {
}
}

"whose view is not in the window hierarchy"
you didn't add the views that you created to the main view try to add the subviews to the main by using this one
self.view.addSubview(holderView)
also don't forget to add the frame for the holder view like that
UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height))
view.translatesAutoresizingMaskIntoConstraints = true
and inside the view did load
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.white
self.view.addSubview(holderView)
}

Related

Navigation item in my UIViewController is overlapping child views and labels

I am adding custom navigation item to my application. But every time I navigate the items of navigation item overlaps. My code is
func fixNavBar(){
self.navigationItem.setHidesBackButton(true, animated: true)
let nav = self.navigationController?.navigationBar
let navView = UIView(frame: CGRect(x: 0, y: 0, width: (nav?.frame.width)!, height: (nav?.frame.height)!))
let backButton = UIButton(frame: CGRect(x: 0, y: 0, width: navView.frame.height, height: navView.frame.height))
backButton.imageView?.contentMode = .scaleToFill
backButton.setImage(UIImage(systemName: "chevron.left"), for: .normal)
backButton.setTitleColor(UIColor(rgb: 0x23C0FF), for: .normal)
backButton.tintColor = UIColor(rgb: 0x23C0FF)
nav?.addSubview(navView)
backButton.addTarget(self, action: #selector(goBack), for: .touchUpInside)
navView.backgroundColor = .clear
let imageView = UIImageView(frame: CGRect(x: backButton.frame.width+5, y: 0, width: navView.frame.height-2, height: navView.frame.height-2))
let profUrl = URL(string: "\(selectedUser.profilePictuer)")
imageView.kf.setImage(with: profUrl)
let userLbl = UILabel(frame: CGRect(x: backButton.frame.width + 15 + imageView.frame.width, y: 0, width: 150, height: navView.frame.height))
userLbl.font = UIFont(name: UIFont.fontNames(forFamilyName: "Ubuntu")[0], size: 17)
userLbl.text = selectedUser.fullName
userLbl.textAlignment = .left
userLbl.textColor = .black
navView.addSubview(imageView)
navView.addSubview(userLbl)
navView.addSubview(backButton)
imageView.layer.cornerRadius = imageView.frame.height/2
imageView.layer.masksToBounds = true
}
#objc func goBack(sender: UIButton!) {
self.navigationController!.popViewController(animated: true)
}
override func viewDidLoad() {
super.viewDidLoad()
fixNavBar()
}
This is root view controller when where I select any chat to open
When I select chat for first time I get something like that
And when select second chat it does not remove previous user's name but overlaps it
Your root and child view controller has the same navigationcontroller so when everytime you call fixNavBar , some views appending on the previous .
First option is adding nav?.subviews.forEach({$0.removeFromSuperview()}) on the top of your function like #Raja's comment.
Second is go storyboard and embed a new navigationController to your child viewcontroller(where yout function is)

In Swift code my Label is not showing up in my ViewController

When the ViewController is displayed on the phone the Label is not displayed
I am new to iOS and swift, I have search YouTube extensively to no avail. In the code you can see I have made two attempts to add two labels. Not that none are showing. The navigation elements are working correctly. The background is being set correctly also.
import UIKit
class WelcomeController: UIViewController {
// MARK: - Properties
var pageTitle: UILabel!
// MARK: - Init
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
let frameLabel:CGRect = CGRect(x: 20, y: 0, width: UIScreen.main.bounds.width - 20, height: 50)
let label:UILabel = UILabel(frame: frameLabel)
label.text = "This text is not showing up on the screen!!! his text is not showing up on the screen!!! his text is not showing up on the screen!!!"
label.textColor = .black
label.textAlignment = .center
view.addSubview(label)
configureUI()
configurePageTitleLabel()
}
// MARK: - Selectors
#objc func handleDismiss() {
dismiss(animated: true, completion: nil)
}
// MARK: - Helper Functions
func configureUI() {
navigationController?.navigationBar.barTintColor = .blue
navigationItem.title = "Welcome"
let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
navigationController?.navigationBar.titleTextAttributes = textAttributes
navigationItem.leftBarButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "ic_menu_white_3x").withRenderingMode(.alwaysOriginal), style: .plain, target: self, action: #selector(handleDismiss))
}
// MARK - Page Contents Functions
func configurePageTitleLabel() {
pageTitle = UILabel()
pageTitle.text = "Welcome"
pageTitle.textAlignment = .center
pageTitle.textColor = .black
let frameTitle:CGRect = CGRect(x: 20, y: 20, width: UIScreen.main.bounds.width - 20, height: 50)
pageTitle.drawText(in: frameTitle)
view.addSubview(pageTitle)
view.backgroundColor = .gray
}
}
The y value should be more than 64 ie. 20 status bar + 44 Navigation bar.
Also, you don't need drawText and frame tile.
Simply adding
pageTitle.frame = CGRect(x: 20, y: 200, width: UIScreen.main.bounds.width - 20, height: 50)
would work.

Why is my button not working in Swift Playgrounds?

I am trying to make a playground and I have a button that says "Let's play!" and moves into a new view controller.
I looked at the code from this website and put it into my code:
http://lab.dejaworks.com/ios-swift-3-playground-uibutton-action/
This is all of my code (like, all of it):
import UIKit
import PlaygroundSupport
class MyViewController : UIViewController {
override func loadView() {
//Introduction
let view = UIView()
view.backgroundColor = .red
//title
func labelCool() {
let label = UILabel()
label.frame = CGRect(x: 50, y: 300, width: 400, height: 100)
label.text = "Add-Add - A Wonderful Game!"
//label.frame = CGRect(x: 150, y: 200, width: 200, height: 20)
label.numberOfLines = 3
label.font = UIFont(name: "HelveticaNeue-Bold", size: 30)
UILabel.animate (withDuration: 10.0, animations:{
label.textColor = .black
})
UILabel.animate(withDuration: 5.0, animations:{
label.textColor = .blue
})
view.addSubview(label)
}
labelCool()
//subtitle
let subtitle = UILabel()
subtitle.frame = CGRect(x: 50, y: 400, width: 200, height: 50)
subtitle.text = "Curated and Created by Yours Truly, Adit Dayal!"
subtitle.numberOfLines = 4
self.view = view
view.addSubview(subtitle)
}
override func viewDidLoad() {
class Responder : NSObject {
#objc func action() {
print("Yay!")
}
}
let responder = Responder()
//next page
let button = UIButton(frame : CGRect(x: 0, y: 500, width: 200, height: 50))
button.setTitle("Let's Play!", for: .normal)
button.backgroundColor = .blue
button.addTarget(responder, action: #selector(Responder.action), for: .touchUpInside)
view.addSubview(button)
}
}
class gameViewController: UIViewController {
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()
For now, I just want the button to display "Yay!" when clicked, but it is doing nothing!
Does anyone know why? (I'm on a bit of a time constraint)
Thank you so much,
Adit Dayal
Your Responder class is inside the viewDidLoad() function put the class outside like so
class Responder : NSObject {
#objc func action() {
print("Yay!")
}
}
override func viewDidLoad() {
let responder = Responder()
//next page
let button = UIButton(frame : CGRect(x: 0, y: 500, width: 200, height: 50))
button.setTitle("Let's Play!", for: .normal)
button.backgroundColor = .blue
button.addTarget(responder, action: #selector(responder.action), for: .touchUpInside)
view.addSubview(button)
}
The problem is that you are creating the responder object inside the viewDidLoad, as a local variable; this cause the object to be destroyed when the function ends (but we want that object alive even after). You have to retain that object, so instead of creating a local variable, create an instance variable by simply saving it as a class scope:
class Responder : NSObject {
#objc func action() {
print("Yay!")
}
}
let responder = Responder() // this is now outside the viewDidLoad, so it's an instance variable
override func viewDidLoad() {
//next page
let button = UIButton(frame : CGRect(x: 0, y: 500, width: 200, height: 50))
button.setTitle("Let's Play!", for: .normal)
button.backgroundColor = .blue
button.addTarget(responder, action: #selector(Responder.action), for: .touchUpInside)
view.addSubview(button)
}

How to set the custom inputview of the textview as same height as that of the default keyboard in iOS?

I want the height of custom inputView of the textView to be same height as that of default keyboard. I tried a lot, including:
self.textView.inputView?.autoresizingMask = .flexibleHeight
I couldn't find a solution. It's always coming less than that of default keyboard. (EDIT: This issue exists only for iPhone X)
My code:
class ViewController: UIViewController {
let textView = UITextView()
let button = UIButton()
var keyboardView = UIView()
override func viewDidLoad() {
super.viewDidLoad()
button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
textView.backgroundColor = .lightGray
button.backgroundColor = .red
self.view.addSubview(textView)
self.view.addSubview(button)
}
#objc func buttonAction() {
if self.textView.inputView == nil {
self.textView.inputView = keyboardView
self.textView.inputView?.autoresizingMask = .flexibleHeight
self.textView.reloadInputViews()
} else {
self.textView.inputView = nil
self.textView.reloadInputViews()
}
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
textView.frame = CGRect(x: 0, y: 50, width: self.view.frame.size.width - 50, height: 50)
button.frame = CGRect(x: self.view.frame.size.width - 50, y: 50, width: 50, height: 50)
}
}

Swift 3: How do I increase a variable being displayed as a UILabel, and then update the UILabel programmatically?

I have a label that is supposed to display a score, and a button that is supposed to increase that score each time it's pressed. My problem is that I get an error no matter where I put my function.
If I have the function above the viewDidLoad class then I get an error because it comes before my label, but if I put it anywhere inside viewDidLoad I get an error because I can't call a local function, and if I put it anywhere after, then my button calling the function comes before the function.
Where am I supposed to put these things? Is there a better way of doing this all together? This was supposed to be so simple...
import UIKit
class ViewController: UIViewController {
let phrase = "Your score: "
var increasingNum = 0
func scoreGoUp (sender: UIButton){
increasingNum += 1
label.text = "\(phrase) \(increasingNum)"
}
override func viewDidLoad() {
super.viewDidLoad()
let label = UILabel(frame: CGRect(x: self.view.frame.size.width / 2 - 100, y: self.view.frame.size.height / 2 - 10, width: 200, height: 20))
label.textAlignment = .center
label.text = "\(phrase) \(increasingNum)"
self.view.addSubview(label)
let button = UIButton(frame: CGRect(x: self.view.frame.size.width / 2 - 150, y: 100, width: 300, height: 50))
button.backgroundColor = UIColor.cyan
button.addTarget(self, action: #selector(scoreGoUp), for: .touchUpInside)
self.view.addSubview(button)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
I have modified your code. Hope this help you.
class ViewController: UIViewController {
var label:UILabel!
let phrase = "Your score: "
var increasingNum = 0
override func viewDidLoad() {
super.viewDidLoad()
label = UILabel(frame: CGRect(x: self.view.frame.size.width / 2 - 100, y: self.view.frame.size.height / 2 - 10, width: 200, height: 20))
label.textAlignment = .center
label.text = "\(phrase) \(increasingNum)"
self.view.addSubview(label)
let button = UIButton(frame: CGRect(x: self.view.frame.size.width / 2 - 150, y: 100, width: 300, height: 50))
button.backgroundColor = UIColor.cyan
button.addTarget(self, action: #selector(scoreGoUp), for: .touchUpInside)
self.view.addSubview(button)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func scoreGoUp (sender: UIButton){
increasingNum += 1
label.text = "\(phrase) \(increasingNum)"
}
}
Here is the output
You need to define your label outside of viewDidLoad (like increasingNum), at the moment, your label variable is only visible inside viewDidLoad
var label:UILabel!
I have cleared up your code. The problem was that, you are not keeping track of you UILabel. Just declare a label to be visible in the class.
import UIKit
class ViewController: UIViewController {
let phrase = "Your score: "
var increasingNum = 0
var label: UILabel?
override func viewDidLoad() {
super.viewDidLoad()
let label = UILabel(frame: CGRect(x: self.view.frame.size.width / 2 - 100, y: self.view.frame.size.height / 2 - 10, width: 200, height: 20))
label.textAlignment = .center
label.text = "\(phrase) \(increasingNum)"
self.view.addSubview(label)
self.label = label
let button = UIButton(frame: CGRect(x: self.view.frame.size.width / 2 - 150, y: 100, width: 300, height: 50))
button.backgroundColor = UIColor.cyan
button.addTarget(self, action: #selector(scoreGoUp), for: .touchUpInside)
self.view.addSubview(button)
}
func scoreGoUp (sender: UIButton){
increasingNum += 1
self.label?.text = "\(phrase) \(increasingNum)"
}
}
Hope this helps!

Resources