From JavaScript to Swift - Building a List in SwiftUI
Tags: javascript, swift
Published: 2019-07-04 02:37:28

---
title: From JavaScript to Swift - Building a List in SwiftUI
published: true
tags: JavaScript,Swift
canonical_url: https://tyhopp.com/notes/list-in-swift-ui
---

So you want to build a list with Apple's new declarative UI framework. Maybe you're used to building for the web like I am, and you think, "Let's mock up a data structure and iterate over it to make a list." Pretty straightforward, or so you thought. In JavaScript, you might do something like this:

```javascript
// Mock data structure
const racers = [
	{
		id: 1,
		name: 'Valentino Rossi',
		team: 'Yamaha'
	},
	{
		id: 2,
		name: 'Marc Márquez',
		team: 'Repsol Honda'
	},
];

// In React
racers.map(racer => (
	<p key={racer.id}>{racer.name} rides with {racer.team}</p>
));

// In ES6
const container = document.querySelector('.container');
racers.map(racer => {
	const item = document.createElement('p');
	item.setAttribute('id', racer.id);
	item.textContent = `${racer.name} rides with ${racer.team}`;
	container.appendChild(item);
});
```

I thought I could do the same thing with SwiftUI. Define an array of dictionaries and iterate over them using something like SwiftUI's `ForEach` or `List` views. In UIKit, `List` would be roughly equal to `UITableView`, and from my experience with `UITableView`, the table wants everything to be set up in a very particular fashion. So approaching cautiously, will `List` require us to do some extra stuff, or can we just chuck some data in and the world will be well and good? Turns out, there's a bit more setup. This won't work:

```swift
import SwiftUI

struct RacerList : View {
    
	  // Mock data structure
    let racers: [[String:String]] = [
        [
            "name": "Valentino Rossi",
            "team": "Yamaha"
        ],
        [
            "name": "Marc Márquez",
	        "team": "Repsol Honda"
        ]
    ]
    
    var body: some View {
        List(racers) { racer in
            if let name: String = racer.name, team: String = racer.team {
                Text("\(name) rides with \(team)")
            }
        }
    }
}
```

The compiler throws this error: `Unable to infer complex closure return type; add explicit type to disambiguate` , essentially boiling down to: "Hey, I don't understand what type you're returning." But didn't we say the `name` and `team` optionals are strings when we unwrapped them?

As it turns out, the problem isn't with the SwiftUI view code, it's with the data structure. **Swift is a strongly typed, protocol-oriented language** (bold for my own sake). The data you pass into a `List` needs to conform to the `Identifiable` protocol so that it knows how to reference each item.

> I like to think about protocols like this: protocols are to class inheritance as GraphQL is to REST. In regular class inheritance in most object-oriented languages, if you want to extend a class, you get all the methods and properties and other stuff from that class in your new sub-class. With protocols, you split up that baggage into different "slices" that you can tell your new classes to conform to. Much like GraphQL, where you tell the backend exactly what you want and what you don't want, protocols allow you to define exactly what you want your sub classes (or structs) to get.

We can implement the `Identifiable` protocol like this:

```swift
import SwiftUI

// Mock data structure
struct Racer: Identifiable {
    var id: Int
    var name: String
    var team: String
}

struct RacerList : View {
    var body: some View {
        let a = Racer(id: 1, name: "Valentino Rossi", team: "Yamaha")
        let b = Racer(id: 2, name: "Marc Márquez", team: "Repsol Honda")
        let racers = [a, b]
        
        return List(racers) { racer in
            Text("\(racer.name) rides with \(racer.team)")
        }
    }
}
```

Yay, it works! 🙌 Now if we're to start refactoring this a bit, we can take the data structure, or _model_ as it's known in the iOS world, and put it in a separate directory with all our models. Then, anywhere in our app we define a capital R `Racer`, the compiler knows we are referencing our model, and hence has detailed information about how it conforms to `Identifiable` and the type of each property.

Done! This has been another round trip in what may become a loosely associated series of articles about how to do things in Swift coming from JavaScript land. Thanks for reading!

More resources:

- [SwiftUI List Tutorial by Apple](https://developer.apple.com/tutorials/swiftui/building-lists-and-navigation)
- [Protocols — The Swift Programming Language (Swift 5.1)](https://docs.swift.org/swift-book/LanguageGuide/Protocols.html)
- [Identifiable - SwiftUI | Apple Developer Documentation](https://developer.apple.com/documentation/swiftui/identifiable)
- [Different flavors of view models in Swift — Swift by Sundell](https://www.swiftbysundell.com/posts/different-flavors-of-view-models-in-swift)