Categories
Haiku

Haiku

Thursday (June 17th)

Haven’t been super.
Writing one every day is
hard for me. Learning.

Haiku is easy.
Making time is harder.
Open to suggestions.

Rosemary Rocksalt makes
delicious bagels. Poppy,
sesame are yummy.

Monday

Seem to be slipping
I missed three days. Must get
back into my groove

Dogs were here for a
Few days. Piper and Cooper
They were a handful!

Got my Moderna
On Sunday. My arm is sore.
Otherwise ok

Thursday

Heat wave is coming
Temperature is climbing
Stay cool and stay safe

Categories
Books

Broadening Horizons

I recently came across a quote that is playfully witty and wise. The character that is speaking is nine years old and has been home schooling, but now is facing the prospect of switching to learning in an actual school. Unfortunately she is reluctant. She is also a very clever lovable free spirit.

Sasha, the main character in the book, has just suggested that going to school will allow Nina to broaden her horizons. After she first asked Sasha to clarify what is meant by broadening one’s horizons, she says this:

Rather than sitting in orderly rows in a schoolhouse, wouldn’t one be better served by working her way toward an actual horizon, so that she could see what lay beyond it?

Nina Kulikova in A Gentleman in Moscow by Amor Towles

I find myself agreeing with her assertion. (as somebody who has occasionally enjoyed working his way toward actual horizons) But I also find myself confoundedly disagreeing (as a parent who has sometimes had to tell kids they need to do something they don’t want to do.)

For better or worse, Nina does go to school and is eventually swept up in life trials and tribulations. I don’t know if she would have been better served by heading toward actual horizons instead of the school house.

Categories
Hobbies

License Plates

I suspect the people close to me have noticed that I spend a lot of time looking at license plates. As kids, we would spend our time in the car searching for license plates and then trying to find words that used the letters on the license plate. (of course in the order they appeared on the plate.) So for example, for VCM 620 the first word I think of is ‘vacuum.’

As we got older, we’d get bonus points for things like having the first letter on the plate not be the first letter of the word. We would usually start by trying to get away with something like ‘revacuum’ or even ‘revacuumed’ to also pad the end of the word. But with time it became seen as lame to mindlessly stick a prefix and/or suffix on a word. Eventually we would aspire to have the first and last letters truly embedded. ‘Servicemen’ is a word, right?

I definitely don’t remember every license plate of every car we’ve ever owned, but I do remember quite a few. GEK is an early one I remember. We had an NBA for quite a long time. The first car I bought myself was an SKV. Our current car is an XAD. More than once, I think I’ve weirded out friends by knowing their license plates.

Sadly as the number of cars on the road continues to grow, the arrangements of letters and numbers on plates get more varied and creative. Ontario, for example, use 4 letters and three digits. BC has recently moved to AB1 23C as the format of choice. The headache for the Ontario scheme is making sure no curse words make it on any plates. (Three letter plates obviously have a much shorter list of words to contend with)

My current license plate game is to turn the numbers into a letter that they look like and seeing if the resulting ‘word’ can be pronounced or even better have some sort of meaning. The numbers map to letters as follows:

  • 0 -> o (duh)
  • 1 -> I or L
  • 2 -> Z (tho I’ve recently wondered if it could be an N on its side)
  • 3 -> E
  • 4 -> A (some people find this to be contrived)
  • 5 -> S
  • 6 -> G
  • 7 -> L
  • 8 -> B (tho something W8 could be read as ‘wait’)
  • 9 -> G (it looks a bit like a lowercase g, tho looking now, it also looks like a lower case q)

Following these rules, one of my favourite finds is CR8 04K which would be “Crate Oak”

Categories
Haiku

Haiku (June 15th)

I thought I’d try a suggestion from Gretchen Rubin. Write a Haiku everyday. I’m planning on publishing this approximately every seven days.

Wednesday (9 june)

Sunshine on my face
Mostly feels good but maybe
Less warm is better

Yummy peas growing
On very tippy lattice
Taste so crunchy good

Lovely irises
Translucent purple from
The sun shining through

I feel a fly that
Is walking among leg hairs
Not gonna smack him

Thursday

I see evil faces
In the reflected water
Upon the table

Stanley Park Seawall
Has become my happy place
Beautiful, tranquil

Start with five syllables
Next a line of seven more
Then the final five

Little ants walking
Relentlessly up the chair.
Where are they going?

Stuck on a puzzle
A sudoku idea
Eureka, it’s done!

Friday

When the rain begins
For a while, it’s dry under
trees. Then drip drop drip.

Pure Bread Bakery
Has so many yummy treats.
Ooey-Gooey bar!

Monday

I’m on the couch now
But I had an active day
Such defensiveness!

Categories
Happy

On the Cusp of Raspberry Season

It makes me happy to see that our raspberries will be ripe soon. We have a thriving colony of Golden Raspberries (the orange ones).

Categories
Hobbies

My Stanley Park ride

Most days, I bike around the stanley park seawall. Some days, I stop to take photos of the remarkable scenery. Other days I take photos of graffiti on train cars. Some days, ok most days, I do multiple loops around the park.

When the weather is sketchy, I’ll take my commuter bike called Ada. On bright sunny days, I’ll usually take my fancy Pinarello racing bike.

I’ve seen seals, otters, coyotes, goslings, ducklings, and a marmot/ferret. One day I even saw a whale. (oddly enough, a few days after writing this draft post, I saw another whale)

The path is populated by cyclists, rollerbladers, walkers, joggers, photographers, readers and fishers. Approximately one third of the people I see are regulars, that I see more than once per week. There is one woman I’ve seen a couple of times who likes to yell at me that I should be on the road, not the bike path. I try not to take it personally.

Sometimes I take the road, but I do prefer the path, as it’s right on the ocean.

I feel a titch disingenuous writing about riding in Stanley Park without discussing my Strava Local Legend situation. Still, I’m going to save that for another post.

View from the Stanley Park Seawall, looking towards Gondor… er no, Vancouver!
Categories
Software

WWDC 2021

No this does not refer to the Western Washington Debutantes Convention. Today is the first day of Apple’s World Wide Developers Conference. For anyone who writes software for iPhones, iPads, Watches, and Apple computers, it tends to be a very exciting week.

Sometimes there are new hardware announcements and releases. Other times there are big technology changes, such as a new development language (eg Swift!). Every time there are a lot of new technology announcements, that are usually obscure as heck. (eg. a new interface for coding In App Purchases)

Buried among the intimidating amount and complexity of detailed information, there are usually a few fun nuggets of new things I find very cool. So far this year, the best example of this is a new feature in the photos app that detects text in photos. Users will be able to copy text in photos and paste it into any other apps. They will also be able to detect and call phone numbers when they show up in photos. Crazy!

Before Covid, the conference was in San Francisco and the information was really only available to people who attended in person. Some time in the past 10 years the conference became ridiculously over subscribed and it became a lottery to be able to attend. At about the same time the information from all the presentations was made available on line.

The last two years, due to Covid, the conference was entirely online and free for everyone. (Attending in person in previous years typically cost ~$1500 USD.)

I have been to WWDC twice, once in 2004 and once in 2010. In 2004, I was attending with a co-worker who was very much a night owl. He would typically arrive at work around 11am. At WWDC I was very perplexed when he insisted we arrive at 6am for the Keynote Address on the first day that didn’t start until 10am.

When we arrived at 6am, there were already hundreds of people in line. I later realized this was most likely due to the personality cult around Steve Jobs. While I’d like to think I wasn’t susceptible to his reality distortion field, it was still pretty exciting to be in the room for his presentations.

Categories
Hobbies

Two Thumbs Up for the Lynn Loop

This morning, Steph and I snuck away for an morning hike up in Lynn Headwaters Regional Park. We’re both pretty sure neither of us had been there before, but it was splendid.

Most of the loop is two parallel trails, one that follows the Lynn Creeks east bank. The other trail is still on the east side but is further east, at a higher elevation, and almost out of ear shot of the creek.

Apparently the usual way (more interesting way?) to do the loop is to start out on the trail further away from the creek. This trail starts with a fairly steep section, but is then fairly flat up to the intersection where you can return to the parking lot via the trail running beside the creek.

The full loop that we did was listed as 8 km and recommended allowing 4 hours. We thought it was more like 9 km, and we were back in a bit under three hours. (YMMV as they say)

If you don’t feel like doing the full 8km, there is a second link between the two trails about halfway along. (This will all be obvious when you see the map.)

There are also more challenging trails heading off in a few different directions, but we didn’t investigate them. This is also a great place for dog owners, or anyone else who enjoys meeting dogs on the trail. (Dogs on hiking trails always seem to be their happy place, I reckon.)

A stump that used to be a cedar tree
Categories
Software

A SwiftUI Picker Using an Swift Enum Part 2

In Part 1, we created a basic SwiftUI Picker that was bound to an enum variable that included n possible values. When users pick a value from the picker, the app’s data model is aware of this change and the UI updates to reflect the user’s selection.

In this post we are going to extend this basic functionality.

Display Text for Sort Types

Life would be better if we could customize the display text for each of the different sort types. To do this we will add a function to our enum.

    func displayText() -> String {
        switch self {
        case .name:
            return NSLocalizedString("Name", comment: "display text for sort type: name")
        case .height:
            return NSLocalizedString("Height", comment: "display text for sort type: height")
        case .averageScore:
            return NSLocalizedString("Average Score", comment: "display text for sort type: averageScore")
        }
    }

In order to use this new function, replace rawValue calls with displayText() calls.

struct ContentView: View {
    @ObservedObject var settings = Settings.shared
    var body: some View {
        VStack {
            Picker(selection: $settings.sortType, label: Text("Sort Type")) {
                ForEach(SortType.allCases, id: \.self) { sortType in
                    Text("\(sortType.displayText())")
                }
            }
            Text("sort type is: \(settings.sortType.displayText())")
        }
    }
}

Persist Preferred Sort Type

In this section we will add code to remember a user’s previously selected sort type. So if the user closes the app and relaunches it, their preferred sort type will still be selected. To do this, we will write the sortType to UserDefaults, and then read this value when the app launches. These changes will be made in the Settings class.

class Settings: ObservableObject {
    static let shared = Settings()
    @Published var sortType: SortType {
        didSet {
            UserDefaults.standard.setValue(sortType.rawValue, forKey: "sortType")
        }
    }
    init() {
        sortType = SortType(rawValue: UserDefaults.standard.string(forKey: "sortType") ?? "name") ?? .name
    }
}

I’m mildly pained by the need to include both a fallback value for the string read from UserDefaults and also a fallback value SortType(rawValue: ) return value. I guess this is just my way to demonstrate that I don’t like forced unwraps !

Add a New Sort Type

So what happens when end requirements change and now our data can also be sorted by…. let’s say Shoe Size? What needs to change in our example? In fact, very little needs to change. Basically just add the new enum case, and add a corresponding case to the displayText function

enum SortType: String, CaseIterable {
    case name
    case height
    case averageScore
    case shoeSize
    
    func displayText() -> String {
        switch self {
        case .name:
            return NSLocalizedString("Name", comment: "display text for sort type: name")
        case .height:
            return NSLocalizedString("Height", comment: "display text for sort type: height")
        case .averageScore:
            return NSLocalizedString("Average Score", comment: "display text for sort type: averageScore")
        case .shoeSize:
            return NSLocalizedString("Shoe Size", comment: "display text for sort type: shoeSize")
        }
    }
}
Categories
Software Uncategorized

A SwiftUI Picker Using an Swift Enum

These two items (the SwiftUI Picker and a Swift enum) work really well together. Some might say they go together as well as Peanut Butter and Banana.

Requirement: Your app needs a way for a user to choose how to sort their list items. Today list items can be sorted by Name, Height and Average Score. Some time in the future, the list of sort types is expected to grow.

Eventually we are going to need some UI for this, but let’s start be defining an enum to define the sort types. Our enum needs to conform to CaseIterable because we will need to call the allCases class method. I don’t think String is required, but is helpful in the initial stage before we polish the UI.

enum SortType: String, CaseIterable {
    case name
    case height
    case averageScore
}

And also a Settings model object to store our source of truth (ie sort type) We will access the Settings singleton via the shared static variable. Settings needs to conform to ObservableObject because the Picker will bind to the sortType property.

class Settings: ObservableObject {
    static let shared = Settings()
    @Published var sortType: SortType
    init() {
        sortType = .name
    }
}

For the UI, we will use the following Picker init

    public init(selection: Binding<SelectionValue>, label: Label, @ViewBuilder content: () -> Content)

The UI content view will start with something like this:

struct ContentView: View {
    @ObservedObject var settings = Settings.shared
    var body: some View {
        VStack {
            Picker(selection: $settings.sortType, label: Text("Sort Type")) {
                ForEach(SortType.allCases, id: \.self) { sortType in
                    Text("\(sortType.rawValue)")
                }
            }
            Text("sort type is: \(settings.sortType.rawValue)")
        }
    }
}

If we run this code, we’ll see a picker above a text label. When we pick a different value in the picker, the text label updates accordingly. Woot!

In Part 2, we will:

  1. Improve the UI by adding display names for the sort types
  2. Use UserDefaults to persist and recall the selected sort type
  3. Add another sort type