I've recently gotten addicted to Extensions
. One thing I've found to be a gigantic PITA is figuring where I stashed a useful method for something like an Array
, an NSManagedObject
, etc.
What I've done is put my extensions in an NSObject
class file called CustomExtensions
and I list the Class Extensions there in alphabetical order.
It works, but I want to see if it aligns with best practices. If not, what is the best way to track Extensions
?
Here's what I've done:
class CustomExtensions: NSObject {
/*
Useful extensions, nothing else here
*/
}
// Example extension
extension Int {
func formatAsTimeString() -> String {
let seconds = self % 60
let minutes = (self / 60) % 60
let hours = self / 3600
let stringHours = hours > 9 ? String(hours) : "0" + String(hours)
let stringMinutes = minutes > 9 ? String(minutes) : "0" + String(minutes)
let stringSeconds = seconds > 9 ? String(seconds) : "0" + String(seconds)
if hours > 0 {
return "\(stringHours):\(stringMinutes):\(stringSeconds)"
}
else {
return "\(stringMinutes):\(stringSeconds)"
}
}
}
// More extensions below
I don't think the "best practices" around this issue have been figured out yet. That said, here is MHO:
Ultimately, I treat these extensions the same way I do global functions in C. After all, that's basically what they are. Global functions with a special syntax...
If the extension is only used in one file, then I will put the extension in the same file. I end up with quite a few of these by the time I'm done. For example, your formatAsTimeString
is a view model kind of thing. If it is used by a single view controller, I would leave it in the view controller's file.
If the extension is used by multiple classes, then I will break it out into a separate file. I will name the file after the extension. So for example if the formatAsTimeString
is used in multiple files, then I will have a file named something like, "Int+formatAsTimeString.swift" where the extension can live.
If there are a number of related functions, then I will put them together in the same file and name the file based on the abstract idea of the functions. I decide that the functions are related by imagining whether they would all have to be moved together if I choose to use them in a different program... For example, maybe I have other time string related functions...
With Swift3, I generally tend to use 'fileprivate' if the extension is only used in one file.
fileprivate extension Date
{
func toString( dateFormat format : String ) -> String
{
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = format
return dateFormatter.string(from: self)
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With