Reputation: 1606
I'm using Swift to create a large number of structs, all of which follow mostly the same pattern. Each struct contains a number of computed properties with getters and setters, the only difference between each struct type is the number of computed properties and the name and type of each. For example,
struct Employee
{
var title: String
{
get { /*...*/ return someDict["title"] as! String }
set { /*...*/ }
}
var id: Int
{
get { /*...*/ return someDict["id"] as! Int }
set { /*...*/ }
}
var salary: Double
{
get { /*...*/ return someDict["salary"] as! Double }
set { /*...*/ }
}
}
struct Student
{
var name: String
{
get { /*...*/ return someDict["name"] as! String }
set { /*...*/ }
}
var gpa: Double
{
get { /*...*/ return someDict["gpa"] as! Double }
set { /*...*/ }
}
}
Now, each of the getters and setters is pretty much identical across the different structs, the only difference being that each refers to a hard-coded string representation of the computed property name and to its type.
This is kind of cumbersome and repetitive. It's hard to just glance at the struct and see what properties it contains and involves a lot of repeated code. I considered just making a protocol with the required properties and adopting in the struct, that way at least the protocol would be more readable, but it doesn't solve the repeated code issue. What I'd like to do is define something like a macro that defines these properties, like,
#define PROPERTY(NAME, TYPE) var NAME: TYPE { get{...} set{...} }
Then each struct could be much more readable and there'd be a lot less repeated code, like,
struct Employee
{
PROPERTY(title, String)
PROPERTY(id, Int)
PROPERTY(salary, Double)
}
struct Student
{
PROPERTY(name, String)
PROPERTY(gpa, Double)
}
Is there a way to do such a thing in Swift? Or is there a better approach I should consider? I'd like a pure Swift solution as I'm running on Linux (incomplete Foundation).
Upvotes: 3
Views: 463
Reputation: 41226
The best approach that I could come up with would be to create an external script which takes as input a some sort of simplified template and spits out a .swift file, run as a precompile build phase. Something like:
Input.notswift:
extension Employee {
PROPERTY(title, String, "title")
}
and then run (something like, the escaping is all wrong) as a precompile build phase:
sed s/PROPERTY\(([^,]*), ([^,]*), ([^,]*)\)/var NAME: TYPE { get{...} set{...} }/ < Input.notswift > Properties.swift
Alternatively, you could manually run the C-preprocessor on Input.notswift to generate Input.swift. Once you decide to take the preprocess approach there's an endless list of mechanisms you can use to generate .swift from .notswift.
Upvotes: 1