.fullScreenCover 始终打开相同的详细信息页面

Posted

技术标签:

【中文标题】.fullScreenCover 始终打开相同的详细信息页面【英文标题】:.fullScreenCover always opening same Detail Page 【发布时间】:2021-02-08 17:19:40 【问题描述】:

所以我在这里遇到了一些问题,我希望很容易解决,只是目前无法解决。我正在通过一些CoreData信息(帖子)循环并返回图像网格,我希望能够单击这些图像并打开DetailView的fullScreenCover,其中包含正确的信息。使用当前代码,DetailView 始终显示第一篇文章中的数据。如果我将它从 Button 更改为 NavigationLink NavigationLink(destination: DetailView(post: post)),正如代码中注释的那样,它可以完美运行,但不会给我想要的 fullScreenCover 行为。我在这里做错了什么?提前致谢!

@FetchRequest(entity: Post.entity(), sortDescriptors: []) var posts: FetchedResults<Post>

enum ActiveSheet: Identifiable 
        case detail, addNew
        
        var id: Int 
            hashValue
        
    
@State var activeSheet: ActiveSheet?

var body: some View 

ForEach(posts.reversed(), id: \.self)  post in
    
    VStack 
    Button(action:  activeSheet = .detail )
    //NavigationLink(destination: DetailView(post: post))
    ZStack 
    Image(uiImage: UIImage(data: post.mainImage ?? self.image)!)
        VStack 
        Text("\(post.title)")
        Text("\(post.desc)")
        
    

.fullScreenCover(item: $activeSheet)  item in
            switch item 
            case .detail:
                DetailView(post: post)
            case .addNew:
                AddNewView()
            
        



【问题讨论】:

最好避免在 .sheet 和 .fullScreenCover 闭包中使用任何条件逻辑。这里的解决方案:***.com/questions/65416673/… 【参考方案1】:

我暂时将帖子数组设为静态而不是来自 Core Data 并模拟对象/结构以便我可以轻松测试,但主体应该保持不变:

struct ContentView : View 
    //@FetchRequest(entity: Post.entity(), sortDescriptors: []) var posts: FetchedResults<Post>
    var posts : [Post] = [Post(title: "1", desc: "desc1"),
                          Post(title: "2", desc: "desc2"),
                          Post(title: "3", desc: "desc3")]
    
    enum ActiveSheet: Identifiable 
        case detail(post: Post)
        case addNew
        
        var id: UUID 
            switch self 
            case .detail(let post):
                return post.id
            default:
                return UUID()
            
        
    
    @State var activeSheet: ActiveSheet?
    
    var body: some View 
        
        ForEach(posts.reversed(), id: \.self)  post in
            
            VStack 
                Button(action:  activeSheet = .detail(post: post) )
                    ZStack 
                        //Image(uiImage: UIImage(data: post.mainImage ?? self.image)!)
                        VStack 
                            Text("\(post.title)")
                            Text("\(post.desc)")
                        
                    
                
            
            .fullScreenCover(item: $activeSheet)  item in
                switch item 
                case .detail(let post):
                    DetailView(post: post)
                case .addNew:
                    AddNewView()
                
            
        
    


struct DetailView : View 
    var post: Post
    
    var body : some View 
        Text("Detail \(post.id)")
    


struct AddNewView : View 
    var body : some View 
        Text("add")
    


struct Post : Hashable 
    var id = UUID()
    var title : String
    var desc : String

基本思想是,与其在第一次渲染时创建fullScreenCover,不如根据activeSheet 创建它,以便动态创建它。您已经使用item:activeSheet 走在了正确的轨道上——问题是它与实际帖子无关,因为您只是使用按钮设置activeSheet = .detail

我已向case detail 添加了一个关联属性,可让您实际将帖子与其关联。然后,在fullScreenCover 中,您可以看到我在创建DetailView 时使用了该关联值。

您可能需要稍作调整以适应您的 Post 模型,但概念将保持不变。

【讨论】:

以上是关于.fullScreenCover 始终打开相同的详细信息页面的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI 中的透明和模糊 fullScreenCover 模态?

如何在 IOS14 的 .fullScreenCover 下使用参数初始化内容

如何在 iOS 14 中使用 fullScreenCover,但在 13 中使用工作表

SwiftUI:在没有动画的情况下显示 fullScreenCover [关闭]

React Modal始终使用一行中的相同记录

始终将屏幕截图保存在“照片”中相同的自定义名称应用相册中