Search code examples
swiftuinsdateformatterdateformatter

Why does SwiftUI format dates as "2020 M10 27" in navigationTitle?


I'm using Xcode 12.1 and the iOS 14.1 simulator.

With the simplest possible code using Text.init(_:style:), the date format seems to differ between the nav bar title and the content view:

struct ContentView: View {
  var body: some View {
    NavigationView {
      Text(Date(), style: .date)
        .navigationTitle(
          Text(Date(), style: .date)
        )
    }
  }
}

I'd expect the title and content to look like "October 27, 2020" but the title looks like "2020 M10 27". I've never seen this format before.

Using a custom Formatter with Text.init(_:formatter:) gives the same result:

struct ContentView: View {
  var body: some View {
    let formatter: DateFormatter = {
      let formatter = DateFormatter()
      formatter.dateStyle = .long
      return formatter
    }()
    
    NavigationView {
      Text(Date(), formatter: formatter) // "October 27, 2020"
        .navigationTitle(
          Text(Date(), formatter: formatter) // "2020 M10 27"
        )
    }
  }
}

Finally, pre-formatting the string with Formatter.string(from:) gives the expected result:

import SwiftUI

struct ContentView: View {
  var body: some View {
    let formatter: DateFormatter = {
      let formatter = DateFormatter()
      formatter.dateStyle = .long
      return formatter
    }()

    NavigationView {
      Text(formatter.string(from: Date())) // "October 27, 2020"
        .navigationTitle(
          Text(formatter.string(from: Date())) // "October 27, 2020"
        )
    }
  }
}

What's going on here? Do I really need this workaround in order to display a date in the navigation title?


Solution

  • Yes, unfortunately it looks like a bug.


    As a workaround you can create an extension:

    extension Text {
        static let dateFormatter: DateFormatter = {
            let formatter = DateFormatter()
            formatter.dateStyle = .long
            return formatter
        }()
    
        init(date: Date) {
            self.init(Text.dateFormatter.string(from: date))
        }
    }
    

    so you have the same amount of code in navigationTitle:

    .navigationTitle(
        Text(date: Date())
    )