Skip to content

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

License

Notifications You must be signed in to change notification settings

ShenghaiWang/SwiftMacros

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

71 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SwiftMacros

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

Install

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

Macros API Doc

Macro Description
@Access An easy API to access UserDefaults, Keychain, NSCache and NSMapTable.
struct TestAccess {
static let cache = NSCache<NSString, AnyObject>()

// Please make sure the generic type is the same as the type of the variable
// Without defalut value
@Access<Bool?>(.userDefaults())
var isPaidUser: Bool?

// With default value
@Access< Bool>(.userDefaults())
var isPaidUser2: Bool = false

@Access<NSObject?>(.nsCache(TestAccess.cache))
var hasPaid: NSObject?

@Access<NSObject?>(.nsMapTable(TestAccess.mapTable))
var hasPaid2: NSObject?

@Access<TestStruct?>(.keychain)
var keychainValue: TestStruct?
}
@AddAssociatedValueVariable Add variables to retrieve the associated values
@AddAssociatedValueVariable
enum MyEnum {
case first
case second(Int)
case third(String, Int)
case forth(a: String, b: Int), forth2(String, Int)
case fifth(() -> Void)
}
@AddInit Generate 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.
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.
@AddPublisher Generate a Combine publisher to a Combine subject in order to avoid overexposing subject variable
@AddPublisher
private let mySubject = PassthroughSubject<Void, Never>()
@AddInit
struct InitStruct {
let a: Int
let b: Int?
let c: (Int?) -> Void
let d: ((Int?) -> Void)?
}
@AddInit(withMock: true)
class AStruct {
let a: Float
}
#buildDate Build a Date from components
This solution addes in a resultBulder DateBuilder, which can be used directly if prefer builder pattern.
Note: this is for a simpler API. Please use it with caution in places that require efficiency.
let date = #buildDate(DateString("03/05/2003", dateFormat: "MM/dd/yyyy"),
Date(),
Month(10),
Year(1909),
YearForWeekOfYear(2025))
#buildURL Build a url from components.
This solution addes in a resultBulder URLBuilder, which can be used directly if prefer builder pattern.
let url = #buildURL("http://google.com",
URLScheme.https,
URLQueryItems([.init(name: "q1", value: "q1v"), .init(name: "q2", value: "q2v")]))
let url2 = buildURL {
"http://google.com"
URLScheme.https
URLQueryItems([.init(name: "q1", value: "q1v"), .init(name: "q2", value: "q2v")])
}
#buildURLRequest Build a URLRequest from components.
This solution addes in a resultBulder URLRequestBuilder, which can be used directly if prefer builder pattern.
let urlrequest = #buildURLRequest(url!, RequestTimeOutInterval(100))
let urlRequest2 = buildURLRequest {
url!
RequestTimeOutInterval(100)
}
@ConformToEquatable Add Equtable conformance to a class type
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
@AddInit
@ConformToEquatable
class AClass {
let a: Int?
let b: () -> Void
}
@ConformToHashable Add Hashable conformance to a class type
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
@AddInit
@ConformToHashable
class AClass {
let a: Int?
let b: () -> Void
}
#encode Encode an Encodable to data using JSONEncoder
#encode(value)
#decode Decode a Decodable to a typed value using JSONDecoder
#decode(TestStruct.self, from: data)
#formatDate Format date to a string
#formatDate(Date(), dateStyle: .full)
#formatDateComponents Format date differences/timeinterval/date components to a string
#formatDateComponents(from: Date(), to: Date(), allowedUnits: [.day, .hour, .minute, .second])
#formatDateComponents(fromInterval: 100, allowedUnits: [.day, .hour, .minute, .second])
#formatDateComponents(fromComponents: DateComponents(hour: 10), allowedUnits: [.day, .hour, .minute, .second])
#formatDateInterval Format two dates into interval string
#formatDateInterval(from: Date(), to: Date(), dateStyle: .short)
@Mock Generate a static variable mock using the attached initializer.
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.
class AStruct {
let a: Float
@Mock(type: AStruct.self)
init(a: Float) {
self.a = a
}
}
#postNotification An easy way to post notifications
#postNotification(.NSCalendarDayChanged)
@Singleton Generate Swift singleton code for struct and class types
@Singleton
struct A {}

To be added

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

Macro Description
@ Your new macro ideas

About

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

Resources

License

Stars

Watchers

Forks

Sponsor this project

 

Packages

No packages published

Languages