Swift Protocols & Extensions

Posted on Wed 19 February 2020 in swift


Another late day of 100 Days of Swift today, I spent all day grinding on iNat vision stuff. Hopefully some of the visualizations from that will make their way into a new blog post soon.

Today was protocols & extensions, super awesome features in Swift. I was lucky to be at the WWDC talk on protocol-oriented programming a few years ago, and I was blown away by it at the time. Still seems like a great language feature, and I can see great uses for it for iNat.

Here's a long code example:

enum TaxonRank: Int {
    case Species = 10
    case Genus = 20
    case Family = 30
    // ... etc

    func nameForCase() -> String {
        switch self {
        case .Species:
            return "Species"
        case .Genus:
            return "Genus"
        case .Family:
            return "Family"
        }
    }

    func isGenusOrHigher() -> Bool {
        return self.rawValue >= 20
    }
}


protocol Taxon {
    var rank: TaxonRank { get set }

    var scientificName: String { get set }
    var commonName: String? { get set }

    func isGenusOrHigher() -> Bool
    func displayName() -> String
}

// doesn't even address localization or user preferences for scientific or common names
extension Taxon {
    // can also be used for italicization rules, if I remember right
    func isGenusOrHigher() -> Bool {
        return rank.isGenusOrHigher()
    }

    func displayName() -> String {
        if let displayName = commonName {
            return displayName
        } else { 
            if isGenusOrHigher() {
                return "\(rank.nameForCase()) \(scientificName)"
            } else {
                return scientificName
            }
        }
    }
}


// from an api
struct TaxonFromJson: Decodable, Taxon {
    ...
}

// realm, for example
class TaxonPersistent: Object, Taxon {
    ...
}


let sls = TaxonPersistent(rank: .Genus, scientificName: "Deroceras", commonName: "Smooth Land Slugs")
print(sls.displayName())
let oxy = TaxonPersistent(rank: .Genus, scientificName: "Oxychilus", commonName: nil)
print(oxy.displayName())
let trl = TaxonPersistent(rank: .Species, scientificName: "Tritonia lineata", commonName: nil)
print(trl.displayName())

The lack of a console in Swift Playgrounds continues to annoy me, as does the subpar text editing. Why can't I select text that's below the screen, ie why can't the selector scroll?