[SwiftUI] How I Built OSS News App
Tags: swift, swiftui, concurrency, ios15
Published: 2022-02-13 21:35:58

---
title: [SwiftUI] How I Built OSS News App
published: true
description: 
tags: Swift, SwiftUI, Concurrency, iOS15
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4pmzymope0de4co6a2ra.jpeg
---


This post is originally [published in Japanese](https://zenn.dev/mtfum/articles/7540aef4ffb3a27bf37c) a half years ago. I want someone to know how create an iOS app with modern technology and how I struggled with that. Please enjoy!!

---

I built an OSS news app for iOS with SwiftUI. 
Please give me stars on GitHub!

{% github https://github.com/mtfum/NewsUI %}


{% github https://github.com/mtfum/NewsAPI %}


## Why I built this

Apple had released a lot of new API in WWDC 2021. Everything is very exciting and motivated me to create a new app though, I just wanted to experiment the new feature like [Searchable](https://developer.apple.com/documentation/swiftui/emptyview/searchable(text:placement:)) and [Refreshable](https://developer.apple.com/documentation/swiftui/image/refreshable(action:)) or new feature of Swift language like Concurrency.

Therefore, the app itself requires Xcode 13 or higher and iOS 15 or higher.

## About App

This app uses the [newsapi.org](https://newsapi.org/) API to search for the world's top news and specific words.
It consists of three tabs and implements only the minimum necessary functions.
I'm personally satisfied with it because it accomplished the purpose of trying out the new features I mentioned above.

| Headline | Search | Publishers |
| --------- |:---------:| -------:|
| ![Screenshot for Headline](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/turrma68r7pq2wgc1wej.png) | ![Screenshot for Search](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lyc0bsl0d7r7fbmcwr7b.png) | ![Screenshot for Publishers](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t2draxx1qx1t8lgg0egt.png) |

## NewsAPI: Concurrency

With the creation of the app, I wrapped the API of newsapi.org and released it as an iOS library.
I could have left it as an internal implementation, but I cut it out as a library for the following reasons.

- There was no Swift library for newsapi that supported asynchronous processing.
- I want people who want to make iOS apps to use it.
- I wanted to do it as a part of OSS activity.


From here, I will lightly introduce the API that uses `async/await` syntax, the most significant language feature added in Swift 5.5.
The following is a sample code that uses the NewsAPI to get the headline news.

```swift
func getHeadlines() async -> [NewsArticle] {
  do {
    let articles = try await NewsAPI(apiKey: "YOUR_API_KEY").getTopHeadlines()
    return articles
  } catch {
    // do something
  }
}
```

If you read the above code, you will see that instead of using traditional closures, the keyword `async` is added to the method and the keyword `await` is used inside.
This method, `getHeadlines`, is defined as an asynchronous function, so it needs the `await` keyword right before it.
Since `await` suspends the process immediately after it is written, it is more intuitive to write.
Not only does it improve readability by reducing the number of lines of code and the depth of nesting, but it also expands the scope of expression by allowing multiple asynchronous processes to be handled simultaneously.

## NewsUI: App Architecture

Here is an explanation of the application itself.
The following image shows an easy-to-understand diagram of the app structure.


![NewsUI App Architecture](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4pmzymope0de4co6a2ra.jpeg)
 

As mentioned in the above section, NewsAPI (red part) has been cut out as an external library.
Only the internal `NewsClient` depends on the `NewsAPI`, and each feature depends on it.
All the features in the yellow part of the image are managed as Packages, and the `Package.json` file is structured as follows.

```swift
// https://github.com/mtfum/NewsUI/blob/main/Package.swift

import PackageDescription

let package = Package(
  name: "NewsUI",
  platforms: [
    .iOS("15.0")
  ],
  products: [
    .library(name: "AppFeature", targets: ["AppFeature"]),
    .library(name: "SearchFeature", targets: ["SearchFeature"]),
    .library(name: "HeadlinesFeature", targets: ["HeadlinesFeature"]),
    .library(name: "SourcesFeature", targets: ["SourcesFeature"])
  ],
  dependencies: [
    .package(url: "https://github.com/mtfum/NewsAPI.git", from: "0.1.0"),
    .package(url: "https://github.com/apple/swift-collections.git", from: "0.0.1"),
  ],
  targets: [
    .target(name: "AppComponent", dependencies: ["NewsAPI"]),
    .target(name: "AppFeature", dependencies: ["SearchFeature", "HeadlinesFeature", "SourcesFeature"]),
    .target(name: "NewsClient", dependencies: ["NewsAPI"]),
    .target(name: "SearchFeature", dependencies: ["AppComponent", "NewsClient", .product(name: "OrderedCollections", package: "swift-collections")]),
    .target(name: "HeadlinesFeature", dependencies: ["AppComponent", "NewsClient"]),
    .target(name: "SourcesFeature", dependencies: ["AppComponent", "NewsClient"])
  ]
)
```

The app is divided into multiple modules, and each module is divided into different functions (in this case, tabs) so that they cannot be cross-referenced.
Multi-module system has some merits such as clear dependencies and optimized compilation, but for a small app like this one, you won't get much benefit from it.

---

Though it is an unnecessary addition, we call it Hyper-modularization, and [isowords](https://github.com/pointfreeco/isowords) is being developed with 86 modules.


{% github https://github.com/pointfreeco/isowords#hyper-modularization %}

---

In addition, each feature was integrated into the AppFeature, and the app itself could be simply configured to refer to the AppFeature.

```swift
import SwiftUI
import AppFeature

@main
struct NewsUIApp: App {
  var body: some Scene {
    WindowGroup {
      AppFeatureView()
    }
  }
}
```

## Wrap-up

This is a brief introduction to [NewsUI](https://github.com/mtfum/NewsUI) and [NewsAPI](https://github.com/mtfum/NewsAPI), which I have been working on.
I'm happy to publish it now that I have a breakthrough for now.
Please star if you find it helpful!
Thank you for reading.