You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI按钮点击后UI样式不更新问题求助

问题排查与解决方案

核心原因

你的问题大概率是因为**Book是值类型(struct)**,而SwiftUI的视图更新依赖于ObservableObject的@Published属性发出的变更通知。当你直接修改Book的isFavourite属性时:

  1. 由于struct是值类型,修改操作会创建一个新的Book副本,而非修改原数组中的实例
  2. 存储Book数组的EnvironmentObject(比如BookStore)的@Published数组并未检测到自身的引用变化,因此不会触发视图刷新

两种解决方案

方案1:将Book改为引用类型(class)并遵循ObservableObject

把Book从struct改成class,同时让它遵循ObservableObject,用@Published标记isFavourite属性,这样修改属性时会直接通知视图更新:

import SwiftUI

class Book: Identifiable, ObservableObject {
    let id = UUID()
    var title: String
    @Published var isFavourite: Bool
    
    init(title: String, isFavourite: Bool = false) {
        self.title = title
        self.isFavourite = isFavourite
    }
}

// 你的EnvironmentObject类(示例)
class BookStore: ObservableObject {
    @Published var books: [Book] = []
}

在BookPreviewView中,需要用@ObservedObject接收Book实例:

struct BookPreviewView: View {
    @ObservedObject var book: Book
    @EnvironmentObject var bookStore: BookStore
    
    var body: some View {
        Button(action: {
            book.isFavourite.toggle()
        }) {
            Image(systemName: book.isFavourite ? "star.fill" : "star")
                .foregroundColor(.yellow)
        }
    }
}

方案2:保持Book为struct,修改时替换数组中的整个元素

如果坚持使用struct,需要在修改isFavourite时,找到对应Book在数组中的索引,替换整个元素,让@Published数组检测到变化:

// 假设你的Book是struct
struct Book: Identifiable {
    let id = UUID()
    var title: String
    var isFavourite: Bool
}

class BookStore: ObservableObject {
    @Published var books: [Book] = []
}

// BookPreviewView中的按钮操作
struct BookPreviewView: View {
    var book: Book
    @EnvironmentObject var bookStore: BookStore
    
    var body: some View {
        Button(action: {
            // 找到book在数组中的索引并替换
            guard let index = bookStore.books.firstIndex(where: { $0.id == book.id }) else { return }
            var updatedBook = bookStore.books[index]
            updatedBook.isFavourite.toggle()
            bookStore.books[index] = updatedBook
        }) {
            Image(systemName: book.isFavourite ? "star.fill" : "star")
                .foregroundColor(.yellow)
        }
    }
}

额外注意事项

  • 确保你在SceneDelegate或App入口处正确注入了BookStore作为EnvironmentObject
  • 如果使用方案1,传递Book实例时要确保是同一个引用,避免意外拷贝

内容的提问来源于stack exchange,提问作者Gargantua01

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 16:27:35