Swift adalah bahasa pemrograman Apple yang menggabungkan kekuatan Objective-C dengan keamanan bahasa modern. Tidak seperti banyak bahasa lainnya, Swift menawarkan konstruksi unik: tipe nilai dengan penyalinan otomatis, Actor dengan isolasi tingkat kompiler, Property Wrappers untuk menggunakan kembali logika properti, dan Pemrograman Berorientasi Protokol sebagai alternatif pewarisan klasik. Menurut Dokumentasi Apple Swift, fitur-fitur ini membuat kode lebih aman dan efisien.
Poin Penting
Di Swift, struct adalah tipe nilai, sedangkan class adalah tipe referensi. Perbedaan mendasar ini menentukan perilaku selama penugasan, penerusan ke fungsi, dan manajemen memori. Struct disalin seluruhnya pada setiap penugasan, class diteruskan oleh referensi — hanya penunjuk ke objek heap yang disalin.
Struct secara otomatis menerapkan semantik nilai — setiap instance independen. Mutasi properti struct hanya mungkin melalui var, dan metode yang mengubah properti harus ditandai sebagai mutating. Struct tidak mendukung pewarisan tetapi dapat sesuai dengan protokol. Pustaka standar Swift menggunakan struct untuk String, Array, Dictionary, Int, Bool — semua tipe fundamental adalah tipe nilai.
struct User {
let id: Int
var name: String
mutating func updateName(_ newName: String) {
name = newName
}
}
var user1 = User(id: 1, name: "Alice")
var user2 = user1
user2.updateName("Bob")
// user1.name === "Alice", user2.name === "Bob"
// Salinan lengkap — instance independen
Class disimpan di heap dan mendukung kesetaraan referensi. Beberapa variabel dapat mereferensi objek yang sama, perubahan melalui satu referensi terlihat melalui semua referensi lainnya. Class mendukung pewarisan, memungkinkan penggantian metode (override), memiliki deinit untuk pembersihan sumber daya. Di Swift, class lebih jarang digunakan daripada struct — Apple merekomendasikan memulai dengan struct dan beralih ke class hanya ketika pewarisan atau semantik referensi diperlukan.
class Car {
let model: String
var speed: Int
init(model: String, speed: Int) {
self.model = model
self.speed = speed
}
func accelerate(_ amount: Int) {
speed += amount
}
}
let car1 = Car(model: "Tesla", speed: 0)
let car2 = car1
car2.accelerate(50)
// car1.speed === 50, car2.speed === 50
// Referensi yang sama — perubahan terlihat di mana-mana
Pilihan antara struct dan class tergantung pada semantik data. Untuk konfigurasi, model data, dan status gunakan struct — penyalinan lebih aman dan dapat diprediksi. Untuk objek dengan identitas (sesi pengguna, koneksi database) dan ketika pewarisan diperlukan, gunakan class.
Actor adalah tipe referensi yang melindungi status yang dapat diubah dari akses bersamaan. Kompiler Swift menjamin bahwa variabel actor hanya dapat diakses dari konteks actor yang sama — akses eksternal apa pun menyebabkan kesalahan kompilasi. Ini mencegah perlombaan data di tingkat bahasa, tanpa kunci manual.
Semua properti dan metode actor diisolasi secara default. Memanggil metode actor dari luar memerlukan await — Swift mengalihkan eksekusi ke actor dan kembali. Actor menyinkronkan akses secara berurutan: permintaan dari tugas yang berbeda diantrekan. Ini menjamin status yang konsisten di dalam actor. Metode yang tidak terisolasi (nonisolated) dapat dipanggil tanpa await tetapi tidak dapat mengakses properti yang dapat diubah.
actor BankAccount {
private var balance: Double
init(initialBalance: Double) {
balance = initialBalance
}
func deposit(amount: Double) {
balance += amount
}
func withdraw(amount: Double) throws {
guard balance >= amount else {
throw BankError.insufficientFunds
}
balance -= amount
}
nonisolated func accountInfo() -> String {
return "Rekening Bank"
}
}
let account = BankAccount(initialBalance: 1000)
await account.deposit(amount: 500)
// balance = 1500 — atomik, tanpa kondisi balapan
Actor berguna untuk manajer status, cache, dan layanan jaringan di mana beberapa tugas membaca dan menulis data secara bersamaan. Tidak seperti sinkronisasi manual melalui NSLock atau DispatchQueue, actor diperiksa pada waktu kompilasi — tidak mungkin membuat kesalahan. Kesalahan isolasi muncul pada waktu kompilasi, bukan waktu proses.
Property Wrapper adalah anotasi yang menambahkan perilaku ke properti tanpa mengubah deklarasinya. SwiftUI dan Combine menyediakan pembungkus bawaan untuk mengelola status tampilan. Kompiler menghasilkan kode yang membungkus akses properti, menambahkan logika observasi, sinkronisasi, atau transformasi.
@Published digunakan di kelas yang sesuai dengan ObservableObject untuk mempublikasikan perubahan secara otomatis. Pelanggan Combine menerima notifikasi pada setiap pembaruan. @State adalah status lokal tampilan SwiftUI. SwiftUI secara otomatis menggambar ulang tampilan saat @State berubah. @Binding membuat koneksi dua arah antara tampilan induk dan anak tanpa memiliki data.
import SwiftUI
import Combine
@main
struct CounterApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
class CounterViewModel: ObservableObject {
@Published var count: Int = 0
func increment() {
count += 1
}
}
struct ContentView: View {
@State private var greeting: String = "Halo"
@StateObject private var viewModel = CounterViewModel()
var body: some View {
VStack {
CounterDisplay(count: $viewModel.count)
Text(greeting)
Button("Tambah", action: viewModel.increment)
}
}
}
struct CounterDisplay: View {
@Binding var count: Int
var body: some View {
Text("Hitungan: \(count)")
}
}
Property Wrappers khusus dibuat menggunakan @propertyWrapper dan struktur dengan bidang wrappedValue. Ini memungkinkan penggunaan kembali logika: validasi, normalisasi, penyimpanan UserDefaults. Property Wrappers secara signifikan mengurangi kode boilerplate dan membuat niat pengembang eksplisit melalui anotasi.
@propertyWrapper
struct Clamped<T: Comparable> {
private var value: T
let range: ClosedRange<T>
init(wrappedValue: T, range: ClosedRange<T>) {
self.range = range
self.value = min(max(wrappedValue, range.lowerBound), range.upperBound)
}
var wrappedValue: T {
get { value }
set { value = min(max(newValue, range.lowerBound), range.upperBound) }
}
}
struct Settings {
@Clamped(range: 0...100) var volume: Int = 50
}
var s = Settings()
s.volume = 150
// s.volume === 100 — nilai otomatis dibatasi
Generics adalah mekanisme Swift yang kuat untuk menulis kode fleksibel tanpa kehilangan keamanan tipe. Fungsi dan tipe generik bekerja dengan tipe apa pun yang memenuhi batasan. Pemrograman Berorientasi Protokol (POP) adalah paradigma Swift di mana protocol + extension menggantikan pewarisan kelas klasik, menyediakan komposisi perilaku.
Swift memungkinkan membatasi parameter generik dengan protokol (klausa where). Protokol dengan tipe terkait adalah padanan generik untuk protokol: tipe konkret ditentukan pada saat kesesuaian. Ini adalah dasar untuk koleksi dan algoritma type-safe. Pustaka standar Swift secara aktif menggunakan Generics: Array, Dictionary, Optional — semuanya adalah tipe generik.
protocol Cacheable {
associatedtype Key: Hashable
associatedtype Value
func get(_ key: Key) -> Value?
mutating func set(_ value: Value, for key: Key)
}
struct MemoryCache<K: Hashable, V>: Cacheable {
private var storage: [K: V] = [:]
typealias Key = K
typealias Value = V
func get(_ key: K) -> V? {
return storage[key]
}
mutating func set(_ value: V, for key: K) {
storage[key] = value
}
}
func firstMatch<T: Equatable>(in array: [T], target: T) -> Int? {
for (index, item) in array.enumerated() {
if item == target {
return index
}
}
return nil
}
let numbers = [10, 20, 30, 40]
let index = firstMatch(in: numbers, target: 30)
// index === 2 — satu metode generik untuk semua tipe Equatable
Extension protokol adalah mekanisme kunci POP. Dalam extension, implementasi default metode protokol dapat disediakan. Tipe yang sesuai dengan protokol mendapatkan implementasi ini secara gratis dan dapat menimpanya jika diperlukan. Ini memungkinkan pembangunan hierarki perilaku tanpa pewarisan kelas — alternatif untuk pewarisan berganda, yang tidak ada di Swift.
protocol Drivable {
var speed: Double { get set }
func drive()
}
extension Drivable {
func drive() {
if speed > 0 {
print("Mengemudi dengan kecepatan \(speed) km/jam")
}
}
}
struct Bicycle: Drivable {
var speed: Double = 15
}
struct Plane: Drivable {
var speed: Double = 900
func drive() {
print("Terbang dengan kecepatan \(speed) km/jam")
}
}
let bike = Bicycle()
bike.drive() // "Mengemudi dengan kecepatan 15.0 km/jam" — default
let plane = Plane()
plane.drive() // "Terbang dengan kecepatan 900.0 km/jam" — ditimpa
POP dengan extension memungkinkan komposisi melalui beberapa protokol — sebuah tipe dapat sesuai dengan beberapa protokol, mendapatkan implementasinya. Ini lebih fleksibel daripada pewarisan kelas tunggal di mana seluruh hierarki tetap. Pustaka standar Swift dibangun di atas POP: CustomStringConvertible, Equatable, Hashable, Codable — semuanya adalah protokol dengan extension.
Enum di Swift adalah konstruksi yang jauh lebih kuat daripada di bahasa lain. Setiap kasus dapat memiliki nilai terkait — kumpulan data arbitrer dari tipe apa pun. Dikombinasikan dengan extension dan pencocokan pola, enum menjadi dasar untuk memodelkan status, hasil operasi, dan mesin status terbatas.
Nilai terkait memungkinkan setiap kasus menyimpan data unik. Misalnya, kasus loading tidak mengandung data, success mengandung hasil, failure mengandung kesalahan. Pencocokan pola melalui switch mengekstrak nilai terkait dan memproses setiap kasus. Kompiler memeriksa kelengkapan (exhaustive switch) — ini menghilangkan status yang terlupakan.
enum NetworkResult<T> {
case loading
case success(T)
case failure(Error)
}
enum MediaFile {
case image(url: URL, width: Int, height: Int)
case video(url: URL, duration: Double)
case audio(url: URL, bitrate: Int)
}
func handle(_ result: NetworkResult<String>) {
switch result {
case .loading:
print("Memuat...")
case .success(let data):
print("Diterima: \(data)")
case .failure(let error):
print("Kesalahan: \(error.localizedDescription)")
}
}
let file = MediaFile.video(url: URL(string: "https://example.com/video.mp4")!, duration: 120)
if case .video(let url, let duration) = file {
print("Video \(url) durasi \(duration)s")
}
Swift memungkinkan penambahan metode, properti terhitung, dan kesesuaian protokol melalui extension untuk enum. Ini tidak memerlukan perubahan deklarasi asli — kode tetap bersih dan modular. Metode dalam extension dapat bekerja dengan nilai terkait, menghitung data turunan, dan menerapkan logika bisnis.
extension MediaFile {
var fileName: String {
switch self {
case .image(let url, _, _),
.video(let url, _),
.audio(let url, _):
return url.lastPathComponent
}
}
var description: String {
switch self {
case .image(_, let w, let h):
return "Gambar \(w)x\(h)"
case .video(_, let d):
return "Video \(d)s"
case .audio(_, let b):
return "Audio \(b) kbps"
}
}
}
extension MediaFile: Equatable {
static func == (lhs: MediaFile, rhs: MediaFile) -> Bool {
return lhs.fileName == rhs.fileName
}
}
let files: [MediaFile] = [file]
files.forEach { print($0.description) }
// "Video 120.0s"
Enum dengan nilai terkait + extension adalah pengganti untuk kelas tersegel dari Kotlin atau union yang didiskriminasi dari bahasa lain. Swift menggunakan kombinasi ini untuk Result (tipe standar di pustaka standar), Optional (Optional adalah enum dengan .none dan .some) dan penanganan status di SwiftUI. Pencocokan pola menjamin semua status ditangani — kesalahan waktu proses tidak mungkin terjadi.
Pertanyaan yang Sering Diajukan
Struct — tipe nilai, disalin saat penugasan, tidak mendukung pewarisan. Class — tipe referensi, diteruskan oleh referensi, mendukung pewarisan, deinit dan pemeriksaan identitas (===). Apple merekomendasikan memulai dengan struct dan beralih ke class hanya ketika semantik referensi diperlukan.
Actor — tipe referensi thread-safe. Kompiler mencegah akses bersamaan ke status yang dapat diubah dari konteks yang berbeda. Gunakan Actor untuk manajer status, cache, dan layanan yang diakses oleh beberapa tugas. Memanggil metode actor memerlukan await.
Utama: @State — status tampilan lokal; @Binding — koneksi data tanpa kepemilikan; @Published — publikasi perubahan di ObservableObject; @StateObject — kepemilikan ObservableObject; @EnvironmentObject — ketergantungan dari lingkungan. Pembungkus khusus dibuat melalui @propertyWrapper.
POP — paradigma di mana protocol + extension mendefinisikan perilaku, bukan pewarisan kelas. Sebuah tipe sesuai dengan beberapa protokol, mendapatkan implementasinya secara gratis. Ini adalah komposisi daripada pewarisan — lebih fleksibel dan aman. Pustaka standar Swift (Equatable, Codable) dibangun di atas POP.
Enum di Swift mendukung nilai terkait — setiap kasus dapat menyimpan data arbitrer dari berbagai tipe. Dikombinasikan dengan pencocokan pola (switch), ini memberikan model yang kuat untuk status, kesalahan, dan Domain-Driven Design. Optional dan Result adalah enum Swift standar dengan nilai terkait.
Ringkasan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.