Swift 3 - Delegate always returns nil value - ios

UPDATED:
I have designed custom tabBar using buttons. I have 3 tabs,
First tab has Messages icon, Second has Profile icon and Third has Photos icon. For third tab button, I have used uiCollectionView() where I need to set images.
For the Third tab's ViewController,there is one condition that I need to check, before changing the title of the first tab button. If messages JSON array is not empty then set "new message" title on the first tab button, else the Messages icon won't change.
There is one ParentTabViewController which has these 3 tabs, I have used uiView, where I change the content according to the tab buttons pressed. I tried to access the values of 3rd tab in ParentTabViewController by using delegate, but the delegate is always nil. I did like this:
class ParentTabViewController: UIViewController,MessageDelegateProtocol{
#IBOutlet weak var contentView: UIView!
#IBOutlet var tabBarButtons : [UIButton]!
#IBOutlet weak var firstTabButton: UIButton!
var MessageVC : UIViewController!
var ProfileVC : UIViewController!
var PhotosVC : UIViewController!
var viewControllers : [UIViewController]!
var message : String!
var selectedIndex:Int = 0
var photoVC = PhotosVC()
override func viewDidLoad() {
super.viewDidLoad()
photoVC.newMessageDelegate = self
let storyBoard = UIStoryboard(name:"Main", bundle:nil)
MessageVC = storyBoard.instantiateViewController(withIdentifier: "messagevc")
ProfileVC = storyBoard.instantiateViewController(withIdentifier: "profile")
PhotosVC = storyBoard.instantiateViewController(withIdentifier: "photos")
viewControllers = [MessageVC, ProfileVC, PhotosVC]
tabBarButtons[selectedIndex].isSelected = true
didPressTabs(tabBarButtons[selectedIndex])
}
#IBAction func didPressTabs(_ sender: UIButton)
{
let previousIndex = selectedIndex
selectedIndex = sender.tag
tabBarButtons[previousIndex].isSelected = false
let previousVC = viewControllers[previousIndex]
previousVC.willMove(toParentViewController: nil)
previousVC.removeFromParentViewController()
previousVC.view.removeFromSuperview()
sender.isSelected = true
let presentVC = viewControllers[selectedIndex]
addChildViewController(presentVC)
presentVC.view.frame = contentView.bounds
contentView.addSubview(presentVC.view)
presentVC.didMove(toParentViewController: self)
if selectedIndex == 2{ // this is what I thought of doing.Correct me if wrong.
// check the condition
// if messagesArray != nil
// set the first tab title "new message"
}
else{
// do not change the button image
}
}
func sendMessage(message : String)
{
self.message = message
print("message........", self.message, "\n\n")
}
}
Here is the View Controller for 3rd tab:
import UIKit
protocol MessageDelegateProtocol:class {
func sendMessage(message : String)
}
class PhotosVC: UIViewController,UICollectionViewDataSource, UICollectionViewDelegate{
#IBOutlet weak var collectionView: UICollectionView!
var userMessageArray = [UserMessageClass]() // array of model class
var newMessage : String!
weak var newMessageDelegate : MessageDelegateProtocol?
override func viewDidLoad() {
super.viewDidLoad()
collectionView.delegate = self
collectionView.dataSource = self
loadData() // function to get json reponse
}
// implement collectionView delegate and dataSource methods
func getData(newMsg : UserMessageClass) //func to get values from model class
{
newMessage = newMsg.messageString // here I get the "new message" String
newMessageDelegate?.sendMessage(message: newMessage)
} enter code here
func loadData()
{
// get json response. And pass the payload to UserMessageClass using that class's array
userMessageArray.append(UserMessageClass(dict : jsonData))
var msgData = UserMessageClass(dict: jsonData)
getData(alarm: msgData)
}
}
I tried searching a lot about accessing tab buttons in another VC, but didn't find any nearby approach as such. Also I am not able to figure out why delegate is always nil. Suggestions or Help would be grateful. Many Thanks :)

The problem is the following line.
let firstTab = storyBoard.instantiateViewController(withIdentifier: "parentVC") as! ParentViewController
You are probably expecting it to give you the instance of ParentViewController which you have setup initially. However, it will give you the instance of a newly initiated ParentViewController which is not what you want.
To counter this problem you can either make use of a delegate or completion block defined which will be defined inside your ParentViewController class.
Update:
Try adding PhotosVC.newMessageDelegate = self under the line
PhotosVC = storyBoard.instantiateViewController(withIdentifier: "photos")
Also change var PhotosVC : UIViewController! to var photosVC: PhotosVC!
This should work now.

Related

How to pass data from First TabBarItem to Second TabBarItem

Above I have a TabBarController with 4 buttons. When I press the second TabBarItem(Cars) or third TabBarItem(Bicycles) I want to pass some values from the firstTabBarItem(HomeScreen) .
I'm using Swift 5 and I don't have a SceneDelegate in my main project (is a 3 years old project), I have only the AppDelegate and this is why I wasn't able to try the only example which I found from Stackoverflow about a similar question like mine.
I managed somehow to pass the data between ViewControllers through TabBarController but I don't think is the right approach anymore (as some people from this community are also saying this on some threads) because when I click on different TabBarItems the data get lost and after is showing up again but with the wrong values etc.
I will attach below a GIF with the bugs which I'm getting while I navigate and also my current code with a link to the DEMO project on GitHub (https://github.com/florentin89/PassDataTabBarController/)
Can you help me please to pass the data using the right implementation ?
Here is my code for HomeScreen ViewController:
import UIKit
class HomeViewController: UIViewController {
#IBOutlet var textfieldHoldingCarsValue: UITextField!
#IBOutlet var textfieldHoldingBicyclesValue: UITextField!
var valueForCarsScreen = String()
var valueForBicyclesScreen = String()
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillDisappear(_ animated: Bool) {
valueForCarsScreen = textfieldHoldingCarsValue.text ?? String()
valueForBicyclesScreen = textfieldHoldingBicyclesValue.text ?? String()
if let navController = self.tabBarController?.viewControllers?[1] as? UINavigationController{
if let carsTab = navController.children.first as? PostcodeViewController{
carsTab.receivedValueFromHomeScreen = valueForCarsScreen
}
}
if let navController = self.tabBarController?.viewControllers?[2] as? UINavigationController{
if let bicyclesTab = navController.children.first as? PostcodeViewController{
bicyclesTab.receivedValueFromHomeScreen = valueForBicyclesScreen
}
}
}
// Logout the user and navigate to Login screen
#IBAction func logoutTapped(_ sender: UIBarButtonItem) {
self.view.window?.rootViewController?.dismiss(animated: true, completion: nil)
}
}
Here is my code for the ViewController used for second and third TabBarItem:
import UIKit
class PostcodeViewController: UIViewController {
#IBOutlet var receivedValueLabel: UILabel!
var receivedValueFromHomeScreen = String()
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
if self.tabBarController?.selectedIndex == 1 {
receivedValueLabel.text = "Value received for Cars: \n" + receivedValueFromHomeScreen
}
if self.tabBarController?.selectedIndex == 2 {
receivedValueLabel.text = "Value received for Bicycles: \n" + receivedValueFromHomeScreen
}
}
}
Here is a GIF with the bugs/glitches which I'm getting when I navigate between ViewControllers:
Thank you for reading this !
The reason is that viewWillAppear of PostcodeViewController is called before the selectedIndex of your tabbar is changed. The first time it works ok. Just put the line:
print("selected index = \(self.tabBarController?.selectedIndex ?? -1)")
in your viewWillAppear and you will see.
The easiest way to fix your code is to move the logic of PostcodeViewController from viewWillAppear to viewDidAppear.
a simple workaround can be.. store data in a static variable in login class, you can access it in other classes.
long workaround is,
create a Custom TabBar programmatically, pass data from login viewController to parent CustomTab bar, and pass data to next screen with the help of delegates.
The fix was to move the code of PostcodeViewController from viewWillAppear to viewDidAppear like this:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
print("Selected index: \(self.tabBarController?.selectedIndex ?? -1)")
if self.tabBarController?.selectedIndex == 1 {
receivedValueLabel.text = "Value received for Cars: \n" + receivedValueFromHomeScreen
}
if self.tabBarController?.selectedIndex == 2 {
receivedValueLabel.text = "Value received for Bicycles: \n" + receivedValueFromHomeScreen
}
}
Now everything works perfect !
GIF below:

delegate method not getting called with UITabBarController

In FourthViewController, I have a slider, which has values ranging from 1 to 1000. The value that is set gets sent via the delegate to PatternViewController, where it should be used to do sth (I put the print for testing purposes).
I've worked with delegates before and it was all ok, checked the code multiple times and multiple answers here on stack, I can't seem to find the issue. Any help would be much appreciated
update: I have added a button so that it would be easier to track along. It turns out that by pressing first time the button, nothing happens. but if I first checkout the PatternViewController, then I go back to FourthViewController and press the button, the delegate gets triggered. anyone got any idea on why is this happening?
FourthViewController
import UIKit
class FourthViewController: UIViewController {
//MARK: Outlets
#IBOutlet var persistenceButton: UIButton!
#IBOutlet var persistenceSlider: UISlider!
#IBOutlet var persistenceLabel: UILabel!
weak var delegate: FourthViewControllerDelegate?
//MARK: Stored Properties - Constants
let userDefaults = UserDefaults.standard
let keyName = "sliderValue"
//MARK: Initializer
override func viewDidLoad() {
super.viewDidLoad()
loadSliderValue()
initialSetUp()
}
//MARK: Actions
#IBAction func handleValueChanged(_ sender: UISlider) {
updateLabel()
persistSliderValue(value: persistenceSlider.value, key: keyName)
}
//MARK: Methods
func updateLabel() {
persistenceLabel.text = String(format: "%.2f", persistenceSlider.value)
}
func persistSliderValue(value: Float, key: String) {
userDefaults.set(value, forKey: key)
}
func loadSliderValue() {
let persistedValue = userDefaults.float(forKey: keyName)
persistenceSlider.value = persistedValue
updateLabel()
}
}
func initialSetUp() {
persistenceButton.addTarget(self, action: #selector(handleButtonPressed), for: .touchUpInside)
}
#objc func handleButtonPressed() {
delegate?.valueChanged(value: persistenceSlider.value)
}
}
PatternViewController
import UIKit
class PatternViewController: UIViewController, FourthViewControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
setUp()
}
func setUp() {
if let tabBar = self.tabBarController, let viewController = tabBar.viewControllers, let fourthViewController = viewController[3] as? FourthViewController {
fourthViewController.delegate = self
}
}
func valueChanged(value: Float) {
print(value)
}
}
It depends upon how you instantiated the tab view controller. If you do it with storyboards, for example, the view controllers for the respective tabs are instantiated lazily, only instantiated as the user taps on them. (This helps reduce latency resulting from instantiating all four of the tabs’ view controllers.)
While you theoretically could go ahead and have the tab bar controller instantiate the four view controllers programmatically up front, rather than just-in-time via the storyboard, I might instead consider specifying a UITabBarControllerDelegate for the tab bar controller. Have the tab bar controller’s delegate method update the relevant tab’s view controller’s model.
Here is an example with two tabs, the first has a slider and the second has a label that displays the slider’s value. In this simplified example, I’ve moved the model object (the value associated with the slider) into the tab bar controller, and it passes it to the second view controller when you select the associated tab.
// TabViewController.swift
import UIKit
class TabBarController: UITabBarController {
var value: Float = 0.5
override func viewDidLoad() {
super.viewDidLoad()
delegate = self
}
}
// MARK: - UITabBarControllerDelegate
extension TabViewController: UITabBarControllerDelegate {
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
guard let viewController = viewController as? SecondViewController else { return }
viewController.value = value
}
}
And
// FirstViewController.swift
import UIKit
class FirstViewController: UIViewController {
#IBOutlet weak var slider: UISlider!
override func viewDidLoad() {
super.viewDidLoad()
guard let tabBarController = tabBarController as? TabViewController else { return }
slider.value = tabBarController.value
}
#IBAction func didAdjustSlider(_ sender: UISlider) {
guard let tabBarController = tabBarController as? TabViewController else { return }
tabBarController.value = sender.value
}
}
And
// SecondViewController.swift
import UIKit
class SecondViewController: UIViewController {
#IBOutlet weak var label: UILabel!
var value: Float = 0 { didSet { updateLabel() } }
let formatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .percent
return formatter
}()
override func viewDidLoad() {
super.viewDidLoad()
updateLabel()
}
func updateLabel() {
label?.text = formatter.string(for: value)
}
}
Probably needless to say, I not only set the base view controller class for the two tab’s view controllers, but also set the base class for the tab bar controller’s storyboard scene to the above TabBarController.

Swift - Delegate through Nav Controller

I'm going to include my full code in this but I will try to give pointers to where the relevant bits are. Basically I am returning to a view controller from an Unwind Segue with some new data. I am using that data successfully in the 'NBARotoHome' VC but I additionally need to pass some of that data through an embedded Nav controller to 'NBARotoTabPager' vc.
I am trying to do this using the 'UpdateChildView' delegate (at the top of the first block of code) and calling its method in 'loadViewData() (in the 'if statement' near the bottom of the first block).
protocol UpdateChildView : class {
func updateView()
func test()
var playerSelected: Player? { get set }
}
class RotoViewRoundCell: UITableViewCell{
#IBOutlet weak var categoryLabel: UILabel!
}
class RotoViewRoundHeader: UITableViewCell{
}
class NBARotoHome: UIViewController{
#IBOutlet weak var posPaidLabel: UILabel!
#IBOutlet weak var progressIndicator: UIProgressView!
#IBOutlet weak var vsLabel: UILabel!
#IBOutlet weak var fantasyFundsAmountLabel: UILabel!
#IBOutlet weak var fantasyFundsLabel: UILabel!
#IBOutlet weak var playerName: UILabel!
#IBOutlet weak var roundIndicator: UILabel!
var selectedPlayer: Player!
var firstNavController: UINavigationController!
weak var updateChildView : UpdateChildView?
override func viewDidLoad() {
super.viewDidLoad()
loadViewData()
firstNavController = self.navigationController
let rightBarButton = UIBarButtonItem(title: "Select", style: UIBarButtonItemStyle.plain, target: self, action: #selector(myRightSideBarButtonItemTapped(_:)))
self.navigationItem.rightBarButtonItem = rightBarButton
self.title = "NBA Roto"
}
func myRightSideBarButtonItemTapped(_ sender:UIBarButtonItem!){
performSegue(withIdentifier: "ShowDraft", sender: nil)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "ShowDraft" {
let navVC = segue.destination as? UINavigationController
let nbaDraftList = navVC?.viewControllers.first as! NBADraftList
nbaDraftList.mainNavController = firstNavController
}
if (segue.identifier == "buyNavControllerChild"){
// let navVC = segue.destination as? UINavigationController
// let buyVC = navVC?.viewControllers.first as! NBARotoTabPager
// buyVC.delegate = self
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
#IBAction func prepareForUnwind(segue: UIStoryboardSegue) {
}
func loadViewData(){
if((selectedPlayer) != nil){
roundIndicator.text = "Upcoming: " + selectedPlayer.game_time
playerName.text = selectedPlayer.Name
vsLabel.text = selectedPlayer.visiting + " # " + selectedPlayer.home
fantasyFundsLabel.text = ""
fantasyFundsAmountLabel.text = ""
updateChildView?.test()
// updateChildView?.playerSelected = selectedPlayer
// updateChildView?.updateView()
}else{
roundIndicator.text = "Select a Player"
playerName.text = "No Player Selected"
vsLabel.text = "--"
fantasyFundsLabel.text = "Fantasy Funds"
fantasyFundsAmountLabel.text = "$10,000"
}
}
}
Because I haven't been able to get the delegate to work, I have been playing around with setting its delegate property in the above 'prepare' method -'buyVC.delegate = self' - but I'm getting 'buyVC has no member delegate' so that has been a dead end.
The next bit of code is the NBARotoTabPager vc which is embedded in the navigation controller. For reasons I'm no longer sure about I decided to make it a subclass of NBARotoHome, but its basically a custom tab pager that uses a segmented control to switch between two additional vcs.
The most important step at this point is just getting the 'test' function to work (which just prints 'test'. Its implemented in the below block of code second from the bottom above updateView).
class NBARotoTabPager: NBARotoHome, UpdateChildView{
#IBOutlet weak var segmentedControl: UISegmentedControl!
#IBOutlet weak var scoreKey: UIBarButtonItem!
#IBOutlet weak var standings: UIBarButtonItem!
var playerSelected: Player?
override func viewDidLoad() {
navigationController?.navigationBar.barTintColor = UIColor(red: 27/255, green: 27/255, blue: 27/255, alpha: 1)
scoreKey.setTitleTextAttributes([NSFontAttributeName: UIFont(name: "Helvetica", size: 13.0)!], for: UIControlState.normal)
scoreKey.tintColor = UIColor.blue
standings.setTitleTextAttributes([NSFontAttributeName: UIFont(name: "Helvetica", size: 13.0)!], for: UIControlState.normal)
standings.tintColor = UIColor.blue
setupView()
}
private func setupView() {
setupSegmentedControl()
updateView()
}
private func setupSegmentedControl() {
// Configure Segmented Control
segmentedControl.removeAllSegments()
segmentedControl.insertSegment(withTitle: "Live", at: 0, animated: false)
segmentedControl.insertSegment(withTitle: "Avg / +", at: 1, animated: false)
segmentedControl.addTarget(self, action: #selector(selectionDidChange(_:)), for: .valueChanged)
segmentedControl.selectedSegmentIndex = 0
}
func selectionDidChange(_ sender: UISegmentedControl) {
updateView()
}
private lazy var viewLiveTab: NBARotoLive = {
// Load Storyboard
let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
// Instantiate View Controller
var viewController = storyboard.instantiateViewController(withIdentifier: "NBARotoLive") as! NBARotoLive
if((self.playerSelected) != nil){
viewController.selectedPlayer = self.playerSelected
}
// Add View Controller as Child View Controller
self.add(asChildViewController: viewController)
return viewController
}()
private lazy var viewAvgsTab: NBARotoAvgs = {
// Load Storyboard
let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
// Instantiate View Controller
var viewController = storyboard.instantiateViewController(withIdentifier: "NBARotoAvgs") as! NBARotoAvgs
if((self.playerSelected) != nil){
viewController.selectedPlayer = self.playerSelected
}
// Add View Controller as Child View Controller
self.add(asChildViewController: viewController)
return viewController
}()
private func add(asChildViewController viewController: UIViewController) {
// Add Child View Controller
addChildViewController(viewController)
// Add Child View as Subview
view.addSubview(viewController.view)
// Configure Child View
viewController.view.frame = view.bounds
viewController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
// Notify Child View Controller
viewController.didMove(toParentViewController: self)
}
private func remove(asChildViewController viewController: UIViewController) {
// Notify Child View Controller
viewController.willMove(toParentViewController: nil)
// Remove Child View From Superview
viewController.view.removeFromSuperview()
// Notify Child View Controller
viewController.removeFromParentViewController()
}
internal func test(){
print("test")
}
internal func updateView() {
if segmentedControl.selectedSegmentIndex == 0 {
let position = viewAvgsTab.tableView.contentOffset.y;
viewLiveTab.tableView.contentOffset = CGPoint(x:0, y:position);
remove(asChildViewController: viewAvgsTab)
add(asChildViewController: viewLiveTab)
} else {
let position = viewLiveTab.tableView.contentOffset.y;
viewAvgsTab.tableView.contentOffset = CGPoint(x:0, y:position);
remove(asChildViewController: viewLiveTab)
add(asChildViewController: viewAvgsTab)
}
}
}
I've looked at a lot of examples but I don't understand the whole 'setting the delegate' thing i.e. theSecondViewController.delegate = self. Sometimes I see examples where you don't need to do this. And other times it seems like my VCs don't even have a delegate property. So I'm not sure if that's my specific problem or not but any direction would be greatly appreciated. Thanks
There are three steps to implement a delegate.
create a protocol.. (you've already done this by creating a updateChildView protocol)
you need to implement this protocol in the class you wish to receive and process this data.. (you've not done this step and thats why you cant set buyVC.delegate = self)
you need to add a property in ViewController2 called "delegate" and make it as a type of your protocol in step 1 (you've not done this step and there is no property called "delegate" in vc2 .. that's why you get this error 'buyVC has no member delegate')
Here's a quick example:
Protocol:
protocol UpdateChildView{ //removed :class
func updateView()
func test()
var playerSelected: Player? { get set }
}
Viewcontroller A:
class NBARotoHome: UIViewController, UpdateChildView { //added conformance to the protocol
//add the methods for conforming to protocol and add your implementation
func updateView() {
//add your implementation
}
func test(){
//add your implementation
}
var playerSelected: Player? {
//add your implementation
}
prepare(for: Segue) {
/** code for passing data **/
let navVC = segue.destination as? UINavigationController
let buyVC = navVC?.viewControllers.first as! NBARotoTabPager
buyVC.delegate = self
//sets the delegate in the new viewcontroller
//remember.. delegate is a property in the next vc
// and the property only accepts any viewcontroller that is implements updatechildview protocol
present(vc2)
}
}
viewcontroller2 :
class viewControllerB: UIViewController {
var delegate: UpdateChildView? //add this
viewdidload {
delegate?.test() //call the func in the previous vc
}
}

Passing array of objects between views using the same tab bar controller, Swift 3

Following the tutorial to pass data between views using the same tab bar controller: (add "https//:" in front, need 10 reputation to post 2 links) makeapppie.com/2015/02/04/swift-swift-tutorials-passing-data-in-tab-bar-controllers/
It works perfectly when I am only passing a single object, but not when I am trying to pass an array of the same object.
I've created a simple app to illustrate my problem clearer.
https://i.stack.imgur.com/C4APn.png
The object
class Item: NSObject {
}
The custom tab bar controller
class CustomTabBarController: UITabBarController {
var addedItemArray = [Item]()
var addedItem = Item()
}
The first view controller
class FirstViewController: UIViewController {
var addedItem = Item()
var addedItemArray = [Item]()
#IBOutlet var ItemLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
let tbc = tabBarController as! CustomTabBarController
addedItem = tbc.addedItem
addedItemArray = tbc.addedItemArray
//creates the first item in the array
addedItemArray.append(Item())
}
override func viewWillAppear(_ animated: Bool) {
print("addedItem:\(addedItem)")
print("addedItemArray:\(addedItemArray)")
}
#IBAction func addItem() {
//adds additional item to addedItemArray
addedItemArray.append(Item())
print(addedItemArray)
}
}
The second view controller
class SecondViewController: UIViewController {
var addedItem = Item()
var addedItemArray = [Item]()
#IBOutlet var ItemLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
let tbc = tabBarController as! CustomTabBarController
addedItem = tbc.addedItem
addedItemArray = tbc.addedItemArray
}
override func viewWillAppear(_ animated: Bool) {
print("addedItem:\(addedItem)")
print("addedItemArray:\(addedItemArray)")
}
}
When I run the code, I get the following in the console, which is the intended output:
addedItem:<Tab_bar_test.Item: 0x60000001d020>
addedItemArray:[<Tab_bar_test.Item: 0x60800001ce20>]
However, when I click on the second tab, I get this:
addedItem:<Tab_bar_test.Item: 0x60000001d020>
addedItemArray:[]
So for some reason, the program passes a single object, but not the array of object.
I'd like to know why, and how to fix this using best practices of Swift 3. Thanks in advance.
try to use a shared array using singleton or a static class
ex:
class Global : NSObject {
static let sharedInstance = Global()
var addedItemArray = [Item]()
}
you can call it in any view you want
first view
class FirstViewController: UIViewController {
var addedItem = Item()
var addedItemArray = [Item]()
#IBOutlet var ItemLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
let tbc = tabBarController as! CustomTabBarController
addedItem = tbc.addedItem
addedItemArray = Global.addedItemArray
//creates the first item in the array
Global.addedItemArray.append(Item())
}
override func viewWillAppear(_ animated: Bool) {
print("addedItemArray:\(Global.addedItemArray)")
}
#IBAction func addItem() {
//adds additional item to addedItemArray
Global.addedItemArray.append(Item())
print(Global.addedItemArray)
}
to call the array from any view just call it like this Global.addedItemArray

Load information from previous ViewControllers swift

I think we all have been through problems in Swift. I wasn't able to find the correct answer for my question. I've tried over and over again.
I've represented an image where it explains how our app should works.
Users can select an option per view. So in a last one the Labels will change depending of each choose.
I hope you can give me a hand with that guys. Thanks
class ViewController1: UIViewController {
#IBOutlet weak var colorLabelSelected: UILabel!
#IBOutlet weak var nextOutlet: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
nextOutlet.hidden = true
}
#IBAction func greenButton(sender: AnyObject) {
colorLabelSelected.text = "You have selected a green BG color"
nextOutlet.hidden = false
}
#IBAction func blueButton(sender: AnyObject) {
colorLabelSelected.text = "You have selected a blue BG color"
nextOutlet.hidden = false
}
#IBAction func pinkButton(sender: AnyObject) {
colorLabelSelected.text = "You have selected a pink BG color"
nextOutlet.hidden = false
}
}
ViewController 2 and ViewController 3 are like ViewController 1
And I have created a .swift class called Attributes but It's empty for now.
I don't know how to make this work.
When you push your next viewController, override prepareForSegue method, get reference to your destinationViewController and pass to it information you need. This will help pass that data around.
Or create a singleton object, some kind of model, where you write the value user has selected on the first screen, and then on the second screen - you read the data from that singleton object.
Define your model, for example:
class MyData {
var background = UIColor()
var title = ""
var level = ""
}
Use appDelegate. In AppDelegate.swift,
var myData = MyData()
In other screens, for instance first screen, use
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
appDelegate.myData.background = yourColor
Same to others
use prepareForSeguefor your concept
for example
#IBAction func pinkButton(sender: AnyObject) {
colorLabelSelected.text = "You have selected a pink BG color"
nextOutlet.hidden = false
self.performSegueWithIdentifier("thirdController", sender: self)
}
override func prepareForSegue(segue:(UIStoryboardSegue!), sender:AnyObject!)
{
if (segue.identifier == "thirdController")
{
var svc = segue!.destinationViewController as! thirdController
print("i set the loading thingy")
svc.toPass = colorLabelSelected.text
}
}
ThirdViewController
create the global variable like
var toPass:String!
for tutorial reference see this link
you have to create array and create one property of array in second and third class and pass color in secondviewcontroller and in secondviewcontroller add title in array of property and pass it to thirdviewcontroller
you can easily manage using create property.

Resources