How to perform class nil checks - swift

I have a class in Swift:
class myClass {
var theBool : Bool
init(theBool: Bool) {
self.theBool = theBool
}
init() {
self.theBool = false
}
}
Elsewhere in my code, I have this check:
classist = myClass()
if let daBool = someRandomBool {
classist.theBool = daBool
}
I want to know where to insert this check into the Class.

Simple solution: Declare the (required) init method with an optional parameter type and perform the check there
class MyClass {
var theBool : Bool
init(bool: Bool?) {
self.theBool = bool ?? false
}
}
let someRandomBool : Bool? = true
let classist = MyClass(bool: someRandomBool)
or – a bit different but still simpler – with a struct
struct MyStruct {
var theBool : Bool
}
let someRandomBool : Bool? = true
let classist = MyStruct(theBool: someRandomBool ?? false)

Related

init class from another class swift

I have this ScreenSecurityWorker
final class ScreenSecurityWorker {
weak var delegate: ScreenSecurityWorkerDelegate?
private var isPassPhraseOn: Bool { return SettingsManager.shared.load(.passPhrase) }
private var isPassPhraseForced: Bool { return environment.forcePassPhraseEnabled }
var screenSecurityEnabled = false
inside my Mainrouter I am changing screenSecurityEnabled bool value to true at activateScreenSecurity
func activateScreenSecurity() {
guard !screenSecurityWorker.passwordSecurityInProgress else { return }
screenSecurityVC = ScreenSecurityBuiler.make()
app.dismissKeyboardOnTopVC()
app.window.rootViewController = screenSecurityVC
screenSecurityWorker.passPhareSuccess = false
screenSecurityWorker.screenSecurityEnabled = true
}
I am trying to reach to screenSecurityEnabled from ChatVC
but if I init it as
let screenSecurityWorker = ScreenSecurityWorker()
it has no values inside at all.
if I try like this it gives error
let screenSecurityWorker : ScreenSecurityWorker?
init(screenSecurityWorker: ScreenSecurityWorker){
self.screenSecurityWorker = screenSecurityWorker
}
I need this screenSecurityWorker.screenSecurityEnabled to change subviews in this function inside ChatVC
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if screenSecurityWorker!.screenSecurityEnabled {
let place = chatTextAreaContainerView.bounds.height + CGFloat(lastContentOffset ?? collectionView.contentOffset.y - chatTextAreaContainerView.bounds.height)
self.collectionView.contentOffset.y = place
screenSecurityWorker!.screenSecurityEnabled = false
}
}

How to toggle a boolean value using timer in Swift

I have a boolean called 'isMatched'. It is written in my Model. I use this boolean to show a view on a certain state of the view. However, I want the view to get hidden automatically after 0.5 second. I tried to use DispatchQueue.main.asyncAfter and also Timer, but always got error "Escaping closure captures mutating 'self' parameter". I have copied my Model below. Please advice me a solution.
I made the boolean var 'isMatched' true in the 'choose()' function.
import Foundation
struct WordMatchingGameModel<CardContent> {
private(set) var cards: Array<Card>
private(set) var words: Array<Word>
private(set) var gameDataSet: Array<String>
private(set) var matchedWord: String = ""
var isMatched: Bool = false
private var colors: [[String]] = [["AeroBlue", "AeroBlue"], ["BlueBell", "BlueBell"], ["PinkLavender", "PinkLavender"], ["Opal", "Opal"], ["CornflowerBlue", "CornflowerBlue"]]
mutating func choose(card: Card) {
if let choosenIndex = cards.firstIndex(matching: card) {
if !cards[choosenIndex].isTapped {
cards[choosenIndex].isTapped = true
cards[choosenIndex].bgColors = numberOfMatchedWords == 0 ? colors[0] : numberOfMatchedWords == 1 ? colors[1] : colors[2]
words.append(Word(id: cards[choosenIndex].id, content: cards[choosenIndex].content))
print(word)
if match() {
for index in 0..<cards.count {
if cards[index].isTapped { cards[index].isDisabled = true }
}
numberOfMatchedWords += 1
score += 10
matchedWord = word
isMatched = true
delay(interval: 0.5) {
self.isMatched = false
}
words.removeAll()
}
} else {
cards[choosenIndex].isTapped = false
cards[choosenIndex].bgColors = ["GradientEnd", "GradientStart"]
var tempWords = Array<Word>()
for index in 0..<words.count {
if words[index].id != cards[choosenIndex].id { tempWords.append(words[index]) }
}
words = tempWords
}
}
}
func delay(interval: TimeInterval, closure: #escaping () -> Void) {
DispatchQueue.main.asyncAfter(deadline: .now() + interval, execute: closure)
}
func match() -> Bool {
for index in 0..<gameDataSet.count {
if gameDataSet[index] == word {
return true
}
}
return false
}
var word: String {
var array = Array<Character>()
for index in 0..<words.count {
array.append(words[index].content as! Character)
}
return String(array).capitalized
}
private(set) var numberOfMatchedWords: Int = 0
private(set) var score: Int = 0
init(numberOfCards: Int, gameDataSet: Array<String>, cardContentFactory: (Int) -> CardContent) {
cards = Array<Card>()
words = Array<Word>()
self.gameDataSet = gameDataSet
for index in 0..<numberOfCards {
let content = cardContentFactory(index)
self.cards.append(Card(id: index + 1, content: content))
}
cards.shuffle()
colors.shuffle()
}
struct Card: Identifiable {
var id: Int
var content: CardContent
var bgColors: [String] = ["GradientEnd", "GradientStart"]
var isTapped: Bool = false
var isDisabled: Bool = false
}
struct Word: Identifiable {
var id: Int
var content: CardContent
}
}
Create a reference for self inside the function and use that instant of self inside the delay function.
mutating func choose(card: Card) {
var createReference = self
....................
delay(interval: 0.5) {
createReference.isMatched = false
}
}

Realm Swift problem to change property value

I implement this class and save Custom class object to realm but i not need to save in database isDataShow property. Problem is when i set isDataShow = true and get isDataShow method return false(getShowData always return false). I cant set isDataShow on true in local. What is problem?
class CustomClass : Object, Decodable
{
#objc dynamic var id : String? = nil
#objc dynamic var position : Int = 0
var isDataShow : Bool? = false
}
func getShowData() -> Bool {
return isDataShow!
}
func setShowData(show: Bool)
{
self.isDataShow = show
}

Can a Swift Property Wrapper reference the owner of the property its wrapping?

From within a property wrapper in Swift, can you someone refer back to the instance of the class or struck that owns the property being wrapped? Using self doesn't obviously work, nor does super.
I tried to pass in self to the property wrapper's init() but that doesn't work either because self on Configuration is not yet defined when #propertywrapper is evaluated.
My use case is in a class for managing a large number of settings or configurations. If any property is changed, I just want to notify interested parties that something changed. They don't really need to know which value just, so use something like KVO or a Publisher for each property isn't really necessary.
A property wrapper looks ideal, but I can't figure out how to pass in some sort of reference to the owning instance that the wrapper can call back to.
References:
SE-0258
enum PropertyIdentifier {
case backgroundColor
case textColor
}
#propertyWrapper
struct Recorded<T> {
let identifier:PropertyIdentifier
var _value: T
init(_ identifier:PropertyIdentifier, defaultValue: T) {
self.identifier = identifier
self._value = defaultValue
}
var value: T {
get { _value }
set {
_value = newValue
// How to callback to Configuration.propertyWasSet()?
//
// [self/super/...].propertyWasSet(identifier)
}
}
}
struct Configuration {
#Recorded(.backgroundColor, defaultValue:NSColor.white)
var backgroundColor:NSColor
#Recorded(.textColor, defaultValue:NSColor.black)
var textColor:NSColor
func propertyWasSet(_ identifier:PropertyIdentifier) {
// Do something...
}
}
The answer is no, it's not possible with the current specification.
I wanted to do something similar. The best I could come up with was to use reflection in a function at the end of init(...). At least this way you can annotate your types and only add a single function call in init().
fileprivate protocol BindableObjectPropertySettable {
var didSet: () -> Void { get set }
}
#propertyDelegate
class BindableObjectProperty<T>: BindableObjectPropertySettable {
var value: T {
didSet {
self.didSet()
}
}
var didSet: () -> Void = { }
init(initialValue: T) {
self.value = initialValue
}
}
extension BindableObject {
// Call this at the end of init() after calling super
func bindProperties(_ didSet: #escaping () -> Void) {
let mirror = Mirror(reflecting: self)
for child in mirror.children {
if var child = child.value as? BindableObjectPropertySettable {
child.didSet = didSet
}
}
}
}
You cannot do this out of the box currently.
However, the proposal you refer to discusses this as a future direction in the latest version:
https://github.com/apple/swift-evolution/blob/master/proposals/0258-property-wrappers.md#referencing-the-enclosing-self-in-a-wrapper-type
For now, you would be able to use a projectedValue to assign self to.
You could then use that to trigger some action after setting the wrappedValue.
As an example:
import Foundation
#propertyWrapper
class Wrapper {
let name : String
var value = 0
weak var owner : Owner?
init(_ name: String) {
self.name = name
}
var wrappedValue : Int {
get { value }
set {
value = 0
owner?.wrapperDidSet(name: name)
}
}
var projectedValue : Wrapper {
self
}
}
class Owner {
#Wrapper("a") var a : Int
#Wrapper("b") var b : Int
init() {
$a.owner = self
$b.owner = self
}
func wrapperDidSet(name: String) {
print("WrapperDidSet(\(name))")
}
}
var owner = Owner()
owner.a = 4 // Prints: WrapperDidSet(a)
My experiments based on : https://github.com/apple/swift-evolution/blob/master/proposals/0258-property-wrappers.md#referencing-the-enclosing-self-in-a-wrapper-type
protocol Observer: AnyObject {
func observableValueDidChange<T>(newValue: T)
}
#propertyWrapper
public struct Observable<T: Equatable> {
public var stored: T
weak var observer: Observer?
init(wrappedValue: T, observer: Observer?) {
self.stored = wrappedValue
}
public var wrappedValue: T {
get { return stored }
set {
if newValue != stored {
observer?.observableValueDidChange(newValue: newValue)
}
stored = newValue
}
}
}
class testClass: Observer {
#Observable(observer: nil) var some: Int = 2
func observableValueDidChange<T>(newValue: T) {
print("lol")
}
init(){
_some.observer = self
}
}
let a = testClass()
a.some = 4
a.some = 6
The answer is yes! See this answer
Example code for calling ObservableObject publisher with a UserDefaults wrapper:
import Combine
import Foundation
class LocalSettings: ObservableObject {
static var shared = LocalSettings()
#Setting(key: "TabSelection")
var tabSelection: Int = 0
}
#propertyWrapper
struct Setting<T> {
private let key: String
private let defaultValue: T
init(wrappedValue value: T, key: String) {
self.key = key
self.defaultValue = value
}
var wrappedValue: T {
get {
UserDefaults.standard.object(forKey: key) as? T ?? defaultValue
}
set {
UserDefaults.standard.set(newValue, forKey: key)
}
}
public static subscript<EnclosingSelf: ObservableObject>(
_enclosingInstance object: EnclosingSelf,
wrapped wrappedKeyPath: ReferenceWritableKeyPath<EnclosingSelf, T>,
storage storageKeyPath: ReferenceWritableKeyPath<EnclosingSelf, Setting<T>>
) -> T {
get {
return object[keyPath: storageKeyPath].wrappedValue
}
set {
(object.objectWillChange as? ObservableObjectPublisher)?.send()
UserDefaults.standard.set(newValue, forKey: object[keyPath: storageKeyPath].key)
}
}
}

How to pass a reference to a Boolean rather than its value?

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
}
}
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
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