# TIL: SwiftUI List on macOS

I am working on a small macOS app using SwiftUI. I struggled to get `List` working as I wanted to. TIL that `List` works better on iOS :)

|Out-of-the-box|Goal|
|---|---|
|![Standard](https://cdn.hashnode.com/res/hashnode/image/upload/v1649778513426/JcBi4QCYF.png)|![FinalVersion](https://cdn.hashnode.com/res/hashnode/image/upload/v1649778471271/af5vPkFCe.png)|

I thought about using `ScrollView` and a `LazyVStack` to emulate a list, but I missed out on specific functionality, especially the option to move items in a list.

```
        List {
            ForEach(items, id: \.id) { entry in
                HStack {
                    Text(entry.text)
                        .lineLimit(2)
                    Spacer()
                    Button {
                        deleteItem(entry)
                    } label: {
                        Image(systemName: "trash")
                    }
                }
            }
            .onMove { indices, destination in
                // TODO: update items array accordingly 
            }
        }
```

If you do not want to use `List`, I recommend reading the article from Avi Tsadok for inspiration. He wrote about reordering items in a `LazyVStack` in **iOS apps** by replicating UIKit Drag and Drop in SwiftUI.
%[https://avitsadok.medium.com/reorder-items-in-swiftui-lazyvstack-6d238efab04]

As you can see in the screenshot above, I had to solve two issues:
1. Background color of the list
2. Divider

# Background color

Super helpful was this answer to the following Stack Overflow question.

%[https://stackoverflow.com/a/61577381/7963350]

I chose to use this extension to override `List`'s color:

```
extension NSTableView {
  open override func viewDidMoveToWindow() {
    super.viewDidMoveToWindow()

    backgroundColor = NSColor.clear
    enclosingScrollView!.drawsBackground = false
  }
}
```

This approach was ok in my case as my app has only one list. An alternative approach is to remove a list's background (without affecting the whole app!) by using [Introspect](https://github.com/siteline/SwiftUI-Introspect). Introspect allows you to get the underlying UIKit or AppKit element of a SwiftUI view for styling.


![Using the extension](https://cdn.hashnode.com/res/hashnode/image/upload/v1649778567026/kiJjKM6zV.png)

# Divider

Stack Overflow came to my rescue again.

%[https://stackoverflow.com/questions/65978431/swiftui-list-with-divider-but-no-extra-insets-in-macos/71586895#71586895]

> The divider should really be provided by the List automatically as it does on iOS but unfortunately is not as of macOS 12.3.

> The padding around each row in a List seems to be there to account for the selection highlight. So if we want to provide our own Divider but want it to look native while accounting for the highlight padding we would need to offset the Divider like so:

```Swift
struct ContentView: View {
    @Binding var selection: Set<Item>

    var body: some View {
        List(selection: $selection) {
           SomeView()
              .swiftyListDivider()
        }
    }
}

import SwiftUI
extension View {
    func swiftyListDivider() -> some View {
        background(Divider().offset(y: 4.0), alignment: .bottom)
    }
}
```

This approach was 'good enough' even though this does not precisely replicate the Divider behavior like other apps.

![FinalVersion](https://cdn.hashnode.com/res/hashnode/image/upload/v1649778471271/af5vPkFCe.png)


