Как мне создать глобальную переменную счетчика баллов в SwiftUI

#swiftui #global-variables

#swiftui #глобальные переменные

Вопрос:

Я новичок в программировании, так что потерпите меня здесь.

Я пытаюсь создать набор изображений, которые выполняют две вещи, когда пользователь нажимает на них:

  1. Измените изображение
  2. Добавьте или вычтите их оценку в зависимости от используемого изображения

Часть изменения изображения работает нормально. Я борюсь с функцией добавления / вычитания.

Оба изображения создаются из структуры и требуют изменения одной и той же переменной. Поэтому, если ни одно изображение не задействовано, оценка должна быть равна нулю. Если задействовано два, оценка должна быть равна двум. Если один из них снова будет задействован, оценка снизится до 1. По сути, он подсчитывает количество изображений, которые в данный момент прослушиваются, и отображает версию изображения «x».

Я попытался создать ObservableObject и EnvironmentObject, используя несколько разных руководств в качестве руководств, и, похоже, я просто не могу заставить их работать.

Вот мой код:

 import SwiftUI
import Combine

class ScoreCounter: ObservableObject {
    @Published var redCounter: Int = 0
    //var yellowCounter: Int = 0
    //var greenCounter: Int = 0
    //var blueCounter: Int = 0
}

struct ContentView: View {
       
    var body: some View {
        
        //MARK - Red Button Stack
        
        HStack {
            
            NumberView(currentImage: "2red", imageName: "2red", xImageName: "2Xred")
            NumberView(currentImage: "3red", imageName: "3red", xImageName: "3Xred")
            
        }
    }
}


struct NumberView: View {
    
    @EnvironmentObject var redScoreCounter: ScoreCounter
    @State var currentImage: String
    @State var imageName: String
    @State var xImageName: String
    
    var body: some View {
        Button(action: {
            self.currentImage = self.currentImage == imageName ? xImageName : imageName

            if currentImage == xImageName {
                ScoreCounter.redScoreCounter  = 1
            } else {
                ScoreCounter.redScoreCounter -= 1
            }
            print(ScoreCounter.redScoreCounter)
            
        }) {
            Image(currentImage)
        }

    }
}
  

И в SceneDelegate:

 import UIKit
import SwiftUI
import Combine

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?
    
    var redScoreCounter = ScoreCounter()
  

Ответ №1:

Вам нужно нажать EnvironmentObject на ваши подвиды внутри вашего SceneDelegate . Важной частью является вызов .environmentObject(redScoreCounter) вашего ContentView .

 import UIKit
import SwiftUI
import Combine

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?
    
    var redScoreCounter = ScoreCounter()

        // Create the SwiftUI view that provides the window contents.
        let contentView = ContentView()
            .environmentObject(redScoreCounter)

        // Use a UIHostingController as window root view controller.
        if let windowScene = scene as? UIWindowScene {
            let window = UIWindow(windowScene: windowScene)
            window.rootViewController = UIHostingController(rootView: contentView)
            self.window = window
            window.makeKeyAndVisible()
        }
    ...
  

Комментарии:

1. Спасибо, это заполняет пробел. Как мне затем изменить переменную redScoreCounter в структуре NumberView? И будет ли она содержать это значение, если оно будет изменено другим экземпляром структуры NumberView?

2. EnvironmentObject вводится в ваш NumberView, и существует только один его экземпляр. (Экземпляр, определенный внутри вашего SceneDelegate) Если вы измените значение внутри вашего EnvironmentObject и это значение будет опубликовано (@Published), каждое представление, использующее EnvironmentObject, будет перерисовано. Поэтому EnvironmentObject синхронизируется между вашими представлениями.