Getting Started

To start, let’s create a new Xcode SwiftUI project. We’ll be using the official Hacker News API, which offers almost real-time data.

In order to create a SwiftUI List that holds the top stories from Hacker News, we need to set up our ObservableObject class. This class is responsible for fetching the stories from the API and passing them on to the SwiftUI List. The following code does that for you:

There’s a lot happening in the above code. Let’s break it down:

fetchTopStories is responsible for returning an array of integer ids for the stories.

is responsible for returning an array of integer ids for the stories. To save time, we’re passing the top 10 story identifiers to the fetchStoryById function, where we’re fetching the Hacker News stories using a custom publisher FetchItem and merging the results.

function, where we’re fetching the Hacker News stories using a custom publisher and merging the results. The collect() operator of Combine is responsible for merging all the stories fetched from the API into a single array.

Let’s look at how to construct our custom Combine publisher next.

Creating a Custom Combine Publisher

To create a custom publisher, we need to conform the struct to the Publisher protocol and set the Output and Failure types of the stream as shown below:

The id defined represents the story identifier that’s passed in the initializer.

defined represents the story identifier that’s passed in the initializer. Implementing the receive(subscriber:) method is crucial. It connects the publisher to the subscriber, and we need to ensure that the output from the publisher has the same type as the input to the subscriber.

method is crucial. It connects the publisher to the subscriber, and we need to ensure that the output from the publisher has the same type as the input to the subscriber. Inside the receive<S>(subscriber: S) method, we’re making another API request. This time, we’re fetching the story and decoding it using a StoryItem model, which is defined below:

struct StoryItem : Identifiable, Codable {

let by: String

let id: Int

let kids: [Int]?

let title: String? private enum CodingKeys: String, CodingKey {

case by, id, kids, title

}

}

The array of StoryItems is then published to the SwiftUI view to get which has a built-in subscriber. The following code is responsible for displaying the Hacker News stories in the SwiftUI list:

The NavigationLink is responsible for taking the user to the destination screen, where the comments are displayed. We’ve wrapped our destination view — CommentView —in a lazy view. This is done to load the destination views only when the user has navigated to that view. It’s a common pitfall in NavigationLink s.

Before we jump into the comments section and the subsequent sentiment analysis using NLP, let’s look at what we’ve built so far: