Learn Swift - Advanced Data Types & Collections
Episode 4 of 23

Learn Swift - Advanced Data Types & Collections

This episode covers Swift's advanced data types: Array, Dictionary, Set, and tuples as collections, optionals with optional chaining and nil coalescing, enums with associated values and raw values, as well as the fundamental difference between struct and class in value semantics and reference semantics.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

After mastering the basic syntax, you need tools to model real data. Episode 4 covers Swift's advanced data types and collections — Array, Dictionary, Set, tuples, optionals, and enums — which form the backbone of every application, from data models to state management.

In this episode we also dissect one of the most important and most misunderstood concepts: the difference between struct and class in value semantics versus reference semantics. Choosing one over the other will affect your application's performance, thread safety, and overall design.

Basic Collections

Array, Dictionary, and Set

Swift's three main collections serve different needs:

  • Array: an ordered collection; elements can be equal in value.
  • Dictionary: key-value pairs with unique keys.
  • Set: an unordered collection of unique values.
Create and modify collections
var kota = ["Jakarta", "Bandung", "Surabaya"]
kota.append("Yogyakarta")
print(kota.count)
 
var populasi = ["Jakarta": 10_562_088, "Bandung": 2_444_160]
populasi["Surabaya"] = 2_874_314
 
let favorit: Set = ["swift", "rust", "swift"]
print(favorit)

kota.append("Yogyakarta") adds an element to the end of an Array. Set automatically deduplicates: favorit only stores swift once. Choosing the right collection simplifies your logic — use Set for membership testing and preventing duplication.

Tuple

A tuple combines several values into a single compound value without needing a dedicated type:

Tuple with labels
let koordinat = (x: 10, y: 20)
let (x, y) = koordinat
print("Lokasi: \(x), \(y)")

(x: 10, y: 20) creates a tuple with labels that can be accessed directly. Tuples are useful for concise, temporary function return values — for data used repeatedly, defining a struct is better.

Optionals

Handling Uncertain Values

Optional is the core feature that sets Swift apart from its predecessors: a value can either exist or not, and the compiler forces you to handle both possibilities. Optional declarations are marked with a question mark:

Optional and nil coalescing
var namaPengguna: String? = nil
let teksTampil = namaPengguna ?? "Tamu"
 
print(teksTampil)

The ?? operator — nil coalescing — provides a default value when the optional is empty. namaPengguna ?? "Tamu" avoids accessing nil without writing an entire if-let block.

Optional Chaining

To access properties or methods inside an optional, use optional chaining with a question mark:

Optional chaining
struct Profil {
    var nama: String
    var bio: String?
}
 
let profil = Profil(nama: "Arman", bio: "Cloud Engineer")
let bioPanjang = profil.bio?.count ?? 0
print(bioPanjang)

profil.bio?.count returns nil if bio is nil, and otherwise returns the count value. The chain stops safely at the first nil point — this pattern eliminates a lot of defensive branching.

Enums

Raw Values and Associated Values

Enum in Swift is far more powerful than the enum in C: it can carry raw values as well as associated values:

Enum with raw value
enum StatusKoneksi: String {
    case online = "terhubung"
    case offline = "putus"
}
 
let status = StatusKoneksi.online
print(status.rawValue)
Enum with associated value
enum Hasil {
    case sukses(data: String)
    case gagal(pesan: String)
}
 
let hasil = Hasil.gagal(pesan: "Timeout")
print(hasil)

case sukses(data: String) carries extra data attached to the case. Combined with switch and pattern matching, enums become the safest way to represent states and operation results — we'll use them again in episode 6 for error handling.

Struct vs Class

Value Semantics and Reference Semantics

The most fundamental difference between struct and class lies in how values are copied:

  • Struct: value semantics — every assignment copies a new, independent value.
  • Class: reference semantics — assignment shares a reference to the same instance.
Value vs reference
struct Titik {
    var x: Int
    var y: Int
}
 
var a = Titik(x: 1, y: 2)
var b = a
b.x = 99
print(a.x, b.x)
 
class Kereta {
    var posisi = 0
}
 
let k1 = Kereta()
let k2 = k1
k2.posisi = 10
print(k1.posisi, k2.posisi)

With a struct, changing b.x doesn't change a because b is a copy. With a class, k1 and k2 point to the same object, so both read 10.

When to Choose Which

Swift's widely accepted guideline: default to struct. Structs give natural immutability, are safe for concurrency, and are cheap thanks to copy-on-write. Use classes when you need identity (two references must point to the same object), inheritance, or interop with reference-based Objective-C APIs.

Info

The Swift compiler optimizes struct copies with copy-on-write: a real copy only happens when the value is modified. So using structs doesn't mean copying large data on every assignment.

Closing

Key takeaways:

  • Array, Dictionary, and Set serve different collection needs.
  • Tuples combine several values without a dedicated type.
  • Optionals are forced to be handled by the compiler; ?? provides a default value when nil.
  • Optional chaining ?. keeps property access safe.
  • Swift enums support raw values and associated values.
  • Structs use value semantics and are the default choice; classes use reference semantics for identity and inheritance.

In the next episode, episode 5, we'll cover object-oriented programming and protocols — classes, inheritance, and method overriding, access control from public to private, protocols with protocol extensions as the core of protocol-oriented programming, and generics with type constraints. Let's continue!