簡體   English   中英

超過最大文本(“”)連接長度 - SwiftUI -

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM