Over the source of Caramel’s development, I struggled with organizing code using extensions. One of the reasons I disliked them was because it was very easy to lose track of logic by abstracting functionality in other files without any direct connection which made maintenance hard as you had to mentally hold together the broadness of an object. This is one of my issues with WordPress’s Filters and Actions system, but alas, is a pattern found everywhere in modern programming. So, I adapt.
In an effort to get over this, I spent some time pooling together resources from Swift Experts on the web and the tricks I was able to learn have been phenomenal.
First off, Bart Jacobs reviews a few tricks related to Protocol Conformance, Preserving Initializers, Code Separation, and Nested Types.
I find the preserving initializers trick especially brilliant, since it allows us to use Swifts auto generation while allowing you to add initializers:
struct Fruit { let color: UIColor let sweetness: Int } extension Fruit { init(_ dictionary: [String: Any]) { self.color = dictionary["color"] as? UIColor ?? .yellow self.sweetness = dictionary["sweetness"] as? Int ?? 5 } } let banana = Fruit(color: .yellow, sweetness: 5); let orange = Fruit(["color": UIColor.orange, "sweetness": 6]);
(There’s a full, better example in the post linked above)
In Swift Essentials: Extensions by Joe Rossano, there’s the same from tips from Clever Uses above are there, but there’s an additional tip that I really like: Computed Properties. This, in combination with Protocol Conformance, is super powerful in many different cases.
In one, Caramel has multiple targets and imported into each is the same Model wrapped in a framework. Often, I’ll need to extend the usages for target specific logic without affecting the original model object:
// CarmaelKit.framework struct Recipe { var name: String var uri: String } // CarmaralSearch.Target protocol SearchableEntity { var searchURI: String { get } } extension Recipe: SearchableEntity { var searchURI: String { get { return self.uri } } }
And finally, Natasha The Robot, a staple in my feed, goes over her uses for loving extensions, including a little bit of historical background. A general rehashing of some of the other benefits and usages of Swift, there’s a golden nugget in the comments by stephencelis:
The Swift core team loves to use extensions for the same reasons 🙂
This is from the first public stdlib file I could find: https://github.com/apple/sw…. The extensions are used purely for grouping. There are plenty more examples where extensions are used for protocol conformance (_e.g._ this set: https://github.com/apple/sw….
The two links are great: Being able to see the Swift core team’s own usages help clear up how to use them a little better. Often you’ll find extensions used for grouping within the same file, rather than an external one.
There’s a lot of powerful Swift resources out there, especially for something as common as extensions, but here is a small group of great articles that I reference often and hopefully can be of value to you!