tera
1
I'm tracing down a swiftUI text layout issue and created a small sample app reproducing it (tested on iOS 15, iPhone max size simulator) which I've filed as a radar. Looking for a workaround until it is fixed. NavigationView, List and PlainListStyle are the important ingredients.
Edit:
Expected Behaviour: text height adjusted appropriately and there is no text truncation. The presence of slider doesn't effect things.
Actual Behaviour: text height is not adjusted appropriately and there is text truncation. Uncommenting slider magically fixes the bug.
import SwiftUI
class Model: ObservableObject {
@Published var value: CGFloat = 0
@Published var text = "t in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis"
private var on = false
init() {
Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [self] _ in
on.toggle()
value = on ? 0.99 : 0
}
}
}
struct ContentView: View {
@StateObject var model = Model()
var body: some View {
NavigationView {
List {
// Uncomment - and there is no bug
// Slider(value: $model.value)
HStack() {
Color.green.frame(width: model.value * 200, height: 1)
Text(model.text)
}
}
.listStyle(PlainListStyle())
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
@main
struct TextBugApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
young
(rtSwift)
2
So I think the bug is Text got elited instead of expand the height more to show the whole?
Add this to Text fix it:
.fixedSize(horizontal: false, vertical: true)
I duplicated the HStack to add an extra item in the List and it still works 
tera
3
yep, the text is truncated like this:
with your workaround the text is not truncated... but extends beyond the list cell boundaries:
young
(rtSwift)
4
I don't see the problem: Text.fixedSize() fix - Album on Imgur
Xcode Version 13.2 (13C90)
I just copy your code and add fixedSize():
import SwiftUI
class Model: ObservableObject {
@Published var value: CGFloat = 0
@Published var text = "t in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis"
private var on = false
init() {
Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [self] _ in
on.toggle()
value = on ? 0.99 : 0
}
}
}
struct ContentView: View {
@StateObject var model = Model()
var body: some View {
NavigationView {
List {
// Uncomment - and there is no bug
// Slider(value: $model.value)
HStack() {
Color.green.frame(width: model.value * 200, height: 1)
Text(model.text)
.fixedSize(horizontal: false, vertical: true)
}
HStack() {
Color.green.frame(width: model.value * 200, height: 1)
Text(model.text)
.fixedSize(horizontal: false, vertical: true)
}
}
.listStyle(PlainListStyle())
}
}
}
tera
5
I think the fact you are duplicating HStack/Text makes it redraw twice and correct any incorrectness that would otherwise surface... try this to see the issue:
HStack() {
Color.green.frame(width: model.value * 200, height: 1)
Text(model.text)
.fixedSize(horizontal: false, vertical: true)
}
Color.blue
young
(rtSwift)
6
Then you need to "invalidated" List item with a new id: List item invalidated - Album on Imgur
import SwiftUI
class Model: ObservableObject {
@Published var id = 0
@Published var value: CGFloat = 0
@Published var text = "t in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis"
private var on = false
init() {
Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [self] _ in
on.toggle()
value = on ? 0.99 : 0
id += 1
}
}
}
struct ContentView: View {
@StateObject var model = Model()
var body: some View {
NavigationView {
List {
// Uncomment - and there is no bug
// Slider(value: $model.value)
HStack() {
Color.green.frame(width: model.value * 200, height: 1)
Text(model.text)
.fixedSize(horizontal: false, vertical: true)
}
.id(model.id)
// HStack() {
// Color.green.frame(width: model.value * 200, height: 1)
// Text(model.text)
// .fixedSize(horizontal: false, vertical: true)
// }
Color.blue
}
.listStyle(PlainListStyle())
}
}
}
Check this to see if there is better approach: id(_): Identifying SwiftUI Views - The SwiftUI Lab
1 Like
tera
7
wow, thanks a lot. It did it and fixedSize trick is no required, just id.
Whenever you post about a bug, you need to describe the expected behavior and the actual behavior that you observe.
tera
9
Edited the expected / actual behaviours in the original post.
Also this variation of @young version works:
class Model: ObservableObject {
@Published var value: CGFloat = 0
@Published var text = "t in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis"
var id: String {
String(Double(value)) + text
}
Edit:
Interestingly this simpler variant also works:
HStack {
Color.green.frame(width: model.value * 200, height: 1)
Text(model.text)
}
.id(model.value)
and changing either the text variable or value variable correctly updates UI. 