Philip
Philip

Reputation: 1606

Use function to define struct properties in Swift

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

Answers (1)

David Berry
David Berry

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

Related Questions