Здравствуйте, я новичок в Swift и использую SwiftUI для своего проекта, где я загружаю некоторые данные о погоде и отображаю их в ContentView ().

Я хотел бы выделить некоторую часть текста, если она содержит какое-то конкретное слово, но я не знаю, с чего начать.

В ContentView () я попытался установить функцию, получающую строку, загруженную из Интернета, и возвращающую строку. Я считаю, что это неправильно, потому что SwiftUI вообще не применяет модификаторы для текста.

Например, в моем ContentView () я бы хотел, чтобы слово thunderstorm имело модификатор .bold ():

struct ContentView: View {
  let testo : String = "There is a thunderstorm in the area"

  var body: some View {
    Text(highlight(str: testo))
  }

  func highlight(str: String) -> String {
    let textToSearch = "thunderstorm"
    var result = ""

    if str.contains(textToSearch) {
      let index = str.startIndex
      result = String( str[index])
    }

    return result
  }

}
5
Damiano Miazzi 31 Май 2020 в 07:24

4 ответа

Лучший ответ

IOS 13, Swift 5. В этой средней статье описано общее решение. Используя его, вы можете выделить любой текст в любом месте с единственным уловом, поскольку он не может быть длиннее 64 символов, поскольку он использует побитовые маски.

https://medium.com/@marklucking/an-interesting-challenge-with-swiftui-9ebb26e77376

enter image description here

Это основной код в статье.

ForEach((0 ..< letter.count), id: \.self) { column in
      Text(letter[column])
        .foregroundColor(colorCode(gate: Int(self.gate), no: column) ? Color.black: Color.red)
        .font(Fonts.futuraCondensedMedium(size: fontSize))

    }

И этот, чтобы замаскировать текст ...

func colorCode(gate:Int, no:Int) -> Bool {

 let bgr = String(gate, radix:2).pad(with: "0", toLength: 16)
 let bcr = String(no, radix:2).pad(with: "0", toLength: 16)
 let binaryColumn = 1 << no - 1

 let value = UInt64(gate) & UInt64(binaryColumn)
 let vr = String(value, radix:2).pad(with: "0", toLength: 16)

 print("bg ",bgr," bc ",bcr,vr)
 return value > 0 ? true:false
}
1
user3069232 31 Май 2020 в 07:09

Если для этого требуется просто стилизация слов, то здесь возможно решение.

Протестировано с Xcode 11.4 / iOS 13.4

demo

struct ContentView: View {
    let testo : String = "There is a thunderstorm in the area. Added some testing long text to demo that wrapping works correctly!"


    var body: some View {
        hilightedText(str: testo, searched: "thunderstorm")
            .multilineTextAlignment(.leading)
    }

    func hilightedText(str: String, searched: String) -> Text {
        guard !str.isEmpty && !searched.isEmpty else { return Text(str) }

        var result: Text!
        let parts = str.components(separatedBy: searched)
        for i in parts.indices {
            result = (result == nil ? Text(parts[i]) : result + Text(parts[i]))
            if i != parts.count - 1 {
                result = result + Text(searched).bold()
            }
        }
        return result ?? Text(str)
    }
}

Примечание. ниже используется ранее использовавшаяся функция, но, как прокомментировал @Lkabo, у нее есть ограничения на очень длинные струны

func hilightedText(str: String) -> Text {
    let textToSearch = "thunderstorm"
    var result: Text!

    for word in str.split(separator: " ") {
        var text = Text(word)
        if word == textToSearch {
            text = text.bold()
        }
        result = (result == nil ? text : result + Text(" ") + text)
    }
    return result ?? Text(str)
}
2
Asperi 19 Июл 2020 в 04:50

Вы можете объединить с несколькими текстовыми представлениями.

import SwiftUI
import PlaygroundSupport

struct ContentView: View {
  var body: some View{
    let testo : String = "There is a thunderstorm in the area"
    let stringArray = testo.components(separatedBy: " ")
    let stringToTextView = stringArray.reduce(Text(""), {
      if $1 == "thunderstorm" {
        return $0 + Text($1).bold() + Text(" ")
      } else {
        return $0 + Text($1) + Text(" ")
      }

    })
    return stringToTextView
  }
}

PlaygroundPage.current.setLiveView(ContentView())

1
BokuWaTaka 31 Май 2020 в 06:13

Я не собираюсь решать это за вас, но я могу указать вам правильное направление. Это только сделает вас лучшим программистом.

Откройте новую игровую площадку в Xcode и вставьте следующий фрагмент кода:

import Foundation

let str = "There is a thunderstorm in the area"

let array = str.components(separatedBy: " ")

print(array)

Вывод: ["Там", "есть", "а", "гроза", "в", "the", "область"]

(Это разбивает строку на слова)

Теперь напишите функцию, которая принимает ввод слова, которое вы пытаетесь найти, и возвращает Bool, если слово, которое вы ищете, существует или нет.

func findWordInStr(str: String) -> Bool {
  // Give this a try 
}
0
Raz 31 Май 2020 в 04:47