Home

Awesome

SwiftMacros

A practical collection of Swift Macros that help code correctly and swiftly.

Install

.package(url: "https://github.com/ShenghaiWang/SwiftMacros.git", from: "1.0.0")

Macros API Doc

MacroDescription
@AccessAn easy API to access UserDefaults, Keychain, NSCache and NSMapTable.
<pre>struct TestAccess {<br> static let cache = NSCache<NSString, AnyObject>()<br><br> // Please make sure the generic type is the same as the type of the variable<br> // Without defalut value<br> @Access<Bool?>(.userDefaults())<br> var isPaidUser: Bool?<br><br> // With default value<br> @Access< Bool>(.userDefaults())<br> var isPaidUser2: Bool = false<br><br> @Access<NSObject?>(.nsCache(TestAccess.cache))<br> var hasPaid: NSObject?<br><br> @Access<NSObject?>(.nsMapTable(TestAccess.mapTable))<br> var hasPaid2: NSObject?<br><br> @Access<TestStruct?>(.keychain)<br> var keychainValue: TestStruct?<br>}</pre>
@AddAssociatedValueVariableAdd variables to retrieve the associated values
<pre>@AddAssociatedValueVariable<br>enum MyEnum {<br> case first<br> case second(Int)<br> case third(String, Int)<br> case forth(a: String, b: Int), forth2(String, Int)<br> case fifth(() -> Void)<br>}</pre>
@AddInitGenerate initialiser for the class/struct/actor. The variables with optional types will have nil as default values. Using withMock: true if want to generate mock data. <br> For custmoised data type, it will use Type.mock. In case there is no this value, need to define this yourself or use @Mock or @AddInit(withMock: true) to generate this variable.
@AddPublisherGenerate a Combine publisher to a Combine subject in order to avoid overexposing subject variable
<pre>@AddPublisher<br>private let mySubject = PassthroughSubject<Void, Never>()</pre>
<pre>@AddInit<br>struct InitStruct {<br> let a: Int<br> let b: Int?<br> let c: (Int?) -> Void<br> let d: ((Int?) -> Void)?<br>}<br>@AddInit(withMock: true)<br>class AStruct {<br> let a: Float<br>}</pre>
#buildDateBuild a Date from components<br>This solution addes in a resultBulder DateBuilder, which can be used directly if prefer builder pattern.<br>Note: this is for a simpler API. Please use it with caution in places that require efficiency.
<pre>let date = #buildDate(DateString("03/05/2003", dateFormat: "MM/dd/yyyy"),<br> Date(),<br> Month(10),<br> Year(1909),<br> YearForWeekOfYear(2025))</pre>
#buildURLBuild a url from components.<br>This solution addes in a resultBulder URLBuilder, which can be used directly if prefer builder pattern.
<pre>let url = #buildURL("http://google.com",<br> URLScheme.https,<br> URLQueryItems([.init(name: "q1", value: "q1v"), .init(name: "q2", value: "q2v")]))<br>let url2 = buildURL {<br> "http://google.com"<br> URLScheme.https<br> URLQueryItems([.init(name: "q1", value: "q1v"), .init(name: "q2", value: "q2v")])<br>}</pre>
#buildURLRequestBuild a URLRequest from components.<br>This solution addes in a resultBulder URLRequestBuilder, which can be used directly if prefer builder pattern.
<pre>let urlrequest = #buildURLRequest(url!, RequestTimeOutInterval(100))<br>let urlRequest2 = buildURLRequest {<br> url!<br> RequestTimeOutInterval(100)<br>}</pre>
@ConformToEquatableAdd Equtable conformance to a class type<br>Use it with caution per https://github.com/apple/swift-evolution/blob/main/proposals/0185-synthesize-equatable-hashable.md#synthesis-for-class-types-and-tuples
<pre>@AddInit<br>@ConformToEquatable<br>class AClass {<br> let a: Int?<br> let b: () -> Void<br>}</pre>
@ConformToHashableAdd Hashable conformance to a class type<br>Use it with caution per https://github.com/apple/swift-evolution/blob/main/proposals/0185-synthesize-equatable-hashable.md#synthesis-for-class-types-and-tuples
<pre>@AddInit<br>@ConformToHashable<br>class AClass {<br> let a: Int?<br> let b: () -> Void<br>}</pre>
#encodeEncode an Encodable to data using JSONEncoder
<pre>#encode(value)</pre>
#decodeDecode a Decodable to a typed value using JSONDecoder
<pre>#decode(TestStruct.self, from: data)</pre>
#formatDateFormat date to a string
<pre>#formatDate(Date(), dateStyle: .full)</pre>
#formatDateComponentsFormat date differences/timeinterval/date components to a string
<pre>#formatDateComponents(from: Date(), to: Date(), allowedUnits: [.day, .hour, .minute, .second])<br>#formatDateComponents(fromInterval: 100, allowedUnits: [.day, .hour, .minute, .second])<br>#formatDateComponents(fromComponents: DateComponents(hour: 10), allowedUnits: [.day, .hour, .minute, .second])</pre>
#formatDateIntervalFormat two dates into interval string
<pre>#formatDateInterval(from: Date(), to: Date(), dateStyle: .short)</pre>
@MockGenerate a static variable mock using the attached initializer. <br>For custmoised data type, it will use Type.mock. In case there is no this value, need to define this yourself or use @Mock or @AddInit(withMock: true) to generate this variable.
<pre>class AStruct {<br> let a: Float<br> @Mock(type: AStruct.self)<br> init(a: Float) {<br> self.a = a<br> }<br>}</pre>
#postNotificationAn easy way to post notifications
<pre>#postNotification(.NSCalendarDayChanged)</pre>
@SingletonGenerate Swift singleton code for struct and class types
<pre>@Singleton<br>struct A {}</pre>

To be added

Please feel free to add the macros you want here. All PRs(with or without implementations) are welcome.

MacroDescription
@Your new macro ideas