Skip to content

Commit 922c2fd

Browse files
david-swiftcthielen
andcommitted
Add adwaita-swift blog post (swiftlang#599)
* Add adwaita-swift blog post * adwaita-swift: Remove title * adwaita-swift: Improve article and author info * adwaita-swift: Update text describing screenshot * Update blog post timestamp --------- Co-authored-by: Christopher Thielen <[email protected]>
1 parent df06401 commit 922c2fd

File tree

3 files changed

+153
-0
lines changed

3 files changed

+153
-0
lines changed

_data/authors.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,3 +437,8 @@ hassila:
437437
gravatar: d6ff2f8e32e6155569a312295bce0ec8
438438
github: hassila
439439
about: "Joakim Hassila is the CTO of Ordo One, which builds high performance distributed trading systems written in Swift running on Linux and macOS."
440+
441+
davidswift:
442+
name: david-swift
443+
github: david-swift
444+
about: "David is a student interested in Swift and the GNOME Project."

_posts/2024-03-25-adwaita-swift.md

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
---
2+
layout: post
3+
published: true
4+
date: 2024-03-25 10:00:00
5+
title: "Writing GNOME Apps with Swift"
6+
author: [davidswift]
7+
---
8+
9+
Swift is well-suited for creating user interfaces thanks to the clean syntax, static typing, and special features making code easier to write.
10+
[Result builders](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/advancedoperators/#Result-Builders), combined with Swift's [closure expression syntax](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/closures/#Closure-Expression-Syntax), can significantly enhance code readability.
11+
12+
[Adwaita for Swift](https://github.com/AparokshaUI/adwaita-swift) leverages these Swift features to provide an intuitive interface for developing applications for the [GNOME](https://www.gnome.org/) platform.
13+
GNOME is a popular, open source desktop environment for Linux, known for its emphasis on simplicity and accessibility.
14+
It offers an intuitive user interface, with a vast app ecosystem built using its modern Adwaita design language.
15+
Explore a collection of great apps under [Apps for GNOME](https://apps.gnome.org).
16+
17+
Let's look at a code example of using Adwaita for Swift.
18+
The following code snippet defines a _view_, which represents a part of the user interface inside a window.
19+
20+
```swift
21+
struct Counter: View {
22+
23+
@State private var count = 0
24+
25+
var view: Body {
26+
HStack {
27+
Button(icon: .default(icon: .goPrevious)) {
28+
count -= 1
29+
}
30+
Text("\(count)")
31+
.style("title-1")
32+
.frame(minWidth: 100)
33+
Button(icon: .default(icon: .goNext)) {
34+
count += 1
35+
}
36+
}
37+
}
38+
39+
}
40+
```
41+
42+
A view can be nested within other views or added as the child of a window.
43+
44+
Its content can be modified from outside that view and is influenced by its position in the view hierarchy.
45+
This makes it easier to compose views to produce different results.
46+
The screenshot shows one simple possibility.
47+
48+
![A screenshot of the counter example app.](/assets/images/2024-03-14-adwaita-swift/demo.png){:style="max-width: 100%; height: auto; width: unset; margin: auto auto; display: block;"}
49+
50+
## Motivation
51+
The primary motivation for this package is to enable the use of Swift when writing GNOME apps, for all the reasons outlined above. But there are a few additional reasons:
52+
53+
### Declarative
54+
While there are already libadwaita and GTK bindings for numerous modern programming languages, including Rust, Python, and JavaScript, all official bindings follow an _imperative_ coding style.
55+
This can be verbose and harder to follow than a declarative style as user interfaces are constructed using a series of commands.
56+
The following Python code serves as an illustration of this.
57+
```python
58+
class Counter(Gtk.Box):
59+
60+
def __init__(self):
61+
Gtk.Box.__init__(self, orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
62+
self.count = 0
63+
64+
button_prev = Gtk.Button.new_from_icon_name("go-previous", Gtk.IconSize.BUTTON)
65+
button_prev.connect("clicked", self.on_prev_clicked)
66+
self.pack_start(button_prev, True, True, 0)
67+
68+
self.label = Gtk.Label(label=str(self.count))
69+
self.label.set_name("title-1")
70+
self.pack_start(self.label, True, True, 0)
71+
72+
button_next = Gtk.Button.new_from_icon_name("go-next", Gtk.IconSize.BUTTON)
73+
button_next.connect("clicked", self.on_next_clicked)
74+
self.pack_start(button_next, True, True, 0)
75+
76+
def on_prev_clicked(self, button):
77+
self.count -= 1
78+
self.label.set_text(str(self.count))
79+
80+
def on_next_clicked(self, button):
81+
self.count += 1
82+
self.label.set_text(str(self.count))
83+
```
84+
85+
This Python code uses the [PyGObject](https://gnome.pages.gitlab.gnome.org/pygobject/) library and produces the same user interface as the Swift code above.
86+
87+
### Ease of Use
88+
As you can see, Adwaita for Swift is built around _data_.
89+
For example, changing the variable `count` when pressing one of the buttons in the sample app will automatically update the user interface.
90+
Traditional bindings require you to call a function on the object holding a widget that should update its content once a value changes.
91+
92+
If you decide to store the value on the disk so that it persists between startups of the app, you would have to add a lot of complexity to your code using traditional bindings.
93+
Adwaita for Swift enables you to simply add a unique identifier to the variable that should be stored, and will take care of the rest.
94+
```swift
95+
@State("count") private var count = 0
96+
```
97+
98+
There is also a simple and safe approach for localization with the [Localized](https://github.com/AparokshaUI/Localized) package.
99+
100+
### Readability
101+
The simplicity coming with the data-centric approach has a positive impact on readability.
102+
103+
Another point is the declarative definition of the user interface itself. You can focus on what the app should look like and how it should behave rather than how to achieve those results.
104+
105+
While there are other solutions available, such as [defining the UI with XML](https://docs.gtk.org/gtk4/class.Builder.html) and [Blueprint](https://jwestman.pages.gitlab.gnome.org/blueprint-compiler/), they require the user interface and actual code to be written in different files. Also, updating the user interface has to be done manually whenever data changes.
106+
This makes it more difficult to follow the logic as a reader.
107+
108+
As the user interface is written in Swift, you can use convenient Swift syntax directly in your user interface definition.
109+
110+
```swift
111+
var view: Body {
112+
if count == 0 {
113+
Text("😍")
114+
} else {
115+
Text("\(count)")
116+
}
117+
}
118+
```
119+
120+
### Cross-Platform App Development
121+
Adwaita for Swift is useful in a number of ways:
122+
123+
- You can write apps that run on Linux, macOS and Windows with a single codebase.
124+
- You can share backend Swift code between SwiftUI apps and GNOME apps.
125+
- You can create entirely new GNOME apps using Swift, achieving great code readability and memory safety.
126+
127+
## Publish Apps
128+
129+
In addition to traditional distribution packages, Adwaita for Swift works great with [Flathub](https://flathub.org).
130+
Flathub is an app store powered by [Flatpak](https://flatpak.org/) which simplifies the installation and publishing of apps for desktop Linux.
131+
132+
There is the [Freedesktop SDK Extension for Swift 5](https://flathub.org/apps/org.freedesktop.Sdk.Extension.swift5) which adds support for Swift, and a [tool to convert Swift Package Manager dependencies into Flatpak sources](https://github.com/flatpak/flatpak-builder-tools/tree/master/spm).
133+
134+
Learn how to publish your apps [in the Adwaita for Swift documentation](https://david-swift.gitbook.io/adwaita/advanced/publishingapps).
135+
136+
## Get Involved
137+
138+
Each contribution to this project is highly appreciated.
139+
140+
You can:
141+
- Create an app! Use the [template repository](https://github.com/AparokshaUI/AdwaitaTemplate) as a starting point and refer to the [tutorial](https://david-swift.gitbook.io/adwaita/gettingstarted). Feel free to showcase your project in the [discussions](https://github.com/AparokshaUI/adwaita-swift/discussions/categories/show-and-tell). Note that libadwaita works best on Linux. If you're on a newer Mac and interested in Linux, check out [Asahi Linux](https://asahilinux.org/fedora/?ref=upstract.com).
142+
- Open [issues](https://github.com/AparokshaUI/adwaita-swift/issues) if you find any problems or if you have an idea, or participate in the [dicussions](https://github.com/AparokshaUI/adwaita-swift/discussions) by asking questions, dicussing ideas, or informing others about your work.
143+
- Write [documentation](https://david-swift.gitbook.io/adwaita/) to help others understand Adwaita for Swift.
144+
- Simply star the [repository](https://github.com/AparokshaUI/adwaita-swift) to improve its discoverability.
145+
- Take a look at the [Memorize](https://flathub.org/apps/io.github.david_swift.Flashcards) app. It is the first app on Flathub built using Adwaita for Swift.
146+
147+
Thanks for your participation ❤️
148+
8.43 KB
Loading

0 commit comments

Comments
 (0)