gpt4 book ai didi

swift - 如何在 Swift 应用程序中创建一个最小的控制台(UILabel、UITextView、滚动、截头?)

转载 作者:行者123 更新时间:2023-11-28 06:12:07 24 4
gpt4 key购买 nike

我想在我的应用程序中创建一个控制台,以便在屏幕上显示事件或信息。它将以一个简单的字符串“等待新消息...”开始,当发生不同的事情时,新消息将添加到该字符串中。当控制台填满时,该字段将随着每次添加而滚动,以便用户始终在控制台底部看到最新的消息,而旧消息从顶部的 View 中消失。

“Truncate Head”和多行 UILabel 有办法吗?我试图先用 UILabel 来做这个,但我找不到始终查看字符串结尾的方法. Truncate head 实际上是逐行工作的,所以它会显示字符串的前五行,然后是最后可见行的尾部。我尝试了各种对齐和环绕设置,但没有任何效果……我是不是遗漏了什么?有没有办法让 UILabel 始终显示字符串的结尾并让内容从顶部消失?

每次都剪切字符串以适应?也许我可以将字符串剪切到最后一千个字符或类似的字符?但我不知道 UILabel 有多大(在不同的屏幕上)......即使我知道了,字体就是它们的样子,我怀疑我能否确切地知道我应该将字符串修剪到的字符数。我不能将它修剪到给定的空间量并在我的 UILabel 中获得空间量,可以吗?

或者,我可以使用 UITextView 和 Scroll 也许这就是我必须做的。我可以获取我的 TextView 文本的全部值并向其添加新字符串并将其放回 UITextView,然后使用 NSMakeRange 和 .scrollRangeToBottom 滚动到底部。

    func updateConsole(switchType: String) {

//unwind the console's text

if let tempString = consoleZe.text {
currentText = tempString
}

consoleZe.text = currentText + "A new message here! Something clever taken from \(switchType).\n"

//Scroll to the bottom

let bottom = NSMakeRange(consoleZe.text.characters.count - 1, 1)
consoleZe.scrollRangeToVisible(bottom)
}

对于我的小型更新控制台来说,这似乎是一项繁重的工作。我不关心滚动查看过去的值。我什至更喜欢控制台没有滚动...所以抓取、添加、粘贴、获取底部然后滚动似乎有很多额外的、不需要的包袱。

欢迎所有关于使用 UILabel 或 UITextView 或任何其他方式实现最小控制台的想法,谢谢!

最佳答案

我已经使用 TableView 和“ConsoleBuffer”类作为数据源实现了“控制台 View Controller ”。表格 View 很好地对应了消息记录控制台的逐行导向特性,并使自动滚动变得容易。

ConsoleBuffer 是一个单例类,它将控制台消息保存在一个简单的字符串数组中,并附有一些辅助函数。请在下面查看完整的 ConsoleBuffer 实现:

class ConsoleBuffer {
struct Prefs {
static let defaultLines = 100
static let maxLines = 1000
}
static let shared = ConsoleBuffer()

private var buffer = [String]() {
didSet {
if buffer.count > lines {
buffer.removeFirst(buffer.count - lines)
}
tableView?.reloadData()
NSAnimationContext.runAnimationGroup({ (context) in
if let tableView = self.tableView {
if let scrollView = tableView.enclosingScrollView {
let range = tableView.rows(in: scrollView.contentView.visibleRect)
let lastRow = range.location + range.length
if lastRow == oldValue.count - 1 {
context.allowsImplicitAnimation = true
tableView.scrollRowToVisible(buffer.count - 1)
}
}
}
}, completionHandler: nil)

}
}

var lines = ConsoleBuffer.Prefs.defaultLines {
didSet {
if lines > ConsoleBuffer.Prefs.maxLines {
lines = ConsoleBuffer.Prefs.maxLines
}
}
}

var count: Int {
get {
return buffer.count
}
}

var tableView: NSTableView?

private init() { }

func line(_ n: Int) -> String {
if n >= 0 && n < buffer.count {
return buffer[n]
} else {
return ""
}
}

func add(_ line: String) {
let dateStampedLine = "\(Date()) \(line)"
buffer.append(dateStampedLine)
}

func clear() {
buffer.removeAll()
}
}

这两个语句使 ConsoleBuffer 成为单例:

static let shared = ConsoleBuffer()
private init() { }

拥有单例可以轻松地在项目的任何位置添加新的控制台行,而无需引用类的实例。将 init 设置为私有(private)可防止任何人调用 ConsoleBuffer() — 您不得不使用它的单例实例:ConsoleBuffer.shared

控制台行字符串保存在 buffer 数组中,该数组是私有(private)的,以隐藏其实现。向该数组添加新行时,tableview 会平滑滚动到添加的最后一行,但前提是之前显示了最后一行。否则滚动位置保持不变。

数据源现在很容易实现:

func numberOfRows(in tableView: NSTableView) -> Int {
return ConsoleBuffer.shared.count
}

func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
let cell = tableView.make(withIdentifier: "ConsoleCell", owner: self) as? NSTableCellView
cell?.textField?.stringValue = ConsoleBuffer.shared.line(row)
return cell
}

在 tableview controller 的 viewDidLoad 函数中,您需要将 ConsoleBuffertableView 属性设置为使用的 tableview。此外,这是设置要存储在缓冲区数组中的所需最大行数的地方:

ConsoleBuffer.shared.tableView = tableView
ConsoleBuffer.shared.lines = 500

现在您可以像这样向控制台添加新行:

ConsoleBuffer.shared.add("console message")

希望这能让您朝着正确的方向前进。

关于swift - 如何在 Swift 应用程序中创建一个最小的控制台(UILabel、UITextView、滚动、截头?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46240085/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com