Dynamically changing background color in VC - swift

I am stuck with this piece of my homework. Maybe someone can explain me how to solve it.
"VC contains a controller with a built-in controller. Both the parent and child controller have three buttons: Green, Yellow, Violet. When you click on one of the buttons in the parent controller, the background color of the child controller changes to the appropriate one. When you click on the button in the child, the background of the parent changes."
Here is what I made in my code
Parent VC
import UIKit
class OrangeViewController: UIViewController, VioletControllerDelegate {
var delegate: VioletControllerDelegate?
override func viewDidLoad() {
super.viewDidLoad()
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let vcV = segue.destination as! VioletViewController
vcV.bgColor = view.backgroundColor
vcV.delegate = self
}
#IBAction func greenOButton(_ sender: Any) {
//TO DO
}
#IBAction func yellowOButton(_ sender: Any) {
//TO DO
}
#IBAction func purpleOButton(_ sender: Any) {
//TO DO
}
func setColor(color: String) {
view.backgroundColor = UIColor(named: color)
}
}
Child VC
import UIKit
protocol VioletControllerDelegate{
func setColor ( color : String)
}
class VioletViewController: UIViewController {
var bgColor : UIColor?
var delegate: VioletControllerDelegate?
override func viewDidLoad() {
super.viewDidLoad()
var bgColor = view.backgroundColor
}
#IBAction func setGreen(_ sender: Any) {
delegate?.setColor( color: "green")
}
#IBAction func setYellow(_ sender: Any) {
delegate?.setColor( color: "yellow")
}
#IBAction func setViolet(_ sender: Any) {
delegate?.setColor( color: "violet")
}
func setColor ( color : String){
view.backgroundColor = UIColor(named: color)
}
}
Thank you!

I did it. In case someone will need something like this I am posting my answer:
Parent VC
import UIKit
class OrangeViewController: UIViewController, VioletControllerDelegate {
var childVC: VioletViewController?
override func viewDidLoad() {
super.viewDidLoad()
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let vcV = segue.destination as! VioletViewController
self.childVC = vcV
vcV.delegate = self
}
#IBAction func greenOButton(_ sender: Any) {
childVC?.view.backgroundColor = UIColor.green
}
#IBAction func yellowOButton(_ sender: Any) {
childVC?.view.backgroundColor = UIColor.yellow
}
#IBAction func purpleOButton(_ sender: Any) {
childVC?.view.backgroundColor = UIColor.purple
}
func setColor( color : UIColor) {
view.backgroundColor = color
}
}
Child VC
import UIKit
protocol VioletControllerDelegate{
func setColor ( color : UIColor)
}
class VioletViewController: UIViewController {
var delegate: VioletControllerDelegate?
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func setGreen(_ sender: Any) {
delegate?.setColor( color: UIColor.green)
}
#IBAction func setYellow(_ sender: Any) {
delegate?.setColor( color: UIColor.yellow)
}
#IBAction func setViolet(_ sender: Any) {
delegate?.setColor( color: UIColor.purple)
}
}

Related

ViewController doesn't pass data on completion

I have 2 ViewControllers.
TimerViewController passes a variable to the EditTimerViewConroller. EditTimerViewConroller edits it and should pass it back, but it looks like code in .completion is not executed.
Any advice how to fix it?
My code is:
TimerViewController
import UIKit
import AVFoundation //play sounds
class TimerViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
var player: AVAudioPlayer!
var timer = Timer()
var totalTime = 10.0
var secondsRemaining = 10.0
var secondsPassed = 0.0
let timerStep = 0.1
#IBOutlet weak var timerLabel: UILabel!
#IBOutlet weak var progressBar: UIProgressView!
#IBAction func startPressed(_ sender: UIButton) {
//works fine
}
#IBAction func editTimerButtinPresed(_ sender: UIButton) {
self.performSegue(withIdentifier: "goToEditTimer", sender: self)
let editTimer = EditTimerViewController()
editTimer.completion = { [weak self] duration in
DispatchQueue.main.async {
self?.totalTime = Double(duration!)
print("editTimer completed, totalTime now is \(self?.totalTime)")
}
}
}
func playSound(fileName: String) {
//works fine
}
#objc func updateTimer() {
//works fine
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToEditTimer" {
let destinationVC = segue.destination as! EditTimerViewController
destinationVC.duration = Int(totalTime)
print("Pasing duration = \(totalTime) to Edit screen")
}
}
EditTimerViewController
import UIKit
class EditTimerViewController: UIViewController {
let maxDuration = 60
var duration: Int? //timer duraton is passed from Timer
public var completion: ((Int?) -> Void)?
override func viewDidLoad() {
super.viewDidLoad()
durationSlider.minimumValue = 0
durationSlider.maximumValue = Float(maxDuration)
durationSlider.value = Float(duration!)
durationLabel.text = String(duration!) + "s"
}
#IBOutlet weak var durationLabel: UILabel!
#IBOutlet weak var durationSlider: UISlider!
#IBAction func durationSliderChanged(_ sender: UISlider) {
duration = Int(sender.value)
print(duration!)
durationLabel.text = String(duration!) + "s"
}
#IBAction func cancelPressed(_ sender: UIButton) {
print("Cancel pressed, dismissing Edit screen")
self.dismiss(animated: true, completion: nil)
}
#IBAction func savePressed(_ sender: UIButton) {
print("Save pressed, duration is \(duration!)")
completion?(duration!)
self.dismiss(animated: true, completion: nil)
}
}
In the output after pressing Save button I see
Save pressed, duration is 11
but after it there is no sign of
editTimer completed, totalTime now is 11
and timer duration never changes
Change
#IBAction func editTimerButtinPresed(_ sender: UIButton) {
self.performSegue(withIdentifier: "goToEditTimer", sender: self)
let editTimer = EditTimerViewController()
editTimer.completion = { [weak self] duration in
DispatchQueue.main.async {
self?.totalTime = Double(duration!)
print("editTimer completed, totalTime now is \(self?.totalTime)")
}
}
}
To
#IBAction func editTimerButtinPresed(_ sender: UIButton) {
self.performSegue(withIdentifier: "goToEditTimer", sender: self)
}
And move completion inside prepare
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToEditTimer" {
let destinationVC = segue.destination as! EditTimerViewController
destinationVC.duration = Int(totalTime)
print("Pasing duration = \(totalTime) to Edit screen")
destinationVC.completion = { [weak self] duration in
DispatchQueue.main.async {
self?.totalTime = Double(duration!)
print("editTimer completed, totalTime now is \ (self?.totalTime)")
}
}
}
}

Change the tabs in a Embedded TabBarController

I have a view controller which has two buttons and an embedded TabBarController.
I want to use the two button instead of the tab bar item. And for some reason cannot make it work.
MainView
import UIKit
class ViewController: UIViewController {
var currentTab = 0
#IBOutlet weak var container: UIView!
#IBAction func item1Button(_ sender: UIButton) {
currentTab = 0
}
#IBAction func item2Button(_ sender: UIButton) {
currentTab = 1
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "toControllers"{
if let vc = segue.destination as? TabsViewController {
vc.selectedIndex = currentTab
}
}
}
}
TabBarController
import UIKit
class TabsViewController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
}
}
I have two items in the storyboard, so item 0 and 1 should be ok.
Maybe it is very simple, cannot figure it out myself.
Thank you!
I figure it out, here is the solution:
Changed the main controller to:
class ViewController: UIViewController {
var currentTab = 1
private var tabViewController: UITabBarController?
#IBOutlet weak var container: UIView!
#IBAction func item1Button(_ sender: UIButton) {
print("click item1")
tabViewController?.selectedIndex = 0
}
#IBAction func item2Button(_ sender: UIButton) {
print("click item2")
tabViewController?.selectedIndex = 1
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "toControllers"{
if let vc = segue.destination as? TabsViewController {
tabViewController = vc
}
}
}

Changing UIButton From different ViewController

i need to change UIButton(status, title) from another UIViewController
i tried the below
import UIKit
class ViewController: UIViewController{
#IBOutlet var B1: UIButton!
#IBOutlet var B2: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
}
import Foundation
import UIKit
class View2: UIViewController {
#IBAction func Dismiss(_ sender: Any) {
h()
dismiss(animated: true, completion: nil)
}
func h(){
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "VC") as? ViewController
vc?.loadViewIfNeeded()
print("c: ",vc?.B1.currentTitle ?? "")
vc?.B1.setTitle("a", for: .normal)
print("c: ",vc?.B1.currentTitle ?? "")
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
The Output is :
c: V1B1
c: a
it's changed (as the output said) ! but when the view dismissed it goes back to "V1B1" which is the title i put in Main.storyboard
i also tried to change it with protocol and delegate
import UIKit
class ViewController: UIViewController,TestDelegate {
func t(NewT: UIButton) {
NewT.setTitle("a", for: .normal)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let dd = segue.destination as? View2 {
dd.d = self
print("B1O: ",B1.currentTitle!)
}
}
#IBOutlet var B1: UIButton!
#IBOutlet var B2: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
}
import Foundation
import UIKit
protocol TestDelegate {
func t(NewT: UIButton)
}
class View2: UIViewController {
var d: TestDelegate?
#IBAction func Dismiss(_ sender: Any) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "VC") as? ViewController
vc?.loadViewIfNeeded()
print("B1: ",vc?.B1.currentTitle!)
d?.t(NewT: (vc?.B1!)!)
print("B1: ",vc?.B1.currentTitle!)
dismiss(animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
Output:
B1O: V1B1
B1: Optional("V1B1")
B1: Optional("a")
what's wrong with the code ?
How can i change the UIButtons permanently even if the UIViewController loaded again
import UIKit
class ViewController: UIViewController{
#IBOutlet var B1: UIButton!
#IBOutlet var B2: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
open override func viewWillAppear(_ animated: Bool) {
// Register to receive notification
NotificationCenter.default.addObserver(self, selector: #selector(self.updateTitle), name: NSNotification.Name(rawValue: "buttonTitleUpdate"), object: nil)
super.viewWillAppear(animated)
}
#objc func updateTitle() -> Void {
print("c: ",B1.currentTitle ?? "")
B1.setTitle("a", for: .normal)
print("c: ",B1.currentTitle ?? "")
}
}
import Foundation
import UIKit
class View2: UIViewController {
#IBAction func Dismiss(_ sender: Any) {
// Post a notification
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "buttonTitleUpdate"), object: nil)
dismiss(animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
"it's changed (as the output said) ! but when the view dismissed it goes back to "V1B1" which is the title i put in Main.storyboard"
You've changed the title of B1 in a new instance of V1, not in the existing instance of V1.
Don't create a new instance for ViewController class in the dismiss method
class ViewController: UIViewController,TestDelegate {
func change(text: String) {
B1.setTitle(text, for: .normal)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let dd = segue.destination as? View2 {
dd.d = self
print("B1O: ",B1.currentTitle!)
}
}
#IBOutlet var B1: UIButton!
#IBOutlet var B2: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
}
protocol TestDelegate {
func change(text: String)
}
class View2: UIViewController {
var d: TestDelegate?
#IBAction func Dismiss(_ sender: Any) {
d?.change(text:"NewTitle")
dismiss(animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
many thanks to "RajeshKumar R" and "Bhavesh Nayi"
import UIKit
class ViewController: UIViewController,TestDelegate {
func t(NewT: Int) {
let TempButton = self.view.viewWithTag(NewT) as! UIButton
TempButton.setTitle("X", for: .normal)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let dd = segue.destination as? View2 {
dd.d = self
}
}
#IBOutlet var B1: UIButton!
#IBOutlet var B2: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
}
import Foundation
import UIKit
protocol TestDelegate {
func t(NewT: Int)
}
class View2: UIViewController {
var d: TestDelegate?
#IBAction func Dismiss(_ sender: Any) {
//just pass the tag
d?.t(NewT: 1)
dismiss(animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
}
}

Swift App runs but no buttons appear

I wrote a Swift app but only the window appears when it runs. I can't see any buttons.
Here is my code... I've tried removing the .white attribute thinking maybe it was hidden behind a layer. Nothing.
//
// ViewController.swift
// BraviaRemote
//
// Created by Ed Gilroy on 7/2/17.
// Copyright © 2017 Edward Williams. All rights reserved.
//
import Cocoa
import Alamofire
class ViewController: NSViewController, NSTextFieldDelegate {
#IBAction func MenuButton(_ sender: NSButtonCell) {
triggerRemoteControl(irccc: "AAAAAQAAAAEAAABgAw==")
}
#IBAction func ReturnButton(_ sender: NSButton) {
triggerRemoteControl(irccc: "AAAAAgAAAJcAAAAjAw==")
}
#IBAction func InfoButton(_ sender: NSButton) {
triggerRemoteControl(irccc: "AAAAAQAAAAEAAAA6Aw==")
}
#IBAction func GuideButton(_ sender: NSButton) {
triggerRemoteControl(irccc: "AAAAAgAAAKQAAABbAw==")
}
#IBAction func SelectButton(_ sender: NSButton) {
triggerRemoteControl(irccc: "AAAAAQAAAAEAAABlAw==")
}
#IBAction func ChnUpButton(_ sender: NSButton) {
triggerRemoteControl(irccc: "AAAAAQAAAAEAAAAQAw==")
}
#IBAction func ChnDownButton(_ sender: NSButton) {
triggerRemoteControl(irccc: "AAAAAQAAAAEAAAARAw==")
}
#IBAction func VolUpButton(_ sender: NSButton) {
triggerRemoteControl(irccc: "AAAAAQAAAAEAAAASAw==")
}
#IBAction func VolDownButton(_ sender: NSButton) {
triggerRemoteControl(irccc: "AAAAAQAAAAEAAAATAw==")
}
#IBAction func LeftButton(_ sender: NSButton) {
triggerRemoteControl(irccc: "AAAAAQAAAAEAAAA0Aw==")
}
#IBAction func RightButton(_ sender: NSButton) {
triggerRemoteControl(irccc: "AAAAAQAAAAEAAAAzAw==")
}
#IBAction func UpButton(_ sender: NSButton) {
triggerRemoteControl(irccc: "AAAAAQAAAAEAAAB0Aw==")
}
#IBAction func DownButton(_ sender: NSButton) {
triggerRemoteControl(irccc: "AAAAAQAAAAEAAAB1Aw==")
}
#IBAction func OnOffButton(_ sender: NSSegmentedControl){
}
#IBOutlet weak var IPField: NSTextField!
var IPAddress: String? {
didSet {
if IPField != nil { IPAddress = "http://\(IPAddress!)/sony/IRCC?" }
else {IPAddress = "http://192.168.2.7/sony/IRCC?"}
if let ip = IPAddress { print (ip) } //Unwraps optional
}
}
override func controlTextDidChange(_ obj: Notification) {
if let txtField = obj.object as? NSTextField {
if txtField.tag == 0 {
//Validation (for later)
IPAddress = txtField.stringValue
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
func viewDidLoad() {
super.viewDidLoad()
}
}
override func viewDidAppear() {
// Window Properties, including solid colour, lack of resize, movable by background.
view.window?.titlebarAppearsTransparent = true
view.window?.backgroundColor = NSColor.white
view.window?.styleMask.remove(.resizable)
view.window?.isMovableByWindowBackground = true
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
struct SOAPEncoding: ParameterEncoding {
let service: String
let action: String
let IRCCC: String
func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
var urlRequest = try urlRequest.asURLRequest()
guard parameters != nil else { return urlRequest }
if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {
urlRequest.setValue("text/xml", forHTTPHeaderField: "Content-Type")
}
let soapBody = "<?xml version=\"1.0\" encoding=\"utf-8\"?><s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:\(action) xmlns:u=\"\(service)\"><IRCCCode>\(IRCCC)</IRCCCode></u:X_SendIRCC></s:Body></s:Envelope>"
urlRequest.httpBody = soapBody.data(using: String.Encoding.utf8)
return urlRequest
}
}
func triggerRemoteControl(irccc: String) {
Alamofire.request(IPAddress!,
method: .post,
parameters: ["parameter" : "value"],
encoding: SOAPEncoding(service: "urn:schemas-sony-com:service:IRCC:1",
action: "X_SendIRCC", IRCCC: irccc)).responseString { response in
print(response)
}
}
}
Three errors:
First, you are overriding viewDidLoad() and defining another viewDidLoad() inside of it.
Your code:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
func viewDidLoad() {
super.viewDidLoad()
}
}
Should just look like this:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
Second, you are overriding viewDidAppear but never calling super.
Your code:
override func viewDidAppear() {
// Window Properties, including solid colour, lack of resize, movable by background.
view.window?.titlebarAppearsTransparent = true
view.window?.backgroundColor = NSColor.white
view.window?.styleMask.remove(.resizable)
view.window?.isMovableByWindowBackground = true
}
Should look like this:
override func viewDidAppear() {
super.viewDidAppear()
// Window Properties, including solid colour, lack of resize, movable by background.
view.window?.titlebarAppearsTransparent = true
view.window?.backgroundColor = NSColor.white
view.window?.styleMask.remove(.resizable)
view.window?.isMovableByWindowBackground = true
}
Third, you are overriding the IPAdress didSet and then setting it again. This will cause an infinite loop. You are also comparing a textField to nil, which it will never be, because it's a NSTextField!, instead of checking whether it's empty or not. I can't really make sense of what you're trying to achieve here but you should rip all this overriding nonsense out until you can clearly formulate your intention.

Swift Take a Variable

I want to take a variable nomeLabel in the func goToSecondView and display it on a SecondView
class ViewController: UIViewController {
var nomeLabel:String!
#IBAction func goToSecondView(sender: AnyObject) {
self.performSegueWithIdentifier("goToSecondView", sender: self)
let newButton = sender as UIButton
nomeLabel = newButton.titleLabel!.text
println("nomeLabel \(nomeLabel)")
}
}
how can I do ?
You need to implement prepareForSegue where you have access to the destination view controller. Here is an example on how to do that:
class ViewController: UIViewController {
#IBOutlet var newButton: UIButton!
#IBAction func goToSecondView(sender: AnyObject) {
self.performSegueWithIdentifier("goToSecondView", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "goToSecondView" {
let secondViewController = segue.destinationViewController as SecondViewController
secondViewController.nomeLabel = self.newButton.titleLabel.text
}
}