SwiftUI Weekly Observations #1

Easy Testing

Whenever I am creating a new View, I always create a data model struct that I’d use to instantiate that View. I mark it with @State attribute and the View becomes stateful, meaning that whenever the data model changes, View will get updated by the underlying system.

struct ScreenModel {
  var title : String
  var name : String

}

extension ScreenModel {
  static var template : Self {
    ScreenModel(title: "Title1", name: "Name1")
  }

}

static Screen : View {
  @State var model : ScreenModel

  var body : some View {
    VStack {
      Text(self.model.title)
        .font(.system(.largeTitle))
      TextField("Enter name", self.$model.name)
    
    }
  
  }

}

#if DEBUG
struct Screen_Previews : PreviewProvider {
  static var previews : some View {
    Screen(model: .template)
  
  }

}
#endif

How to Improve

This is on its own very useful technique, but it still is limited to hardcoded model data, which is not a good fit when it comes to i18n and l10n. 

So what to do? Arrays.

A hardcoded array that contains elements with a non-identical model data. This solves both covering as many test cases as possible, as well as expands experience of the process during the development.

extension ScreenModel {
  static var template : [Self] {
    [
      ScreenModel(title: "Title1", name: "Name1")
      ScreenModel(title: "A very long title", name: "A very long name to test edge cases")
      ScreenModel(title: "Short name", name: ".")
      ScreenModel(title: ".", name: "Short title")
    ]
  
  }

}

#if DEBUG
struct Screen_Previews : PreviewProvider {
  static var previews : some View {
    Screen(model: .template.randomElement()) // notice the random element selection for the preview
  
  }

}
#endif

One Step Further

It’s possible to use a ForEach in PreviewProvider’s body to generate multiple previews. So with a small modification, it would become possible to test multiple variants of layout at the same time!

#if DEBUG
struct Screen_Previews : PreviewProvider {
  static var previews : some View {
    ForEach(ScreenModel.template) {
      Screen(model: $0)
    }
  
  }

}
#endif

P.S. I miss Objective-C because it was kind-of possible to do this with a dyci while the app was running. It was hard, but fun.

Thanks for reading! More articles will come soon.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s