在使用 SwiftUI 滚动包含约 1000 行的文本视图时出现性能问题。

huangapple go评论54阅读模式
英文:

Bad SwiftUI performance when scrolling a text view with ~1000 lines

问题

我创建了一个简单的 SwiftUI macOS 应用程序,允许用户导入文本文件,然后显示文本。当导入一个相当大的文本文件(1500行)时,在使用滚动条滚动后,视图会停顿几秒钟。使用分析器,我可以看到 CPU 使用率非常高,出现严重的停顿。有关可能导致这种情况的代码问题的想法吗?谢谢。

英文:

I've created a simple SwiftUI macOS app that allows users to import a text file and then displays the text. When importing a decently sized text file (1500 lines) the view will hang for several seconds after scrolling using the scrollbar. Using the profiler I can see the CPU usage is very high and has Severe Hangs. Any ideas the issue with my code that might be causing this? Thank you.

struct ContentView: View {
  private var loggingView = LoggingView()
  
  var body: some View {
    loggingView
  }
}

struct LoggingView: View {
  @StateObject private var model = LoggingModel()
  var body: some View {
    
    ScrollView {
      if model.data.isEmpty {
        Text("Add a file to begin.")
      } else {
        Text(model.data).frame(maxWidth: .infinity)
      }
    }
    .toolbar {
      ToolbarItem(placement: .principal) {
        Button(action: model.addFilePath) {
          Text("New File")
          Label("Import", systemImage: "square.and.arrow.down")
        }
      }
    }
  }
}

class LoggingModel: ObservableObject {
  @Published var data: String = ""
  
  func addFilePath() {
    let dialog = NSOpenPanel()
    dialog.title                   = "Choose a .txt file";
    dialog.allowedContentTypes     = [.text]
    
    if (dialog.runModal() == NSApplication.ModalResponse.OK) {
      let result = dialog.url // Pathname of the file
      
      guard let result else {
        return
      }
      
      load(file: result.path)
    }
  }
  
  func load(file: String) {
    do {
      let contents = try String(contentsOfFile: file)
      DispatchQueue.main.async {
        self.data = contents
      }
    } catch let error as NSError {
      print(error.localizedDescription)
    }
  }
}

答案1

得分: 2

你应该在ScrollView中使用LazyVStack,并修改你的代码如下以实现所需效果:

ScrollView {
    LazyVStack {
        // 这里放你的视图
    }
}

通过在ScrollView中使用LazyVStack

  • 你可以创建一个垂直增长的堆栈,仅在需要时生成项目。
  • 这种方法通过仅渲染屏幕上可见的项目来提高性能,特别是在处理大型数据集时。

如果你想要一个水平排列的堆栈,可以使用LazyHStack

类似地,还有LazyHGrid可用于类似网格的布局。

英文:

You should use LazyVStack in the ScrollView and modifier your code as follows to achieve the desired effect:

ScrollView {
    LazyVStack {
        // Your views here
    }
}

By using LazyVStack within the ScrollView:

  • You can create a vertically growing stack that generates items only as needed.
  • This approach improves performance by rendering only the visible items on the screen, especially when dealing with large data sets.

If you want a horizontally arranged stack, you can use LazyHStack instead.

Similarly, there is LazyHGrid available for grid-like layouts.

huangapple
  • 本文由 发表于 2023年6月19日 12:06:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/76503554.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定