SwiftUI – Simple ScrollViewReader use to get ScrollView to start at the top left.

Had occasion to use a SwiftUI ScrollView today and ran into the issue where the SwiftUI team decided to use one of the two most sensible defaults for initial presentation when the content is too large to fit in the container – center the content. This makes sense for images or maps, but not for much of anything else I am thinking of. Everything else seems to want top left (for left-to-right locales at least). Strange that something that a large percentage of people are going to want isn’t as easy to set as alignment or something, but so it goes.

Anyway, this gave me an opportunity to read up on ScrollViewReader which, combined with the .onAppear modifier, can get the initial presentation of a ScrollView to the top left like so many want/need it to be.

Putting the code here so I remember for next time and in case anyone else finds a bazillion Stack Overflow posts about how ScrollView is so hard to make display properly but no modern ScrollViewReader answers.

//
//  ContentView.swift
//  trashme
//

import SwiftUI

struct ContentView : View {
  var cellSize: CGFloat = 50
  var numRows: Int = 30
  var numCols: Int = 10
  var body : some View {

    VStack(alignment: .leading, spacing: 20) {
      ScrollViewReader() { proxy in
        ScrollView([.horizontal,.vertical], showsIndicators: true) {
          HStack( alignment: .top, spacing: 0) {
            VStack ( alignment: .leading, spacing: 0) {
              ForEach(0 ..< numRows, id: \.self) { row in
                Text("row " + row.description)
                  .frame( height: self.cellSize )
              }
            }
            ForEach(0 ..< self.numCols, id: \.self) { col in
              VStack( spacing: 0) {
                ForEach(0 ..< self.numRows, id: \.self) { row in
                  Text("\(row), \(col)")
                    .frame( width: self.cellSize, 
                            height: self.cellSize, 
                            alignment: .center)
                    .border(.blue)
                }
              }
            }
          }
          .id("root")  // since our ForEach views don't really 
          		// have true ids (\.self ~)  
          		// we make one for the outer HStack
          		// in the ScrollView
        }
        .onAppear {
          proxy.scrollTo("root", anchor: .topLeading)
        }
      }
    }
  }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

And here’s what it looks like in an iOS SwiftUI preview pane:

Twitter Advanced Search cheatsheet

Here so I can find it again 🙂

from:username
to:username       // to username
@username         // mentioning @username
keyword           // can be a #hashtag
-keyword
keyword OR keyword
min_retweets: x
min_faves: x
min_replies: x
filter:links
filter:images     // any image
filter:twimg      // twitter pic.twitter.com image
filter:video
filter:native_video
filter:periscope
filter:vine
filter:media      // image or video
filter:retweets
filter:safe
filter:verified   // verified users
-filter:____      // use with any of the above filter nouns to exclude
since:YYYY-MM-DD
until:YYYY-MM-DD
near:X within:10mi // (where X is a city name)
list:user/listname
url:apple          // has url containing "apple" anywhere in it
lang:languagecode  // en, da, cs, de, es, fr, it, ja, ko, nl, no, pt, ro, uk,…

Taking Mars Edit 4 for a spin!

So I was sad the WordPress macOS “app” is just an Electron app that wraps the website with a few macOS menu items to jump to specific pages on the site. 

Thought I’d give MarsEdit a try.  But the Mac App Store glitched 😦

 

AppStore download error for MarsEdit

 

Worked after I quit and restarted the App Store.

So one thing I’m not seeing is how to have it post to Twitter when I post to my blog.  Maybe that’ll happen inside of WordPress?

It DOES!   Ok, that’s pretty cool.  This might work after all.

 

Hmm.  So maybe I’ve been using Pages & Numbers too much lately, and the WordPress site, but I find myself looking to the right side “Options” pane for formatting commands.  I often want to format some content as code (go figure!) and having that very handy is nice.

OH MY WOWZA!  You can add your own formatting macros to the Format menu with key command shortcuts.  Ok.  That is slick.

let foo = 12

Little bit of trouble getting out of code mode.. but not terrible.

— 

Wow. The feature where MarsEdit downloads my template from WordPress so that it can preview posts is very cool.

––

There are a few things that are tripping me up, but since I want to put more of the content I usually put on twitter onto a platform that I can keep if I bail on twitter, this seems like a good way to do it.  (I think about micro.blog also, but I just don’t ‘get’ it.  ¯\_(ツ)_/¯ ).

I do wish MarsEdit would save out static blog posts and use FTP to upload them to a statically hosted blog/site.  But a WPXML roc adaptor to Jekyll or something has been sketched out by two different friends so maybe that’ll materialize somehow.

macOS custom window titlebar – don’t forget to implement the standard title right-click feature!

PSA: For a great macOS app experience, the details matter. As an example, if you implement a custom macOS window titlebar for a document based app* don’t forget to implement the feature whereby you display a menu with the folder hierarchy for the document if the user right clicks, control+clicks or command+clicks the document title in the window titlebar.

Just ran across an app that failed to do this and it was quite annoying. I needed to open the folder containing the document in the Finder so I could duplicate the file and selecting the folder name in this menu from the document title is the easiest way to do that. Bug report filed with the app maker, but please save me the time of filing one against your app by getting this right from the beginning 😉

* Note that the Finder implements this for Finder windows, so I’d follow their lead and interpret “document” broadly as ‘anything with a location in the file system’.

Psychology hack: Convert shopping therapy urge into donation urge

Chatting with one of my sisters and she remarked upon our mother’s Amazon book buying … addiction? compulsion? Orders way more books than she can or does read. Hear or read a book review that sounds good? Go order the book. Etc.

I opined that this was probably a form of shopping therapy and given our mother’s chronic health issues in recent years, probably understandable. My sister then mentioned that she just goes to the dollar store to satisfy this for very little money 🙂 but also that one of her kids seemed have a bit of a shopping therapy urge also.

I mentioned that I’d been pretty successful some years back when I hacked what felt like my own occasional shopping therapy urge (“Feeling down? Buy something!” – such an American consumer ingrained message for so many years).

What I decided to do was every time I felt that urge and couldn’t just easily talk myself out of it I’d find one of the organizations I like to support, a creative person trying to make their first album/book /comic/etc on Kickstarter, a request for help that a friend or Twitter acquaintance had shared, or similar, and make a donation instead.

I found that I got a better “feel good” feeling this way, someone benefits, and I don’t end up with more STUFF cluttering up my life. Triple Win!

I thought I’d share this hack here in case anyone else might like the idea and want to adopt it.

19?! Wow…

Today we remember Nina who would have been 19 today.

Today we remember Nina who would have been 19 today. Impossible for me to really imagine her at 19 since she didn’t live to 4, but here she is on her 2nd birthday in her new dress from a friend of grandma’s in Kenya:

Nina 2nd birthday in her new birthday dress made by grandma’s friend in Kenya

I woke up this morning remembering what an intense day this was 19 years ago and the intense week that followed. We knew she had hydrocephalus and that she’d need a shunt in her brain to relieve the CSF pressure, but we didn’t know she’d be in the neonatal intensive care unit (NICU) for a week and we definitely didn’t expect all the other medical challenges she was born with. Nor did we expect the three other major surgeries she’d need in that first year (spinal cord surgery, intestinal surgery, eye surgery).

It wasn’t until a couple of months before this picture on her 2nd birthday that we finally got a diagnosis of Fanconi Anemia (FA), and some idea of what to expect for her as a result. Up until then it was a mystery to her doctors. Unfortunately, that expectation was likely a short life due to the type of FA she had. She had a pretty great year from this birthday through the next one. And then a month not so great due to brain surgery to remove a new tumor, but then a really great summer of family visitors, and good early fall before her decline and departure.

Outcomes are much better now for people with FA, but it’s still tough for many. These improvements are largely thanks to the efforts of researchers supported by the Fanconi Anemia Research Fund (FARF) and all the family and friends who’ve raised money for them to fund research over the years (including ours). Much of this research has shed light on, and improved treatments for, cancer as well as FA due to physiological pathways in common between the two and the higher determinism for FA.

Anyway, it’s been a long road, but we feel very lucky to have had Nina in our lives for part of it. Hug the ones you love.

Build Racing circa 2006

Found an old document where I’d written down some data on build timing and though it might be fun to share it.

Did some build racing of a fairly large codebase for a widely used macOS application from a company I was working for. Thought it might be fun to see the progression.

I loved the Quad G5 I bought for myself (employer wasn’t spending that kind of money) as an upgrade from the dual G5 I first bought. What an amazing jump in speed with the Quad G5! The intel based Macs were a significant jump in performance though and cheaper and sucked a lot less electricity (turning on the Quad G5 would trip my UPS about 50% of the time – it had a nasty initial surge).

—-

This is an ant build of {REDACTED}. Interestingly, the second build is faster
even though we do a clean before each build.. suggests our “clean” isn’t
really cleaning everything…? Maybe source file and system library caching in the file cache? Anyway, clearly not very carefully done, but amusing all the same. You can see why I didn’t work on my 17″ G4 laptop much – ouch!

Mac Mini 1.66 GHz core duo, 2G of RAM

1st build: 26 min 58 sec
2nd build: 25 min 6 sec

same machine but put source on an external firewire 400 drive:
remove objects directory (like 1st build):

3rd build: 30 min 4 sec
4th build: 27 min 10 sec

17″ Powerbook G4, 1.33 GHz, 1G RAM

1st build: 57 min 50 sec
2nd build: 55 min 26 sec

Dual G5 2Ghz, 1.5G RAM: (I think this hard drive must be fragmented or
something)

1st build: 22 minutes+
2nd build:

“Quad” G5 2.5GHz, 2.5G RAM:

1st build: 9 min 4 sec
2nd build: 8 min 16 sec

**WINNER *** (and it cost $800 less than the Quad G5!)
NEW Mac Pro (guessing: Dual 2.66GHz dual-core Xeon with 1G of RAM):

1st build: 8 min 4 sec
2nd build: 7 min 9 sec (+/-)

Implanted Medical Devices, OSS, Open Hardware , Right to Repair, … and Electric vehicles.

Implanted medical devices from companies that go under or discontinue them have a major impact on the humans those devices have been implanted into. How do we mange this as a society in ways that doesn’t inhibit innovation and progress?

Imagine you’ve got a high-tech implant in your retina that gives you a crude but effective form of vision. Now imagine the company that produced the implant suddenly goes out of business, and will no longer service or fix your implant

Glenn Zorpette, on twitter

He’s referencing this article:

THEIR BIONIC EYES ARE NOW OBSOLETE AND UNSUPPORTED
Second Sight left users of its retinal implants in the dark

spectrum.ieee.org, (article)

I read this article last night and I’ve been thinking about it ever since. I don’t have an answer I’m convinced is complete yet, but it does seem like this situation represents a strong vote for FDA approval of medical implant requiring an implant meet the following standards:

  • Right to Repair requirements
  • Open Source Hardware
  • Open Source Software

But how do we do that in a way that doesn’t prevent companies making the massive R&D effort and incurring the corresponding expense to create these devices despite these requirements? Companies and investors will likely feel they’ll have insufficient time to earn back their investment, let alone the profit investors want, if their work can just be easily copied because it’s open source hardware/software.

I don’t have an answer, but the following come to mind as possibilities. I encourage you to add any practical ideas you have to the comments below.

  • Federal R&D grants for companies that are working on products that meet these guidelines (pre-launch funding).
  • R&D tax credits/incentives for companies that release products under this framework (pre- post-launch funding/incentives).
  • Have the technology held in an escrow system for hardware & software source that automatically becomes public 5 years (say) after shipping the approved device so companies have time to make their investment plus profit back.
  • Perhaps companies should be encouraged to patent what they create (discount the cost of that?) with a requirement that they also publish their hardware & software as open source restricted to non-commercial use only by others for as long as the company remain in business their patent is still in force (maybe limit patent duration to 10 years post product release or something)? They could still charge too much so as to make parts “available”, but not really available except to the super wealthy.
  • Maybe only non-profit entities can make implantable medical devices for approval and they will be required to follow the guidelines above. Investors don’t “invest” in these companies in a traditional sense, but perhaps they can ‘donate’ the loan of capital with a maximum interest return specified by statute (or something like that).

Curious what ideas others have.

Seems like something we need to solve – probably through legislation, but I’m open to other ideas. If done via legislation, we need that legislation crafted by people who actually understand the technological and business dynamics sufficiently well and who care about the people in whom these implants are placed sufficiently more than a desire for profit; we want good laws that actually work and don’t inhibit R&D and innovation so much we make no forward progress but also don’t risk leaving patients out in the cold, suddenly unable to see.

Postscript

I did also think about how this isn’t the first such device – I have at least two friends/colleagues with pacemakers that have been surgically implanted into their bodies. So this isn’t an entirely new thing.

I’ve also been thinking about this in the context of electric vehicles – how many of the new electric vehicles / companies are going to go out of business or decide it’s not worth it for them to keep maintaining or supporting early models that didn’t sell well?

Do all those vehicles prematurely become garbage because the battery controller software is closed source and so can’t be updated to work with new battery technology? Or because the inverter goes bad and the specifications for it aren’t available any more and so no one can create an aftermarket replacement? Or vehicles that had too few for it to make financial sense for a third market parts manufacturer to bother? (See man blows up Tesla Model S because replacement battery is too expensive to justify).

I don’t think we can afford to be making so much garbage. There’s a lot of embodied energy in an EV and a massive level of promotion for people to switch to EVs from internal combustion engine (ICE) vehicles. Those ICE vehicles can be kept running for 20, 30, 40, even 50 years if they were popular when they were released and so third party parts manufacturers have figured out how to make parts for them.

Batteries in electric vehicles aren’t going to last even half the lower end of that spectrum.

This seems like an issue that needs to be addressed. Not as individually impactful as having your medical implant “End of Life’d”, but still.

Automatic Once-a-Day Time Machine Backups

Update: So in macOS 12 (and likely v11 and maybe v10) you have to give cron Full Disk Access for it to work. This seems less than ideal from a security perspective, so I’ve move to using launchd via a LaunchAgent plist file. Documentation on how to use cron is in an addendum in case you prefer that.


My wife is using an older MacBook Air from late 20101 and it can’t handle a Google Meet meeting, Chrome with a bunch of tabs open, and a Time Machine backup (all over WiFi) without the video meeting having trouble. We still wanted to back it up to the two TimeCapsules we have though.

I tried just having her run a backup manually when she was done for the day, but she’s tired then and so backups weren’t happening regularly at all. Thus, it was clear I needed a way to automate this. Turns out it’s not that difficult. This post explains how.

Quick summary

  • Setup Time Machine backup destinations
  • Run a first backup to each backup destination
  • Option 1 (described in an addendum since launchd is preferred by Apple):
    • Use crontab to setup a daily call to tmutil startbackup --auto --rotation
    • Use System Preferences > Security & Privacy > Full Disk Access to give /usr/sbin/cron full disk access
  • Option 2:
    • Create a LaunchAgent plist to invoke tmutil startbackup --auto --rotation at the desired time.
    • use sudo launchctl bootstrap gui/501/ /Users/{your-username}/Library/LaunchAgents/{your-launch-agent-plist-filename} to get the system to load and enable your
  • Use Energy Saver / Battery settings, or pmset repeat wake with appropriate time and days to wake up the computer a couple of minutes before that crontab command trigger time.

Step by Step instructions

  1. First step – create the Time Machine backup destinations in the Time Machine settings inside System Preferences.
  1. Run the first backup to each destination – either manually (via right-click on the destination drive icon in System Preferences > Time Machine view), or automatically by enabling “Back Up Automatically” in Time Machine settings and then waiting until they’ve both completed their first backup (don’t forget to turn off automatic once the first backup to each has run!).
  1. Decide what time you want your daily backup to run. I chose 12:59AM.
  1. Now create a LaunchAgent file for your task. The easiest way is to use LingonX, but you can create the file in a text editor like the excellent BBEdit and may want to refer to this very helpful documentation for launchd.

Name your file something that makes sense to you, I matched the file name to the label, so: “com.geekanddad.DailyTimeMachineBackup.plist” is what I used.

Contents should be something like this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>com.geekanddad.DailyTimeMachineBackup</string>
  <key>ProgramArguments</key>
  <array>
    <string>/usr/bin/tmutil</string>
    <string>startbackup</string>
    <string>--auto</string>
    <string>--rotation</string>
  </array>
  <key>StartCalendarInterval</key>
  <array>
    <dict>
      <key>Hour</key>
      <integer>00</integer>
      <key>Minute</key>
      <integer>59</integer>
    </dict>
  </array>
</dict>
</plist>
  1. If doing this manually with a text editor, you’ll need to save this file into ~/Library/LaunchAgents/ and then you’ll need to tell launchd about it via something like:

    launchctl bootstrap gui/501/ /Users/dad/Library/LaunchAgents/com.geekanddad.DailyTimeMachineBackup.plist

    Note 1: If you don’t know what your uid (User ID) is (it’s the number after “gui” in the service domain target argument above), you can use launchctl manageruid command to find out.
    Note 2: If this doesn’t work, try running it via sudo and you’ll get more verbose error messages.
  1. Now all you need to do is make sure your Mac is awake at 12:59am 🙂

    A note about the time: Since waking up triggers connecting to the network which triggers auto-fetching of mail, likely calendar syncing, and who knows what other Apple stuff and this was an old and slow Mac, I chose to wake it up at 12:57am so it would have 2 minutes to complete all of the network stuff before the Time Machine backup tried to start. This is because if it’s too slow sometimes Time Machine on this old version of macOS will decide that “the backup destination isn’t available” and it will fail.

    I think you can do this via the Energy Saver (“Battery” in macOS 12.x) System Preferences pane under “Schedule” (for macOS 12.x) by selecting the “Startup or wake” checkbox and picking “Every Day” and the time you chose above.

    I didn’t go this route because I didn’t want it to wake up a shutdown Mac which might not be plugged in and then my wife would wake up to a dead laptop (not good for my reputation! :)).

    However, if that would work for you, I recommend trying that out because it’s easier.

    What I did:

    sudo pmset repeat wake MTWRFSU 00:57:00

Which sets a repeating wake event for 12:57am every day of the week. You’ll note that I didn’t use wakeorpoweron here because I only want it to wake up a sleeping computer and do not want it to turn on a shutdown computer.

That’s it!

All she has to do now is leave her laptop open at night when she wants it backed up (it won’t wake up if the lid is shut and no external monitor is attached).


Addendum – using (crontab):
  1. Using Terminal, initiate editing of the crontab for the current user (which is what I did), or potentially a system crontab (I didn’t look into this):

crontab -e

This puts you into your terminal editor with the current user’s crontab file open. Once there, add the following two lines

# For daily backups
59 0 * * * /usr/bin/tmutil startbackup --auto --rotation

This crontab entry says to run the tmutil command at 59 minutes after midnight every day. The parameters to tmutil are telling it to start a backup, run it as if it was a system initiated backup, and to automatically rotate between multiple backup destinations (you only need the last parameter if you have multiple defined).

  1. Give cron permissions necessary to run
    1. Open “System Preferences…” from the Apple menu and select the “Security & Privacy” icon.
    2. Then select the “Privacy” tab and scroll through the list on the left and select “Full Disk Access.”
    3. Select the lock icon in the lower left and enter an administrator’s credentials.
    4. select the + icon below the list of applications
    5. type Cmd+shift+g to display the path entry file selection interface and type: /usr/sbin/cron and select the cron binary

The window should look like this when you’ve got it added properly:

Security & Privacy panel inside System Preferences with the Privacy tab selected and Full Disk Access selected from the list on the left.  Shows the cron command line tool in the list on the right with the enabled checkbox to the left of the tool name checked.


Footnotes

1) She’s since upgraded to a late 2020 MacBook Air and is loving it, as you’d imagine :). Retina screen, insanely faster, insanely long battery life, etc. Only thing she’s annoyed by is all the dongles required to connect to her external keyboard, mouse, and external display 🙂 (back)

Life planning circa early 2001

Old life-planning image that Jaimee Jaimee’s Coffee With Jaimee – getting unstuck radio show made me think of.

Just started listening to the first couple of episodes of Jaimee Finney’s new live radio show Coffee With Jaimee – A Show About Getting Unstuck and have been enjoying it quite a bit.

In these first two episodes Jaimee talked about writing down what’s most important to you in your life in episode one, and then talked about writing down your big bulky desires or goals in episode two. This reminded me of something along these lines I did in early 2001 (?). Sharing it not because the content is particularly interesting, but to illustrate that “write down” doesn’t necessarily mean making a list in the usual way. My thought was that perhaps this might help someone feel free to diagram these things out in a way that organizes them by modality, or topic, or location, or whatever works best for them and to remind people that it doesn’t have to be a linear list.

Circle in the center containing core goals/values (Be a good dad; be a good mate; be healthy) and with "rays" of text coming out for various projects (software products, technologies to learn, house projects, and so on) and things to learn and do.

I redid this later and it got a bit more concentric circle oriented, but the shape is just whatever way helps you evaluate the relative importance of things to you, your life, those you care about, and so on, so I’d recommend not letting yourself be constrained by what I or anyone else has done.

(slight redaction to remove names of products and people as appropriate)