3. Jenis-Jenis Swift Macro
3. Jenis-Jenis Swift Macro
Swift Macro dibagi menjadi dua kategori besar: Freestanding dan Attached.
Freestanding Macro (#macroName)
Freestanding macro dipanggil secara independen menggunakan prefix #. Tidak menempel pada deklarasi lain.
3.1 Expression Macro
Menghasilkan sebuah ekspresi (nilai). Bisa digunakan di mana saja ekspresi diizinkan.
@freestanding(expression)
public macro stringify<T>(_ value: T) -> (T, String) = #externalMacro(
module: "MyMacrosMacros", type: "StringifyMacro"
)
// Penggunaan:
let (value, src) = #stringify(42 * 2) // menghasilkan ekspresi
3.2 Declaration Macro
Menghasilkan satu atau lebih deklarasi baru (fungsi, struct, class, dll). Digunakan di level file atau type body.
@freestanding(declaration, names: named(makeGreeting))
public macro makeGreeting(for name: String) = #externalMacro(
module: "MyMacrosMacros", type: "MakeGreetingMacro"
)
// Penggunaan — di level file:
#makeGreeting(for: "World")
// Menghasilkan fungsi:
// func greetWorld() -> String { "Hello, World!" }
Attached Macro (@MacroName)
Attached macro menempel pada deklarasi Swift (class, struct, func, property, dll) dan menghasilkan kode tambahan berdasarkan deklarasi tersebut.
3.3 @attached(member) — Tambah Member ke Type
Menambahkan property, fungsi, atau initializer baru ke dalam type.
@attached(member, names: named(init))
public macro AutoInit() = #externalMacro(
module: "MyMacrosMacros", type: "AutoInitMacro"
)
// Penggunaan:
@AutoInit
struct Point {
var x: Double
var y: Double
// ← macro generate: init(x: Double, y: Double)
}
3.4 @attached(memberAttribute) — Tambah Atribut ke Member
Menambahkan atribut ke setiap member dari type target (misal: menambahkan @Published ke semua property).
@attached(memberAttribute)
public macro AllPublished() = #externalMacro(
module: "MyMacrosMacros", type: "AllPublishedMacro"
)
// Penggunaan:
@AllPublished
class ViewModel: ObservableObject {
var name: String = "" // ← macro tambahkan @Published
var age: Int = 0 // ← macro tambahkan @Published
}
3.5 @attached(accessor) — Tambah getter/setter ke Property
Mengubah stored property menjadi computed property dengan getter/setter kustom.
@attached(accessor)
public macro UserDefaultsBacked<T>(_ key: String) = #externalMacro(
module: "MyMacrosMacros", type: "UserDefaultsBackedMacro"
)
// Penggunaan:
struct Settings {
@UserDefaultsBacked("username")
var username: String // ← macro generate getter/setter ke UserDefaults
}
3.6 @attached(conformance) — Tambah Protocol Conformance
Menambahkan konformitas protokol beserta implementasinya ke type.
@attached(conformance)
public macro AutoCodable() = #externalMacro(
module: "MyMacrosMacros", type: "AutoCodableMacro"
)
// Penggunaan:
@AutoCodable
struct Config {
var apiKey: String
var baseURL: URL
// ← macro generate: Codable conformance dengan custom CodingKeys
}
3.7 @attached(peer) — Generate Peer Declaration
Menghasilkan deklarasi baru yang "sejajar" (peer) dengan deklarasi target — misalnya membuat fungsi async dari fungsi sinkron.
@attached(peer, names: suffixed(Async))
public macro AddAsync() = #externalMacro(
module: "MyMacrosMacros", type: "AddAsyncMacro"
)
// Penggunaan:
@AddAsync
func fetchUser(id: String, completion: @escaping (User?) -> Void) { ... }
// ← macro generate:
// func fetchUserAsync(id: String) async -> User? { ... }
3.8 @attached(extension) — Generate Extension
Menghasilkan extension pada type (berbeda dengan conformance yang langsung pada deklarasi).
@attached(extension, conformances: CustomStringConvertible, names: named(description))
public macro AutoDescription() = #externalMacro(
module: "MyMacrosMacros", type: "AutoDescriptionMacro"
)
// Penggunaan:
@AutoDescription
struct Product {
let name: String
let price: Double
}
// ← macro generate:
// extension Product: CustomStringConvertible {
// var description: String { "Product(name: \(name), price: \(price))" }
// }
Ringkasan Jenis Macro
| Jenis | Sintaks | Menghasilkan | Posisi Penggunaan |
|---|---|---|---|
@freestanding(expression) |
#macro() |
Ekspresi/nilai | Di dalam ekspresi |
@freestanding(declaration) |
#macro() |
Deklarasi baru | Level file/type |
@attached(member) |
@Macro |
Member baru di type | Pada type |
@attached(memberAttribute) |
@Macro |
Atribut pada member | Pada type |
@attached(accessor) |
@Macro |
getter/setter | Pada property |
@attached(conformance) |
@Macro |
Protocol conformance | Pada type |
@attached(peer) |
@Macro |
Deklarasi sejajar | Pada func/property |
@attached(extension) |
@Macro |
Extension pada type | Pada type |