I'm having some difficulties calling a function in a view controller that is different than the one it was declared in. I've tried some methods from different posts on the site, but none of them are working for me.
class Housekeeping: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
var balance = 387563 //remove later, arbitrary value for testing
var username = "kaplan"
#objc func addTop() {
let balanceLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 150, height: 30))
balanceLabel.text = "\(balance)"
balanceLabel.textAlignment = .center
balanceLabel.font = UIFont.boldSystemFont(ofSize: 20)
balanceLabel.center = CGPoint(x: self.view.center.x*2-95, y: 50)
balanceLabel.textColor = UIColor(displayP3Red: 160/255, green: 160/255, blue: 160/255, alpha: 1.0)
view.addSubview(balanceLabel)
let genechipImg = UIImageView(image: UIImage(named: "genechip"))
genechipImg.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
genechipImg.center = CGPoint(x: balanceLabel.center.x + 60, y: balanceLabel.center.y)
view.addSubview(genechipImg)
let usernameLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 130, height: 30))
usernameLabel.text = "Dr. \(username)"
usernameLabel.textAlignment = .center
usernameLabel.font = UIFont.boldSystemFont(ofSize: 20)
usernameLabel.center = CGPoint(x: 80, y: 50)
usernameLabel.textColor = UIColor(displayP3Red: 160/255, green: 160/255, blue: 160/255, alpha: 1.0)
view.addSubview(usernameLabel)
}
}
This addTop function was declared in a view controller named Housekeeping and I'm trying to call it on a second view controller named GeneLibrary but I can't figure out how. As you can see, the function doesn't do much just adds two labels at the top, which I'm trying to add on a subsequent view controller. Here's the second view controller I'm trying to pass it to:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
print("gene library scene running")
}
}
If anybody could please provide some insight I'd really appreciate it. Stay safe everybody, thanks!
Declare your function as static:
static func addTop() { print("hello") }
Then call it like so:
Housekeeping.addTop()
Without a context of your app, The solution is:
GeneLibrary().addTop()
This will get to the function and print hello, but I believe this is not your intention, as GeneLibrary() creates a new instance from GeneLibrary view controller, while there might already be another instance that you want to call in order to do what you want.
if you can provide more details I'll be glad to help.
UPDATE
as the second view controller is being presented:
let housekeepingVC = presentingViewController as? Housekeeping
housekeepingVC.addTop()
this will do the job
Related
I’m making my first project that is a truth or dare game but when I tap the button to print a Truth/dare the labels are getting stacked on each other. How do I make it that the previous label disappear and the new one is there alone. Thanks in advance
import UIKit
import PlaygroundSupport
public class ViewController: UIViewController {
public override func loadView() {
//adding baground
super.loadView()
let view = UIView()
view.backgroundColor = .red
self.view = view
//dare button
let dareButton = UIButton(frame: CGRect(x:300, y: 500, width: 100, height: 69))
dareButton.layer.cornerRadius = 10
dareButton.backgroundColor = #colorLiteral(red: 0.6352941393852234, green: 0.6470588445663452, blue: 0.886274516582489, alpha: 1.0)
dareButton.setTitle("dare", for: UIControl.State.normal)
dareButton.isUserInteractionEnabled = true
dareButton.addTarget(self, action: #selector(dareButtonDidTap), for: .touchDown)
view.addSubview(dareButton)
self.view = view
view.addSubview(dareButton)
}
#objc
private func dareButtonDidTap() {
let lbl = UILabel(frame: CGRect(x:95 , y:100, width: 325, height: 500))
lbl.text = daresEng.randomElement()
lbl.textColor = #colorLiteral(red: 0.6313725709915161, green: 0.6470588445663452, blue: 0.9058823585510254, alpha: 1.0)
lbl.numberOfLines = 6
view.addSubview(lbl)
}
}
PlaygroundPage.current.needsIndefiniteExecution = true
PlaygroundPage.current.liveView = ViewController()
The labels are stacked because you create a new label and add it to the view each time you click the dareButton, and the previous labels are not removed from the superView. So you can move the label to the class level and add it to the view in loadView(). This way you only have one label, and in the dareButtonDidTap(), you only have to change the text of this label.
import UIKit
import PlaygroundSupport
public class ViewController: UIViewController {
let lbl = UILabel(frame: CGRect(x:95 , y:100, width: 325, height: 500))
public override func loadView() {
//adding baground
super.loadView()
let view = UIView()
view.backgroundColor = .red
self.view = view
//dare button
let dareButton = UIButton(frame: CGRect(x:300, y: 500, width: 100, height: 69))
dareButton.layer.cornerRadius = 10
dareButton.backgroundColor = #colorLiteral(red: 0.6352941393852234, green: 0.6470588445663452, blue: 0.886274516582489, alpha: 1.0)
dareButton.setTitle("dare", for: UIControl.State.normal)
dareButton.isUserInteractionEnabled = true
dareButton.addTarget(self, action: #selector(dareButtonDidTap), for: .touchDown)
view.addSubview(dareButton)
self.view = view
view.addSubview(lbl)
view.addSubview(dareButton)
}
#objc
private func dareButtonDidTap() {
lbl.text = daresEng.randomElement()
lbl.textColor = #colorLiteral(red: 0.6313725709915161, green: 0.6470588445663452, blue: 0.9058823585510254, alpha: 1.0)
lbl.numberOfLines = 6
}
}
PlaygroundPage.current.needsIndefiniteExecution = true
PlaygroundPage.current.liveView = ViewController()
Trying to make .saver in swift for MacOS, But don't know how to add custom text or Label on ScreenSaverView class which is the subclass from NSView.
Below is my piece of code, but doesn't work.
private var text: CATextLayer!
override func draw(_ rect: NSRect) {
// Draw a single frame in this function
self.layer?.backgroundColor = .init(red: 142/255, green: 167/255, blue: 125/255, alpha: 1)
text.removeFromSuperlayer()
text.string = "Test"
text.frame = CGRect(x: 100, y: 100, width: 200, height: 100)
text.foregroundColor = .white
text.backgroundColor = .clear
self.layer?.addSublayer(text)
}
This is my first post on StackOverflow! Seems to be an amazing community.
I have created a custom UITextfield with a bottom line (bottomLine) programmatically and also a shadowed line (shadowLine) that I wish should be removed when the user moves away from the textfield. How do I do that?
lazy var textField: UITextField = {
let textField = UITextField()
textField.anchor(width: 150, height: 22)
textField.backgroundColor = UIColor(white: 100, alpha: 1)
var bottomLine = CALayer()
bottomLine.frame = CGRect(x: 0, y: 22, width: 150, height: 1)
bottomLine.backgroundColor = UIColor.black.cgColor
textField.borderStyle = UITextField.BorderStyle.none
textField.layer.addSublayer(bottomLine)
let shadowLine = UIView()
shadowLine.frame = CGRect(x: 0, y: 22, width: 150, height: 3)
shadowLine.backgroundColor = UIColor.black
shadowLine.layer.shadowColor = UIColor.darkGray.cgColor
shadowLine.layer.shadowOffset = CGSize(width: 3, height: 3)
shadowLine.layer.shadowRadius = 3
shadowLine.layer.shadowOpacity = 1
shadowLine.tag = 1
textField.addSubview(shadowLine)
return textField
}()
Then I implemented the UITextFieldDelegate protocol and one of its optional functions in order to remove shadowLine subview but it doesn't get removed as I want to:
func textFieldDidEndEditing(_ textField: UITextField) {
if textField == textField {
textField.viewWithTag(1)?.removeFromSuperview()
}
}
Can you help a rookie out? :)
It looks like you forgot to set the delegate:
textField.delagate = self
I try to access the function "addNavBar()" from, my helper class, but when I run the emulator, no view is shown on HomeViewController.
Swift 4
HomeViewController.swift
class HomeController: UIViewController {
let NavBar = NavigationBarHelper()
override func viewDidLoad() {
super.viewDidLoad()
NavBar.addNavBar()
}
}
NavigationBarHelper.swift
class NavigationBarHelper: UIView {
func addNavBar() {
let rect = CGRect(x: 10, y: 70, width: 250, height: 100)
let navBarView = UIView(frame: rect)
navBarView.backgroundColor = UIColor.blue
self.addSubview(navBarView)
}
}
self in NavigationBarHelper is not the same object as the view in the view controller. Pass the VC's view as a parameter. There is no need to make NavigationBarHelper a subclass of UIView (in fact it could also be a struct).
class NavigationBarHelper {
func addNavBar(to view: UIView) {
let rect = CGRect(x: 10, y: 70, width: 250, height: 100)
let navBarView = UIView(frame: rect)
navBarView.backgroundColor = UIColor.blue
view.addSubview(navBarView)
}
}
please also stick to naming conventions
class HomeController: UIViewController {
let navBarHelper = NavigationBarHelper()
override func viewDidLoad() {
super.viewDidLoad()
navBarHelper.addNavBar(to: self.view)
}
Instead of creating an object every usage
let NavBar = NavigationBarHelper()
I think it's more robust to make it static like this
class NavigationBarHelper: UIView {
static func addNavBar(view:UIView) {
let rect = CGRect(x: 10, y: 70, width: 250, height: 100)
let navBarView = UIView(frame: rect)
navBarView.backgroundColor = UIColor.blue
view.addSubview(navBarView)
}
}
and call it directly without object creation
NavigationBarHelper.addNavBar(view: self.view)
A Better Alternative for this would be an extension so you don't have to create the special class for this
extension UIView {
func addNavBar() {
let rect = CGRect(x: 10, y: 70, width: 250, height: 100)
let navBarView = UIView(frame: rect)
navBarView.backgroundColor = UIColor.blue
self.addSubview(navBarView)
}
}
And in you UIViewController you can simply write this without creating an object of your helper.
self.view.addNavBar()
I have the following code running on Xcode Playground. However, even though I specify that the label is centered at the center of the view, it doesn't appear there.
import UIKit
import PlaygroundSupport
class TestViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.white
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 20))
label.center = CGPoint(x: view.frame.width / 2, y: view.frame.height / 2)
label.text = "Hello World!"
label.textColor = UIColor.black
view.addSubview(label)
}
}
PlaygroundPage.current.liveView = TestViewController()
The view controller's view's frame is not final in viewDidLoad.
You either need to set the label's autoresizingMask or apply constraints to keep it in the center.
And since you made the label wider than the text, you also need to set the label's textAlignment to center.
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 20))
label.center = view.center
label.text = "Hello World!"
label.textColor = .black
label.textAlignment = .center // or call label.sizeToFit()
label.autoresizingMask = [ .flexibleTopMargin, .flexibleBottomMargin, .flexibleLeftMargin, .flexibleRightMargin, ]
view.addSubview(label)
view frame is not finalized when viewDidLoad is triggered, you need to set the frame of the label inside the method viewDidLayoutSubviews as this method is being invoked when view bound was finalized.
Try
class TestViewController: UIViewController {
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 20))
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.white
label.text = "Hello World!"
label.textColor = UIColor.black
self.view.addSubview(label)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
self.label.center = self.view.center
}
}