[英]Exceeding max Text("") concatenation length - SwiftUI -
參考 Asperi ( https://stackoverflow.com/users/12299030/asperi ) 在問題上發布的答案: 突出顯示 SwiftUI 中文本的特定部分
我發現他的答案非常有用,但是,當我的字符串輸入超過 32k 個字符時,應用程序崩潰,所以我假設 String() 的最大值為 32k,並且正在尋找解決方法。
在我的應用程序中,如果有人搜索單詞“pancake”,搜索詞將被存儲,當用戶查看詳細信息頁面(比如說食譜)時,單詞 pancake 將突出顯示。 一切都適用於這個答案,但是當配方超過 32k 個字符時,應用程序會因超出索引范圍消息而崩潰。 (具體錯誤信息:Thread 1: EXC_BAD_ACCESS (code=2, address=0x16d43ffb4))
這是該問題答案中修改后的代碼:
這將打印數據:
hilightedText(str: self.recipes.last!.recipeData!)
.multilineTextAlignment(.leading)
.font(.system(size: CGFloat( settings.fontSize )))
上面這段代碼顯然還有更多內容,但本質上,它迭代了一個數據庫,找到最后一條包含'search word'的記錄,並在此處顯示recipeData,它是數據庫中包含的一個大字符串。
實現 highlightText 功能:
func hilightedText(str: String) -> Text {
let textToSearch = searched
var result: Text!
for word in str.split(separator: " ") {
var text = Text(word)
if word.uppercased().contains(textToSearch.uppercased()) {
text = text.bold().foregroundColor(.yellow)
}
//THIS NEXT LINE has been identified as the problem:
result = (result == nil ? text : result + Text(" ") + text)
}
return result
}
我已經稍微修改了 Asperi 的答案以滿足我的需要,並且一切都很好,除非我遇到一個大於 32k 的 recipeData 條目,如前所述。
我試過用其他一些數據類型替換String
,但沒有任何效果..
有任何想法嗎?
謝謝!
更新:
在評論中經過長時間的討論后,問題的根本原因似乎是在某些時候,對於某些記錄,我超過了最大 Text("") 連接。
在上面的代碼中,每個單詞都被拆分、評估並添加到長字符串“result”中,最終看起來像這樣: Text("word") + Text(" ") + Text("Word")
等等.
這樣做了,所以我可以輕松地為每個單詞應用顏色屬性,但似乎一旦我達到一定數量的單詞(少於 32k,一條記錄是 22k 並崩潰),應用程序就會崩潰。
Leo 建議https://stackoverflow.com/a/59531265/2303865這個線程作為替代方案,我將不得不嘗試實現它。
謝謝..
嗯...意想不到的限制...無論如何 - 學習新的東西。
好的,這是改進的算法,它應該會遠離這個限制。
使用 Xcode 12 / iOS 14 測試。(還更新了引用主題中的代碼突出顯示 SwiftUI 中文本的特定部分)
func hilightedText(str: String, searched: String) -> Text {
guard !str.isEmpty && !searched.isEmpty else { return Text(str) }
var result = Text("")
var range = str.startIndex..<str.endIndex
repeat {
guard let found = str.range(of: searched, options: .caseInsensitive, range: range, locale: nil) else {
result = result + Text(str[range])
break
}
let prefix = str[range.lowerBound..<found.lowerBound]
result = result + Text(prefix) + Text(str[found]).bold().foregroundColor(.yellow)
range = found.upperBound..<str.endIndex
} while (true)
return result
}
在評論中進行了多次討論之后,很明顯我達到了最大 Text() 連接限制,所以要小心,顯然有一個。
但是我意識到,當特定單詞需要特殊格式(IE 突出顯示等)時,我只需要拆分 Text("Word"),否則,我可以將所有原始字符串連接在一起並將其作為 Text("字串”)。
這種方法減輕了將每個單詞作為 Text("Word" 本身發送的操作,並大大減少了返回的 Text() 的數量。
請參閱下面解決問題的代碼:
func hilightedText(str: String) -> Text {
let textToSearch = searched
var result = Text(" ")
var words: String = " "
var foundWord = false
for line in str.split(whereSeparator: \.isNewline) {
for word in line.split(whereSeparator: \.isWhitespace) {
if word.localizedStandardContains(textToSearch) {
foundWord = true
result += Text(words) + Text(" ") + Text(word).bold().foregroundColor(.yellow)
} else {
if foundWord {
words = ""
}
foundWord = false
words += " " + word
}
}
words += "\n\n"
}
return result + Text(" ") + Text(words)
}
extension Text {
static func += (lhs: inout Text, rhs: Text) {
lhs = lhs + rhs
}
}
它可以使用一些清理,如評論中所討論的按空格分割等,但這只是為了克服崩潰的問題。 在我說它好之前需要一些額外的測試,但不會再崩潰..
添加:使用分隔符 by.isWhiteSpace 的建議有效,但是當我將它放回原處時,一切都是空格,不再有換行符,所以我添加了額外的換行符分割以保留換行符。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.