swiftuiapple-watchwatchoswidgetkitapple-watch-complication

SwiftUI and WidgetKit: Getting AM and PM to wrap to a second line


Working in WidgetKit on the watch, I can't figure out how to style this text so that it looks correct. The problem is that, in locations where Am/Pm time styles are appropriate, the system only wraps the M to the next line, where I would like both AM and PM to wrap to the second line. In locations where they use a 24 hour clock, there should be no AM and PM. How can I achieve this?

static let sleepTimeFormat: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateStyle = .none
        formatter.timeStyle = .short
        return formatter
    }()

    Text("\(targetBedTime, formatter: Self.sleepTimeFormat)")
        .font(.system(size: 14))
        .fontWeight(.bold)

enter image description here


Solution

  • You can use ViewThatFits plus replace spaces with newlines to make this work.

    let timeString = Self.sleepTimeFormat.string(from: .now)
    ViewThatFits {
        Text(timeString).lineLimit(1)
        Text(timeString.replaceCharacters(from: .whitespaces, with: "\n")) // The formatter doesn't use a regular " "
    }
    .font(.system(size: 14))
    .fontWeight(.bold)
    .frame(width: 50) // Ensure second option gets displayed
    
    // Convenience method 
    extension String {
        func replaceCharacters(from characterSet: CharacterSet, with replacementString: String = "") -> String {
            self.components(separatedBy: characterSet).joined(separator: replacementString)
        }
    }
    

    And the result:

    Broken across two lines