SwiftUI 在一种情况下而不是另一种情况下查看层次结构警告

Posted

技术标签:

【中文标题】SwiftUI 在一种情况下而不是另一种情况下查看层次结构警告【英文标题】:SwiftUI View Hierarchy Warning in One Case and Not Another 【发布时间】:2020-02-03 06:55:03 【问题描述】:

我最初制作了一个 SwiftUI 列表/详细信息应用程序,其中包含一个 TabView,其中一个选项卡作为添加新记录的视图。这和预期的差不多。我想将选项卡中的添加功能更改为从导航栏按钮调用。在这两种情况下,我都使用完全相同的视图。当从导航栏按钮调用视图时,我得到 tableView 层次结构错误:

[TableView] 仅警告一次:UITableView 被告知布局其可见单元格和 不在视图层次结构中的其他内容(表视图或其之一 superviews 还没有被添加到窗口中)....+ 更多的喋喋不休

TabView 调用:

AddNewPatient().tabItem (
    Image(systemName: "plus.circle")
    Text("Add")
)
.tag(2)

以及导航按钮调用:

.navigationBarItems(trailing: NavigationLink(destination: AddNewPatient()) 
    Text("Add Patient")
)      

我很困惑为什么从导航栏按钮调用视图时视图超出层次结构。到目前为止,我还没有遇到过应用程序崩溃,但显然应用程序不开心。数据确实已保存并显示在列表中。 (核心数据存储)

我在 UITableViewAlertForLayoutOutsideViewHierarchy 设置了一个符号断点,但我所有的 可以收集到相同的数据 - 在视图层次结构之外。

Xcode 11.1 (11A1027) ios 13.1.2

任何指导将不胜感激。

AddNewPatient 视图:

import SwiftUI
import CoreData

struct AddNewPatient: View 
    
    @Environment(\.managedObjectContext) var managedObjectContext
    @Environment(\.presentationMode) var presentationMode
        
    @State private var updatedTitle: String = "No Title"
    @State private var updatedFirstName: String = "No First Name"
    //more properties
    
    @State var photos: [UIImage] = [UIImage]()
    @State private var showImagePicker: Bool = false
    
    var bImage: Image = Image("InventoryThinBlueWithCamera")

    var body: some View 
        NavigationView 
            ScrollView 
            VStack 
                if photos.count > 0 
                    Image(uiImage: photos[photos.count - 1])
                        .resizable()
                        .frame(width: 320, height: 320)
                        .aspectRatio(contentMode: .fit)
                        .cornerRadius(12)
                 else 
                    bImage
                

                VStack 
                Button("Take Photo") 
                    self.showImagePicker = true
                
                .padding()
                .background(Color.green)
                .foregroundColor(.white)
                .cornerRadius(12)
                //.disabled(!showAlert)
                
                .sheet(isPresented: self.$showImagePicker) 
                    PhotoCaptureView(photos: self.$photos)
                

                VStack(alignment: .leading) 
                    Text("Patient Title:")
                        .padding(.leading, 5)
                        .font(.headline)
                    TextField("Enter a Title", text: $updatedTitle)
                        .onAppear 
                            self.updatedTitle = ""
                    
                    .textFieldStyle(RoundedBorderTextFieldStyle())
                
                .padding(10)
                
                
                VStack(alignment: .leading) 
                    Text("First Name:")
                        .padding(.leading, 5)
                        .font(.headline)
                    TextField("Enter First Name", text: $updatedFirstName)
                        .onAppear 
                            self.updatedFirstName = ""
                    
                    .textFieldStyle(RoundedBorderTextFieldStyle())
                
                .padding(10)
                
                //bunch more fields
                

                
                Spacer()
            
        //ScrollView
        .navigationBarTitle("Add New Patient", displayMode: .inline)
        .padding(.top, 50)
        .navigationBarItems(trailing:  Button(action: (
                    
            let nmo = Patient(context: self.managedObjectContext)
            var chosenImageData : Data?

            if self.photos.count > 0 
                let theImage = self.photos[self.photos.count - 1]
                
                let rir = CRSReduceImageResolution()
                let temp = rir.resizeMyImageData(theImage, startSize: CGSize.zero, endSize: CGSize(width: 320, height: 240))
                chosenImageData = temp
                //chosenImageData = myImageData
                nmo.image = chosenImageData
            

            nmo.myID = UUID()
            nmo.title = self.updatedTitle
            nmo.firstName = self.updatedFirstName
            nmo.lastName = self.updatedLastName
            nmo.createdAt = Date()
            
            do 
                try self.managedObjectContext.save()
             catch 
                print(error)
            
                    
            self.photos = []
                    self.updatedTitle = ""
                    self.updatedFirstName = ""
                    //bunch more fields
                )) 
                    Text("Save")
                )
        //nav
    

【问题讨论】:

能否请您发布 AddNewPatient 视图的正文? 上面添加了AddNewPatient视图代码。 我看不到在视图代码中创建表格视图的位置。您没有列表。 这不是表格视图。这相当于 UIKit master/detail 中的详细视图。我从列表视图上的导航栏按钮调用此视图。 在那种情况下我不明白错误Warning once only: UITableView was told to layout its visible cells and other contents without being in the view hierarchy (the table view or one of its superviews has not been added to a window) 【参考方案1】:

我更改了尾随按钮调用以切换属性以显示添加患者表,然后调用一个函数来添加患者。这非常有效。

 .navigationBarTitle("Person")
 .sheet(isPresented: $showAddPatient) 
      AddNewPatient(photoStore: self.photoStore)
  

  .navigationBarItems(
       leading: EditButton(),
       trailing: Button(
           action: 
               withAnimation  self.showAddPatient.toggle() 
           
        ) 
          Image(systemName: "plus")
        

【讨论】:

以上是关于SwiftUI 在一种情况下而不是另一种情况下查看层次结构警告的主要内容,如果未能解决你的问题,请参考以下文章

为啥在一种情况下更改熊猫数据框列中的值很快,而在另一种情况下更改速度很慢?

为啥在一种情况下会收到带有字符串文字的不推荐使用的转换警告,而在另一种情况下却没有?

如何在一种情况下推送视图控制器,但在另一种情况下以模态方式呈现它?

为啥 PHP 在一种情况下允许将文字传递给按引用传递的参数,而在其他情况下不允许?

Swift 4:JSONDecoder 在一种特定情况下失败-“操作无法完成”[关闭]

SwiftUI:输入无效时文本字段抖动动画