I have my main screen with only one button on it "Show next screen". When the second screen(VC) pops up it has 2 buttons (go back and toSelect button).
My goal is to when I show my second screen and select a button on it then go back to first. The button on my second screen will stay selected. How can I do that?
So basically I need to save my actions on the second screen so if I go back to it it will show everything I did.
What is the best way to do it?
Storyboard
The easiest way to achieve this using Delegate and protocol.
you should listen and save the changes of SecondViewController at FirstViewController using delegate methods.
And when you are presenting the secondViewController you will share the saved changes to secondViewController so that button can be selected on behalf of that information
Code -
class FirstViewController: UIViewController {
//secondViewController States
private var isButtonSelected = false
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func gotoSecondVCAction(_ sender: Any) {
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
guard let secondVC = storyBoard.instantiateViewController(withIdentifier: "SecondViewController") as? SecondViewController else { return }
secondVC.isButtonSelected = isButtonSelected
secondVC.delegate = self
self.present(secondVC, animated: true, completion: nil)
}
}
extension FirstViewController: ButtonSelectionProtocol {
func button(isSelected: Bool) {
isButtonSelected = isSelected
}
}
and for secondViewController
protocol ButtonSelectionProtocol {
func button(isSelected:Bool)
}
class SecondViewController: UIViewController {
var isButtonSelected : Bool = false
var delegate:ButtonSelectionProtocol?
#IBOutlet weak var selectButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
if isButtonSelected {
selectButton.tintColor = .red
selectButton.setTitle("Selected", for: .normal)
}else{
selectButton.tintColor = .green
selectButton.setTitle("Select Me", for: .normal)
}
}
#IBAction func gobackAction(_ sender: Any) {
self.dismiss(animated: true, completion: nil)
}
#IBAction func selectAction(_ sender: Any) {
self.dismiss(animated: true, completion: nil)
isButtonSelected.toggle()
delegate?.button(isSelected: isButtonSelected)
}
}
Related
I made it using a storyboard
I made another view controller for the custom tab bar and created a UIView called innerContents.
And I made another view controller for the setting page in it and put another view controller in innerContents with addSubview.
CustomTabBar with innerContents UIView
thats innerTabBar main CustomTabBar View Controller page
other ViewController
i will put thats ViewController in innerContents. so i writed addSubView. they are showing but UIButtons are not working. only work ScrollView.
How can I fix it?
code
I confirmed that all outlets are connected normally.
But the UIButton inside the UIView inside the UIScrollView inside the UiView of another view controller inside the UiView doesn't work.
mainCustomTabBar Page viewController > innerContents > otherViewController(addSubView) > UIView > UI ScrollView > UIView > UIView > UIButton(it's not working. i want fix that)
if currentPage != 5 {
currentPage = 5
print("탭바 클릭 5")
guard let AppSet = self.storyboard?.instantiateViewController(identifier: "AppSetViewController") as? AppSetViewController else {return}
AppSet.view.frame = ContentsView.bounds
AppSet.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
AppSet.view.tag = 500
removeSubview(tag: nowTag)
nowTag = 500
ContentsView.addSubview(AppSet.view)
let root = UIApplication.shared.windows.first?.rootViewController
root?.addChild(AppSet)
AppSet.didMove(toParent: root!)
page5Mode()
return
}
}
//
// AppSetViewController.swift
// rael
//
// Created by HongDaehyeon on 2021/07/08.
// 앱 설정 페이지를 위한 페이지 입니다.
import UIKit
class AppSetViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
#IBOutlet var ContentView: UIView!{
didSet {
self.ContentView.isUserInteractionEnabled = true
}
}
#IBOutlet var Scrollview: UIScrollView!{
didSet{
self.Scrollview.isExclusiveTouch = true
}
}
//지갑정보
#IBAction func walletInfo(_ sender: Any) {
print("지갑정보")
}
//알림설정
#IBAction func alertSet(_ sender: Any) {
print("알림설정")
}
//인증방식설정
#IBAction func authSet(_ sender: Any) {
print("인증방식설정")
}
//공지사항
#IBAction func noticeNav(_ sender: Any) {
let vc = self.storyboard?.instantiateViewController(identifier: "SettingsNoticeViewController")
let navController = UINavigationController(rootViewController: vc!)
navController.modalPresentationStyle = .fullScreen
navController.modalTransitionStyle = .crossDissolve
navController.setNavigationBarHidden(true, animated: false)
self.present(navController, animated: true, completion: nil)
}
//FAQ
#IBAction func faqNav(_ sender: Any) {
let vc = self.storyboard?.instantiateViewController(identifier: "FaqViewController")
let navController = UINavigationController(rootViewController: vc!)
navController.modalPresentationStyle = .fullScreen
navController.modalTransitionStyle = .crossDissolve
navController.setNavigationBarHidden(true, animated: false)
self.present(navController, animated: true, completion: nil)
}
//고객상담
#IBAction func serviceCenter(_ sender: Any) {
print("고객상담")
}
//약관 및 정책
#IBAction func termsNav(_ sender: Any) {
print("약관 및 정책")
}
//지갑 삭제
#IBAction func removeWallet(_ sender: Any) {
print("지갑삭제")
}
//전화걸기
#IBAction func callService(_ sender: Any) {
print("전화걸기")
let urlString = "tel://1588-8282"
let numberURL = NSURL(string: urlString)
UIApplication.shared.open(numberURL! as URL, options: [:], completionHandler: nil)
}
//앱정보 로딩
#IBOutlet var appVer: UILabel!{
didSet{
self.appVer.text = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
}
}
}```
I spent hours to make this work but I am trying to show an array in a view controller based on the button that is pressed in the previous view. So I want to use the same view controller but with different data.
In the view controller:
#IBAction func firstDeck(_ sender: UIButton) {
var dataSource : CardsDataModel? {
didSet {
label.text = cardsDeck.FirstDate()
}
}
}
#IBAction func secondDeck(_ sender: UIButton) {
var dataSource : CardsDataModel? {
didSet {
label.text = cardsDeck.PizzaFriends()
}
}
}
So there are two cardDecks: PizzaFriends and FirstDates. I tried using IBAction from the buttons to then show the relevant cardsDeck but without success. The cards are empty.
Declare an Array of String type variable in NextViewController
var someData = [String]()
In viewDidLoad() method of NextViewController add this
print("Some Data: \(someData)")
In the PreviousViewController in the IBAction methods present/push the NextViewController with assign someText variable according to which button has been pressed
#IBAction func firstDeck(_ sender: UIButton) {
let vc = NextViewController()
vc.someData = cardsDeck.FirstDate()
// If you want to present NextViewController
present(vc, animated: true, completion: nil)
// If you want to push NextViewController to navigation stack
//navigationController?.pushViewController(vc, animated: true)
}
#IBAction func secondDeck(_ sender: UIButton) {
let vc = NextViewController()
vc.someData = cardsDeck.PizzaFriends()
// If you want to present NextViewController
present(vc, animated: true, completion: nil)
// If you want to push NextViewController to navigation stack
//navigationController?.pushViewController(vc, animated: true)
}
Here is a sample NextViewController
class NextViewController: UIViewController {
var someData = [String]()
var cardView = SwipeCardView(frame: CGRect(x: 10, y: 150, width: 300, height: 600))
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .white
self.view.addSubview(cardView)
cardView.label.text = "\(someData)"
}
}
I want to use UISwitch from that when isON use it should be in ViewController1 isOFF then it has to go next ViewController. Can someone help me on this?
import Foundation
import Firebase
import FirebaseAuth
class HomeViewController: UIViewController {
#IBOutlet weak var citiPostSwitch:UISwitch!
#IBAction func switchToCitiPost (switchState: UISwitch){
if citiPostSwitch.isOn{
print("your in ViewConroller 1")
citiPostSwitch.setOn(false, animated: true)
} else{
citiPostSwitch.setOn(true, animated: true)
print("your in ViewController 2")
}
}
#IBAction func logOutAction(sender: AnyObject) {
if Auth.auth().currentUser != nil {
do {
try Auth.auth().signOut()
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "SignUp")
present(vc, animated: true, completion: nil)
} catch let error as NSError {
print(error.localizedDescription)
}
}
}
}
In your function , just off the switch of this and second controller, in which your are navigating.
#IBAction func switchToCitiPost (switchState: UISwitch){
if citiPostSwitch.isOn {
citiPostSwitch.setOn(false, animated: true)
let vc = SecondViewController()
vc.switch.setOn(false, animated: true)
self.navigationController?.pushViewController(vc, animated: true)
}
}
When your come to your controller you will get your switch in off state.
class SecondViewController: UIViewController {
#IBOutlet weak var `switch`: UISwitch!
override func viewDidLoad() {
super.viewDidLoad()
self.switch.addTarget(self, action: #selector(self.switchAction(_:)), for: .valueChanged)
}
#objc func switchAction(_ switchState: UISwitch) {
self.navigationController?.popViewController(animated: true)
}
}
In SecondView Controller , on switch action just dismiss or pop from Controller.
Hope it helps
I have implemented delegate in LoginViewController defined in RegistrationViewController. Callback function is calling but the problem is that I am not able to update the textfield of LoginViewController in delegate method.
LoginViewController.swift
import UIKit
class LoginViewController :UIViewController,RegisterViewDelegate {
#IBOutlet weak var mobileNumber: UITextField!
#IBAction func showRegistrationView(_ sender: Any) {
let controller = storyboard?.instantiateViewController(withIdentifier: "registration") as! RegistrationViewController
controller.delegate = self
present(controller, animated: false, completion: nil)
}
func onUserRegistrationCompletion(number: String) {
print(number) // output is 05010101010
DispatchQueue.main.async {
self.mobileNumber.text! = number
print(self.mobileNumber.text!) . // output is empty
}
}
}
RegistrationViewController.swift
import UIKit
class RegistrationViewController: UIViewController {
weak var delegate:RegisterViewDelegate?
#IBAction func register(_ sender: Any) {
self.delegate?.onUserRegistrationCompletion(number: "05010101010")
let controller = self.storyboard?.instantiateViewController(withIdentifier: "login")
present(controller!, animated: false, completion: nil)
}
}
protocol RegisterViewDelegate:class {
func onUserRegistrationCompletion(number:String)
}
it means you allocating the memory again on self.storyboard?.instantiateViewController(withIdentifier: "login") in Register VC, that the reason your delegate is by default goes to nil.
#IBAction func register(_ sender: Any) {
self.delegate?.onUserRegistrationCompletion(number: "05010101010")
self.dismiss(animated: true, completion:nil)
}
I suggest you to use navigationController.
and you can push to next view this way:
let controller = storyboard?.instantiateViewController(withIdentifier: "registration") as! RegistrationViewController
controller.delegate = self
self.navigationController?.pushViewController(controller, animated: true)
and when you want to go back to previous view use this code:
self.delegate?.onUserRegistrationCompletion(number: "05010101010")
self.navigationController?.popViewController(animated: true)
And your result will be:
Check THIS sample for more info.
And don't forget to Embed In your LoginViewController into navigationController from storyboard. as shown in demo project.
I am having troubles showing the Game Center leaderboard when the user presses a button on my SecondViewController (game over screen with score/top score). The UIbutton is ShowLeaderboard which you'll see below.
The error I get is:
Warning: Attempt to present <GKGameCenterViewController: 0x7fb1c88044a0> on <UIViewController: 0x7fb1c2624e90> whose view is not in the window hierarchy!
I have tried dismissing the view first but no matter what I do I can't just get the leaderboard view to show. Below is my SecondViewController code:
import UIKit
import GameKit
class SecondViewController: UIViewController, GKGameCenterControllerDelegate {
#IBOutlet var scoreLabel: UILabel!
#IBOutlet var HighScoreLabel: UILabel!
var receivedString: String = ""
var receivedHighScore: String = ""
override func viewDidLoad() {
super.viewDidLoad()
scoreLabel.text = receivedString
HighScoreLabel.text = receivedHighScore
}
#IBAction func ShowLeaderboard(sender: UIButton) {
dismissViewControllerAnimated(true, completion:nil)
showLeader()
}
func showLeader() {
var vc = self.view?.window?.rootViewController
var gc = GKGameCenterViewController()
gc.gameCenterDelegate = self
vc?.presentViewController(gc, animated: true, completion: nil)
}
func gameCenterViewControllerDidFinish(gameCenterViewController: GKGameCenterViewController!)
{
gameCenterViewController.dismissViewControllerAnimated(true, completion: nil)
}
override func prefersStatusBarHidden() -> Bool {
return true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func retryButton(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil)
}
}
EDIT Got it working! All I had to do was change
var vc = self.view?.window?.rootViewController
to
var vc = self
You are probably seeing this warning because you are displaying the Leaderboard before dismissViewControllerAnimated has finished the animation. You should place the showLeader() inside the completion argument of dismissViewControllerAnimated.
Here is my Code. Hope it helps!
if (self.levelGameAttemptCount == 3)
{
self.canRestart = false
let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
let vc = mainStoryboard.instantiateViewControllerWithIdentifier("gameOverControllerID") as! GameOverController
self.view!.window!.rootViewController!.dismissViewControllerAnimated(false, completion: nil)
UIApplication.sharedApplication().keyWindow!.rootViewController!.presentViewController(vc, animated: true, completion: nil)
}
else
{
self.canRestart = true
}