Swift, значение не обновлено

в файле Maze.swift у меня есть:

var myMaze = Maze() // -> 9.0

определение структуры Maze со следующим содержимым:

@State var widthDouble = 9.0

и метод init()

init() {
print("Maze init:", self.widthDouble) }

В файле ContentView.swift у меня есть следующее:

@State var widthDouble = myMaze.widthDouble
Slider(value: $widthDouble, in: 3...33, step: 1) // updated to 16.0
Button(action: { action() }) { Text("Build maze with updated values") }

и, наконец, функция action()

func action() {
myMaze.widthDouble = widthDouble
print("ContentView: ", widthDouble) // -> 16.0
print("ContentView (myMaze.): ", myMaze.widthDouble) // -> 9.0
myMaze = .init() }

Хотя в func action() myMaze.widthDouble присваивается значение widthDouble (16.0), значение myMaze.widthDouble не обновляется и по-прежнему равно 9.0!

Вывод инициализации(): Инициализация лабиринта: 9.0

Значение 9.0 обновлено до 16.0 в ползунке.

Вывод действия(): КонтентВью: 16.0 ContentView (мой лабиринт): 9.0

Вывод инициализации(): Инициализация лабиринта: 9.0

Может кто-нибудь сказать мне, что не так и почему myMaze.widthDouble не обновляется?

Файл ContentView.swift

//
//  ContentView.swift
//  Maze
//
//  Created by Philippe Lagarrigue on 24/12/2020.
//

import SwiftUI

struct ContentView: View {
    @State private var selectedTab = 0
    
    let numTabs = 2
    let minDragTranslationForSwipe: CGFloat = 50
    
    var body: some View {
        TabView(selection: $selectedTab){
            NavigationView{
                MenuView()
                .navigationBarTitle("Settings")
            }
            .tabItem {
                Image("map")
                Text("Map")
            }.tag(0)
             .highPriorityGesture(DragGesture().onEnded({
                 self.handleSwipe(translation: $0.translation.width)
             }))
            NavigationView{
                MenuView()
                .navigationBarTitle("Settings")
            }
            .tabItem {
                Image("navigation")
                Text("Navigation")
            }.tag(1)
             .highPriorityGesture(DragGesture().onEnded({
                 self.handleSwipe(translation: $0.translation.width)
             }))
        }
    }
    
    private func handleSwipe(translation: CGFloat) {
        if translation > minDragTranslationForSwipe && selectedTab > 0 {
            selectedTab -= 1
        } else  if translation < -minDragTranslationForSwipe && selectedTab < numTabs-1 {
            selectedTab += 1
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

struct MenuView : View {
    @State var widthDouble = myMaze.widthDouble
    @State var heightDouble = myMaze.heightDouble
    @State var oneWay = myMaze.oneWay
    @State private var isEditing1 = false
    @State private var isEditing2 = false
    //@Environment(\.presentationMode) var mode: Binding<PresentationMode>
    var body : some View {
        HStack(alignment: VerticalAlignment.top) {
            VStack(alignment: .leading) {
                Text("Number of rooms (horizontally): \(widthDouble, specifier: "%.0f")")
                    .foregroundColor(isEditing1 ? .red : .black)
                Slider(value: $widthDouble, in: 3...33, step: 1,
                       onEditingChanged: { editing in isEditing1 = editing })
                Divider()
                // format: "Angle: %.0f", angle
                Text("Number of rooms (vertically): \(heightDouble, specifier: "%.0f")")
                    .foregroundColor(isEditing2 ? .red : .black)
                Slider(value: $heightDouble, in: 3...33, step: 1,
                       onEditingChanged: { editing in isEditing2 = editing })
                Divider()
                Toggle("One way", isOn: $oneWay)
                Button(action: { action() }) { Text("Build maze with updated values") }
            } .padding()
        }
    }
    func action() {
        myMaze.widthDouble = widthDouble
        myMaze.heightDouble = heightDouble
        print("ContentView: ", widthDouble, heightDouble)
        print("ContentView (myMaze.): ", myMaze.widthDouble, myMaze.heightDouble)
        myMaze = .init()
    }
}

Файл Maze.swift

//
//  Maze.swift
//  NewMaze
//
//  Created by Philippe Lagarrigue on 23/12/2020.
//

import Foundation
import SwiftUI

let wall = (North: 1, East: 2, South: 4, West: 8) // 15 means all walls
let exit = (toNorth: 16, toEast: 32, toSouth: 64, toWest: 128) // 0 means no exit
var myMaze = Maze()

struct Room {
    var x: Int
    var y: Int
    var roomsToExit: Int
}

struct Maze {
    // Properties
    var width = 9
    var height = 12
    var widthDouble = 9.0
    var heightDouble = 12.0
    var oneWay = true
    var exitRoom = Room(x: 0, y: 0, roomsToExit: 0)
    var farestRoom = Room(x: 0, y: 0, roomsToExit: 0)
    var mazeData = [[Int]]()
    var numberOfRooms: Int { return self.width * self.height }
    
    // Methods
    init() {
        //print(self.widthDouble, self.heightDouble)
        self.width = Int(self.widthDouble)
        self.height = Int(self.heightDouble)
        mazeData = Array(repeating: Array(repeating: 15, count: height), count: width)
        print("Maze init:", self.width, "x", self.height)
    }
}

@State следует использовать только в представлениях для свойств, обновленных в компоненте пользовательского интерфейса, поэтому вам не следует использовать его в модели (?), Такой как Maze. Кроме этого, я должен сказать, что очень трудно понять, что вы пытаетесь сделать.

Joakim Danielson 26.12.2020 15:03

Спасибо за ответ, но не могли бы вы сказать мне, как я могу обновить свое значение <myMaze.widthDouble> вне структуры?

Swiftiti 26.12.2020 15:07

@Swiftiti удалите @State из var widthDouble = 9.0 в вашем struct Maze , и он будет работать (Проверено)

Ouail Bellal 26.12.2020 15:09

Я только что удалил состояние и смог скомпилировать без ошибок, но значение <myMaze.widthDouble> все еще не обновлено!

Swiftiti 26.12.2020 15:18

Немного странно, что вы вызываете init() для вашей переменной лабиринта после того, как вы обновили свойство. Мне кажется, вам нужно два типа: одна модель лабиринта и один строитель лабиринта, скажем, Maze и MazeBuilder. Я бы посоветовал изучить ObservableObject и @Published и использовать их для своего класса строителя.

Joakim Danielson 26.12.2020 15:19
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
5
108
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий
  • @State используется для изменений внутри поля зрения
  • @ObservedObject используется для хранения ObservableObject.
  • @Published публикует, когда @Published var изменяется.

с этим знанием, вот ответ.

import SwiftUI

struct ContentView: View {
    @State private var selectedTab = 0
    
    let numTabs = 2
    let minDragTranslationForSwipe: CGFloat = 50
    
    var body: some View {
        TabView(selection: $selectedTab){
            NavigationView{
                MenuView()
                .navigationBarTitle("Settings")
            }
            .tabItem {
                Image("map")
                Text("Map")
            }.tag(0)
             .highPriorityGesture(DragGesture().onEnded({
                 self.handleSwipe(translation: $0.translation.width)
             }))
            NavigationView{
                MenuView()
                .navigationBarTitle("Settings")
            }
            .tabItem {
                Image("navigation")
                Text("Navigation")
            }.tag(1)
             .highPriorityGesture(DragGesture().onEnded({
                 self.handleSwipe(translation: $0.translation.width)
             }))
        }
    }
    
    private func handleSwipe(translation: CGFloat) {
        if translation > minDragTranslationForSwipe && selectedTab > 0 {
            selectedTab -= 1
        } else  if translation < -minDragTranslationForSwipe && selectedTab < numTabs-1 {
            selectedTab += 1
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

struct MenuView : View {
    @ObservedObject var myMaze = Maze()
    @State private var isEditing1 = false
    @State private var isEditing2 = false
    //@Environment(\.presentationMode) var mode: Binding<PresentationMode>
    var body : some View {
        HStack(alignment: VerticalAlignment.top) {
            VStack(alignment: .leading) {
                Text("Number of rooms (horizontally): \(myMaze.widthDouble, specifier: "%.0f")")
                    .foregroundColor(isEditing1 ? .red : .black)
                Slider(value: $myMaze.widthDouble, in: 3...33, step: 1,
                       onEditingChanged: { editing in isEditing1 = editing })
                Divider()
                // format: "Angle: %.0f", angle
                Text("Number of rooms (vertically): \(myMaze.heightDouble, specifier: "%.0f")")
                    .foregroundColor(isEditing2 ? .red : .black)
                Slider(value: $myMaze.heightDouble, in: 3...33, step: 1,
                       onEditingChanged: { editing in isEditing2 = editing })
                Divider()
                Toggle("One way", isOn: $myMaze.oneWay)
                Button(action: { action() }) { Text("Build maze with updated values") }
            } .padding()
        }
    }
    func action() {
        
    }
}

import Foundation
import SwiftUI

let wall = (North: 1, East: 2, South: 4, West: 8) // 15 means all walls
let exit = (toNorth: 16, toEast: 32, toSouth: 64, toWest: 128) // 0 means no exit


struct Room {
    var x: Int
    var y: Int
    var roomsToExit: Int
}

class Maze: ObservableObject {
 
    @Published var height = 12
    
    
    @Published var widthDouble = 9.0 {
        didSet {
            setMezData(height: Int(heightDouble), width: Int(widthDouble))
        }
    }
    @Published var heightDouble = 12.0 {
        didSet {
            setMezData(height: Int(heightDouble), width: Int(widthDouble))
        }
    }
    
    @Published var oneWay = true
    @Published var exitRoom = Room(x: 0, y: 0, roomsToExit: 0)
    @Published var farestRoom = Room(x: 0, y: 0, roomsToExit: 0)
    @Published var mazeData = [[Int]]() {
        didSet {
            print(mazeData)
        }
    }
    var numberOfRooms: Int { return Int(heightDouble) * Int(widthDouble) }
    
    func setMezData(height: Int, width: Int) {
        mazeData = Array(repeating: Array(repeating: 15, count: height), count: width)
    }
   
}

Спасибо, я обновил все, как было предложено, и не получил никаких ошибок, но массив mazeData не обновляется новыми значениями, не могли бы вы сказать мне, как я могу его обновить? Наличие < myMaze = .init() > в func action() дает мне следующую ошибку: Невозможно назначить свойство: «я» неизменяемо

Swiftiti 26.12.2020 16:25

Большое спасибо всем вам, теперь все работает, как и ожидалось, и я многому научился!

Swiftiti 26.12.2020 18:32

Где найти эту галочку?

Swiftiti 27.12.2020 11:03

@Swiftiti meta.stackexchange.com/questions/5234/…

YodagamaHeshan 27.12.2020 11:18

с вашей помощью я наконец нашел способ получить доступ к классу из других классов.

// MyClass definition
class MyClass: ObservableObject {
    static let sharedInstance = MyClass()
    var myProperty = "Something"
    ...
}

// A struct where I need to use MyClass
struct MyView1 : View {
    @ObservedObject var ClassInst = MyClass.sharedInstance
    ...
    ClassInst.myProperty = "Something else"
}

// Another struct where I need to use MyClass
struct MyView2 : View {
    @ObservedObject var ClassInst = MyClass.sharedInstance
    ...
    ClassInst.myProperty = "Nothing"
}

Другие вопросы по теме