4

I want to use booleans as state storage.

In order to do that, I need to be able to change their state from difference places in the project.

To do that, I need somewhere to store them, and a way to pass a reference to them.

I've tried storing them as static variables in a GameManager, but passing references to these only seems to pass the value of true of false, not a reference.

How do I achieve this goal of having a passable boolean reference I can change the state of it from any part of the project?

UPDATE:

This can't be the best way to do this, but this achieves the goal of having a bunch of state booleans that I can use around the game world:

class GameManager {

    static let sharedInstance = GameManager()

    var previewAudioIsON: Bool = false
    var previewVisuaIsOn: Bool  = false
    var timerDisplayIsOn: Bool  = false
    var quickStartIsOn: Bool  = false

    func touchedPreviewAudioButton() -> Bool {
        if previewAudioIsON { previewAudioIsON = false}
        else { previewAudioIsON = true }
     return previewAudioIsON
    }

    func touchedPreviewVisualButton() -> Bool {
        if previewVisuaIsOn { previewVisuaIsOn = false }
        else { previewVisuaIsOn = true }
     return previewVisuaIsOn
    }

    func touchedTimeDisplayButton() -> Bool {
        if timerDisplayIsOn { timerDisplayIsOn = false }
        else { timerDisplayIsOn = true }
     return timerDisplayIsOn
    }

    func touchedQuickStartButton() -> Bool {
        if quickStartIsOn { quickStartIsOn = false }
        else { quickStartIsOn = true }
     return quickStartIsOn
    }
}
Community
  • 1
  • 1
Confused
  • 6,048
  • 6
  • 34
  • 75
  • 1
    One possibility would be to wrap it in a `RefBool` class, as suggested in this answer http://stackoverflow.com/a/40710901/1187415 . – Martin R Nov 22 '16 at 15:00
  • @MartinR putting that approach to the side for a moment, is there a chance I need to use `inout` to make the reference to a boolean editable inside the function it's passed into? – Confused Nov 22 '16 at 15:05
  • Boolean is a primitive, non reference type? Correct me if I'm wrong but I don't think it can be passed by reference? – Jacob King Nov 22 '16 at 15:07
  • @JacobKing you might be very right. No matter what I try, I can't seem to send a reference to a boolean. – Confused Nov 22 '16 at 15:09
  • 1
    You can pass an inout parameter to a function, but that does not make it a reference. You cannot *store* it somewhere in order to reference it later. – Martin R Nov 22 '16 at 15:09
  • @MartinR how is the class `RefBool` approach different from my approach of using `static vars` in a Manager class? – Confused Nov 22 '16 at 15:16
  • @MartinR I'm at the point where I think I need to learn how GameplayKit provides a state machine. It's gotta be simpler than trying to figure out how to use booleans as state managers/flags. – Confused Nov 22 '16 at 15:23

2 Answers2

1

I gave you partially wrong information the other day ( I was having a brain fart), and need to apologize for that. I had overlooked something in my testing...

Here is what you need if you don't want to make the RefBool instances as I suggested (requires more legwork, not recommended):

/// Mutates a boolean:
func toggle(_ boolean: inout Bool) -> Bool {
  boolean ? (boolean = false) : (boolean = true)
  return boolean
}

/// Static state manager for Booleans
struct IsOn {

    private static var
    _previewAudio  = false,
    _previewVisual = false,
    _timerDisplal  = false,
    _quickStart    = false

    enum State { case toggle, get }

   static func previewAudio(_ toggleVal: State = .get) -> Bool {
    if toggleVal == .toggle { toggle(&_previewAudio) }; return _previewAudio
  }

   // ... others
}

Testing:

let referenceToPA = IsOn.previewAudio

print ( IsOn.previewAudio() ) // False (default pram works)
print ( referenceToPA(.get) ) // False (can't use default pram)

referenceToPA(.toggle) 

print ( IsOn.previewAudio() ) // True
print ( referenceToPA(.get) ) // True

IsOn.previewAudio(.toggle)

print ( IsOn.previewAudio() ) // False
print ( referenceToPA(.get) ) // False



But honestly, it would be easier to just do the RefBool from my other answer, then you wouldn't need the enum or the functions:

/// Holds a boolean in .val:
final class RefBool { var val: Bool; init(_ boolean: Bool) { val = boolean } }

/// Static state manager for Booleans
struct IsOn {
    static var
      previewAudio  = RefBool(false),
      previewVisual = RefBool(false),
      timerDisplal  = RefBool(false),
      quickStart    = RefBool(false)
}

Convenience Funcs (not necessary):

/// Mutates a boolean:
func toggle(_ boolean: inout Bool) -> Bool {
  boolean ? (boolean = false) : (boolean = true)
  return boolean
}

/// Mutates .val:
func toggle(_ refBool: RefBool) -> Bool {
    refBool.val ? (refBool.val = false) : (refBool.val = true)
    return refBool.val
}

Testing2:

let refToPA = IsOn.previewAudio

refToPA.val = true

print(refToPA.val) // true
print(IsOn.previewAudio.val) // true

toggle(&refToPA.val)

print(refToPA.val) // false
print(IsOn.previewAudio.val) // false

toggle(refToPA) // Using our fancy second toggle

print(refToPA.val) // true
print(IsOn.previewAudio.val) // true
Fluidity
  • 3,985
  • 1
  • 13
  • 34
0

try something like that:

Full example

import UIKit

enum ButtonType {
    case PreviewAudio;
    case PreviewVisua;
    case TimerDisplay;
    case QuickStart;
}

class SwitchProperty {

    var type: ButtonType
    var value: Bool

    init (type: ButtonType) {
        self.type = type
        self.value = false
    }

    var description: String {
        var result = "type = \(type)\n"
        result += "value = \(value)"
        return result
    }

    func switchValue() {
        value.invertValue()
    }
}

class GameManager {

    static var previewAudioIsON = SwitchProperty(type: .PreviewAudio)
    static var previewVisuaIsOn = SwitchProperty(type: .PreviewVisua)
    static var timerDisplayIsOn = SwitchProperty(type: .TimerDisplay)
    static var quickStartIsOn = SwitchProperty(type: .QuickStart)

}

class Button: UIButton {
    var switchValue: SwitchProperty
    init (type: ButtonType, frame: CGRect) {
        switch type {
        case .PreviewAudio:
            switchValue = GameManager.previewAudioIsON
        case .PreviewVisua:
            switchValue = GameManager.previewVisuaIsOn
        case .TimerDisplay:
            switchValue = GameManager.timerDisplayIsOn
        case .QuickStart:
            switchValue = GameManager.quickStartIsOn
        }
        super.init(frame: frame)
        addTarget(self, action: #selector(Button.buttonTouched), for: .touchUpInside)
    }

    func buttonTouched() {
        switchValue.switchValue()
        print(switchValue.description)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

extension Bool {
    mutating func invertValue() {
        self = !self
    }
}

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        addButton(type: .PreviewVisua, frame: CGRect(x: 40, y: 40, width: 200, height: 40));
        addButton(type: .PreviewAudio, frame: CGRect(x: 40, y: 100, width: 200, height: 40));
    }

    func addButton(type: ButtonType, frame: CGRect) {
        let button = Button(type: type, frame: frame);
        button.setTitleColor(UIColor.blue, for: .normal)
        button.setTitle("\(type)", for: .normal)
        view.addSubview(button)
    }
}

Properties accsess from another code

// change value
GameManager.previewAudioIsON.value = false
// check type
if (GameManager.previewAudioIsON.type == .PreviewAudio) {
    print("previewAudioIsON")
}

Result

enter image description here

Vasily Bodnarchuk
  • 24,482
  • 9
  • 132
  • 127
  • Sorry, I've asked this before somewhere else, and it's slipped my mind, again. What's the difference between a `class var/func` and a `static var/func`? – Confused Nov 22 '16 at 19:24
  • Here is a discussion on this topic. http://stackoverflow.com/questions/25156377/what-is-the-difference-between-static-func-and-class-func-in-swift I think this is the same thing. – Vasily Bodnarchuk Nov 22 '16 at 19:29
  • thanks for that. What a frigging contrived, mouthful of marbles mess that is. I hope I never need to think about this again. – Confused Nov 22 '16 at 19:34
  • Well, the one about the difference between class func and static func, yes. I'm still trying to figure out how this answer solves the problem of being able to pass references to these booleans around. – Confused Nov 22 '16 at 19:36
  • Can I ask, how do I pass a reference to this boolean variable? I simply cannot see how. Sorry. I'm stupid when it comes to this kind of thing. – Confused Nov 22 '16 at 19:41
  • Why do you pass a pointer? From any part of the program you can write the following code: GameManager.previewAudioIsON = true or if GameManager.previewAudioIsON {....} – Vasily Bodnarchuk Nov 22 '16 at 19:44
  • Because I'm creating instances of a Buttons class that know nothing of these booleans, yet want to know about them... so I pass them their state variable to control/use. – Confused Nov 22 '16 at 19:47
  • Here is the first part of this saga: http://stackoverflow.com/questions/40710813/is-a-static-boolean-a-reference-type-in-swift – Confused Nov 22 '16 at 19:48
  • The Buttons class is a generic factory to make buttons. It doesn't have any unique knowledge of the different kinds of buttons and their states. That's why I'm trying to pass a reference to the state into the button, so that it can update itself, which then updates the state across the whole game world. Which means your answer update here: class `AnotherClass { var previewAudioIsON:Bool {` is not possible because I'd have to make a maker Class for every conceivable button to use this the states in this way. – Confused Nov 22 '16 at 20:16
  • I'm not sure this is normal thinking, to have a factory that makes buttons (which are actually switches, since they only have on or off) and for there to be a lot of them, and that they be different available buttons for different modes of the game. But that's the weird situation I'm in... sorry. I know this is probably both a weird way to try do something like this, and an unusual situation. – Confused Nov 22 '16 at 20:18
  • Ok. You want to create buttons factory. it is clear. But I can not understand what will be inside each button – Vasily Bodnarchuk Nov 22 '16 at 20:46
  • Each button is a unique switch. For this example, imagine four: one each for visuals, audio, a timer display and a quickstart button option. Each is either on or off. And depending on whether they're on or off determines what's loaded and how the game mode is played. Because the button class doesn't know about these specific modes, it's in need of a variable to be passed to it that defines what each instance of a button controls. – Confused Nov 22 '16 at 20:51
  • So. E.g. we have button1 which has var previewAudioIsON: Bool, button2 - var previewVisuaIsOn: Bool = false, and so on. Right? – Vasily Bodnarchuk Nov 22 '16 at 20:55
  • Yes, but because these buttons are coming from a factory, they don't have these variables in their class definition, they'll need that passed to them from whatever is requesting that the buttons be made for these purposes. – Confused Nov 22 '16 at 21:48