July 14, 2018 at 10:47 PM by Dr. Drang
If you pay any attention at all to Apple-related websites,1 you know this past week was the tenth anniversary of the opening of the App Store. And in the dozens of blog posts marking the occasion, you no doubt saw many references to Steve Jobs’s much-derided “sweet solution” of web apps only for iPhone developers in that initial App Storeless year. But some good things came out of that year.
The first I remember fondly was a hangman game that I played with my older son every night before he went to bed. Sadly, I deleted the bookmark for it long ago, and I never mentioned it here on the blog, so I can’t find even an outdated link to it. Too bad. It was a simple game, but it worked exactly as you’d expect, and it fit nicely on that original iPhone screen.
The other app I used so much in the pre-App Store days was Hahlo, a web-based Twitter client that was so much better designed for the iPhone screen than the Twitter website was.
The Hahlo website still exists, but it redirects to this nicely written farewell page from Hahlo’s developer, Dean Robinson. On it you’ll find several screenshots of Hahlo in action, one of which you see above.
I learned of Hahlo from Andy Ihnatko. I don’t remember if he wrote about it on his blog or mentioned it on MacBreak Weekly, but he thought highly of it, and so did I. I used it as my main mobile Twitter client until Tweetie came along.
No one wants to go back to the days before the App Store, but it is worth remembering that clever developers gave us useful things even when they were stuck in the molasses of the sweet solution.
July 4, 2018 at 3:26 PM by Dr. Drang
As if I weren’t already subscribed to more podcasts than I could possibly listen to, along come David Sparks (of Mac Power Users and countless instructional videos and books) and Rosemary Orchard (of Automation Orchard and countless posts in the MPU and Drafts forums) with a new podcast about automation on Apple devices. I’m not sure what I’ll have to squeeze out to fit this one in, but I will.
As a sort of inverse tribute to David and Rosemary, who provide automations with broad appeal across all sorts of Mac and iOS users, this post is about a pair of recent automations that appeal basically to me. With luck, though, they may trigger ideas for you to create similar automations that solve your own specific problems.
Let’s start with the simpler one. I deal with architectural and engineering drawings quite a bit at work. They usually come to me as PDFs, whether scanned or generated directly from CAD. When I need to have a discussion about them, I drop the PDF into an OmniGraffle document and use OG’s tools to mark up the parts I have questions or comments about. Then I export the annotated document out as a PDF so my client can view it.
Exporting an OmniGraffle document as a PDF is a straightforward and quick process, one that I’d never thought about automating until recently, when I had about two dozen marked-up drawings that I needed to export as PDFs. I wasn’t concerned with the time it would take, but I was pretty sure I’d screw something up during the mindlessly repetitive clicking and tapping I’d need to do. So I made a Keyboard Maestro macro to do it for me. It didn’t do the job faster than I could have by hand, but it didn’t make any mistakes or forget to export any of the drawings.
Here’s the macro:
This started out as a macro that exported just one file. After I got that working, I wrapped those steps in the action that loops through all the selected files.
There are only a few tricky things in this macro:
- The pauses at several points in the macro are needed to allow OmniGraffle to catch up. It takes time to open files, bring up the export sheet, and so on, and a macro without pauses wouldn’t work. I could probably cut down on some of these delays, but it didn’t seem worth the effort to do so.
- The target image for the first click in the export sheet, telling OmniGraffle to export to PDF, is cropped very tightly to make sure it’s recognized. As you can see below, the icon for the selected format has a darker background than the others. If I included one of those backgrounds in the target image, the target wouldn’t be recognized if it had the other background.
- Similarly, the target image for the export area selection has to be the descriptive text next to the popup menu, not the popup menu itself, because the text in the popup menu changes depending on which export area was last selected. One of OmniGraffle’s clever features is the ability to direct the click some distance away from the target image; I took advantage of that here.
- After clicking the export area popup menu, the menu item is chosen by typing the first letter (or first few letters, if necessary) of the menu item and the Return key.
Because of all the pauses, this macro takes a while to run when there are a lot of files to convert. But it does the job more accurately than I can. And now that I’ve made it, I’ll use it even when I don’t have dozens of documents to convert.
The second piece of automation is an AppleScript and is also needed because of the way I use OmniGraffle to mark up drawings.
Quite often, I need to go through the drawings for a building and identify where certain features or components are located. After that, I need to provide a count of all these items. I do the identifying and locating by marking the items with circles or boxes, as in this drawing.
Here I’m marking up a plumbing drawing, showing where the valves are. The different sizes of valve have been given different colors and the circles that identify them are kept in separate layers. This is a convenient way of organizing things while I’m working on the markup, and it makes the process of counting easier.
But when I have dozens of drawings and dozens of items on each drawing, I don’t trust myself to do the counting without making mistakes. Luckily, computers are really good at counting. Here’s the AppleScript I use to count all the different parts on all the drawings:
applescript: 1: -- Create the file for the results 2: tell application "Finder" to set theFolder to target of front Finder window as alias 3: 4: set fileRef to choose file name with prompt ¬ 5: "Valve count file:" default name ¬ 6: "valve-count.txt" default location theFolder 7: open for access fileRef with write permission 8: 9: -- Initialize the output string 10: set output to "" 11: 12: -- Get a list of all the files of interest. 13: tell application "Finder" 14: set FPFiles to the selection as alias list 15: end tell 16: 17: -- Count the circles in each layer of each drawing. 18: repeat with f in FPFiles 19: tell application "OmniGraffle" 20: open f 21: delay 3 22: tell front document 23: -- Start with the name of the drawing. 24: set output to output & name & linefeed 25: tell front canvas 26: -- The bottom layer has the highest number and contains 27: -- only the drawing, no circles. 28: repeat with i from 1 to ((count of layers) - 1) 29: tell layer i 30: set sCount to count of graphics 31: -- Add the layer name and count. Skip empty layers. 32: if sCount > 0 then 33: set output to output & name & ": " & sCount & linefeed 34: end if 35: end tell 36: end repeat 37: end tell 38: close 39: set output to output & linefeed 40: end tell 41: end tell 42: end repeat 43: 44: -- Write and close the file. 45: write output to fileRef 46: close access fileRef
Line 2 gets the folder that contains all the selected drawings. Lines 4–6 ask the user for a file in that folder in which to save the counts. Line 7 then opens that file for writing.
Lines 13–15 create a list of all the selected files. This will be the list we loop through starting on Line 18.
For each file in the list, we open the file and loop through all the layers, getting the count of the graphic items in each layer. The output string, which was initialized to the empty string in Line 10, gets updated with each new file name and item count as we work our way through the two loops. When the outer loop is done, Line 45 writes the output string to the file we opened in Line 7, and Line 46 closes the file.
OmniGraffle numbers the layers from top to bottom. Since the bottom layer is the drawing, we don’t need to include its item count, which is why the upper limit on the repeat loop in Line 28 is one less than the number of layers.
I sometimes make layers that end up not getting used. Because I have no interest in reporting counts of zero, the condition in Line 32 filters those out.
The output of the script looks like this:
P101 .75 in: 1 1.5 inch: 4 2 inch: 6 4 inch: 12 6 inch: 2 P102 .75 in: 3 1.5 inch: 2 2 inch: 12 4 inch: 16 6 inch: 4
If I need to do further processing of the counts, this format is easy to parse.
We all know the XKCD comic about the false efficiency of automation, but automation is at least as much about accuracy and repeatability as it is about efficiency. No one thinks it’s wrong to put in more time to get more accurate and trustworthy results.
June 24, 2018 at 10:43 AM by Dr. Drang
I got the battery in my iPhone replaced last Sunday, and after a week of use I can say without reservation that it was a big success. Before the replacement, a normal day of use at the office would put the battery well below 50% and I’d usually have to recharge sometime during the evening; now it’s typically over 80% when I get home, and I don’t even think about recharging. This success is tempered, though, by the poor advice Apple gave me before doing the replacement.
I tweeted about this on Monday, but I think it’s worth discussing in more detail. Let’s start with a bit of history.
My phone is an iPhone 6s bought phone shortly after it was released, probably in October of 2015. About a year later, Apple announced a [free battery replacement program] for a certain set of 6s phones made in September and October of 2015. My phone fit in that window, so I got the replacement, even though I hadn’t had the sudden shutdown problem the recall was meant to address.
I was pretty happy about getting the new battery. The original was still giving me plenty of life, but I’d decided I wasn’t going to get an iPhone 7, so I figured a new battery would keep my phone going strong at least until the next phone was released in Fall 2017.
When September 2017 rolled around, I decided to take a pass on the iPhone 8 and iPhone X. After all, I had a phone that worked fine with a battery that was still less than a year old. I could wait until the next generation.
Then came the blowup about sudden shutdowns on many phone models and, what was more controversial, Apple’s throttling of performance to avoid those shutdowns without telling its customers it was doing it. At the time, I didn’t think my phone was being throttled, and I was still getting a full day of use with capacity to spare. But that didn’t last much longer, so I decided to take advantage of the $29 replacement program.
With stories of long waits at the Apple Store as everyone rushed in to get their batteries replaced, I put off getting my own replacement until I couldn’t stand it anymore. I made an appointment for last Sunday.
The Apple Store employee (not sure if he was technically a Genius or not—are all Store employees called Geniuses?) looked at the phone’s Battery Health in Settings, saw that the Maximum Capacity was 81%, and told me the battery replacement wouldn’t do me any good. “You won’t see any difference,” he said.
I was sure he was wrong but didn’t say it in so many words. I told him I wanted the replacement anyway because I could no longer get through a day without recharging. Maybe the replacement wouldn’t fix that, but I wanted to give it a try.
He said he’d certainly do the replacement if that’s what I wanted; he just wanted to make sure I knew it wasn’t likely to help. Apple didn’t want me spending money for no reason. Background processes were the more likely culprit. Did I mind if he looked through my settings to see if there were some things that could be changed to improve battery life?
Of course I let him and of course he found nothing. I’d been through that exercise myself several times. He did say—and this was the one time I was tempted to laugh in his face—that my Auto-Lock setting of 5 minutes was too long and would really kill the battery. I told him I’d used that Auto-Lock setting on every iPhone I’d owned over the past ten years and it had never been a problem. I still wanted the battery replaced.
An hour and a half later I had my phone back with a new battery—with, I noted with some disappointment, only a 17% charge—and it’s now behaving exactly as I expected and exactly the opposite of what Apple told me to expect.
I say “what Apple told me to expect” rather than “what an Apple Store employee told me to expect” because I don’t think he was making up his own advice to pass along to customers. I think this is Apple’s official advice. And it’s wrong. I ignored Apple’s advice because I knew how I used my phone, knew that I didn’t have many background processes running, and knew that the battery life had decreased significantly over the course of a few months even though my usage hadn’t changed. I wonder if other customers are living with short battery lives because they listened to Apple.
I should point out that anyone with an eligible phone who wants a new battery will get one for $29. That’s Apple’s policy. But the policy is being undercut by poor advice based on a single number that comes out of the Battery Health setting. Which is beta software. The mixed message is not good customer relations.
June 13, 2018 at 8:23 PM by Dr. Drang
Two recent Amazon purchases got me thinking about design and manufacturing.
Let’s start with design. On the recommendation of a couple of friends, I bought this LitraTorch LED light cube.
It’s a nice compact little light that generates fairly uniform coverage at three intensity levels (and there’s a strobe mode, which I find useless). Also, it starts at the lowest intensity so you don’t get immediately blinded when you turn it on in a dark room. It’s not cheap, but it’s a professional tool for the inspections I do at work. Overall, I’m happy with it.
It has a permanent battery that recharges through a micro USB port. I always struggle getting the orientation of the plug and port to match, and working with this one is going to be even more trouble than I’m used to.
Every port I’ve run across before is shaped like the plug in sort of a curved trapezoid. Not this guy. The only way to know which end is up is to see the black connector part inside the black rectangle on the back of a black cube. I assume the decision to go with a rectangular port was driven by cost, but it’s an unfortunate choice, especially in an $80 flashlight.
It’s a simple case and not expensive, but the first time I tried to unzip the main compartment, the zipper pull came off in my hands.
The little hook on the slider that holds the pull had snapped off.
Since I was at work, I took the broken hook into the lab to have a look at it under the microscope. Please forgive the fuzziness; it’s hard to get good depth of field in optical microscopy.
So many problems in how this was made. The immediately obvious flaw is the bubble in the center. This is a cheap casting made of cheap pot metal and the casting left a huge (relative to the size of the part) bubble in the center of the hook.
But I doubt that was the main cause of the failure. The hook is loaded mainly in bending, and the bending strength of a hollow part isn’t usually significantly different from that of a solid part. Many parts are deliberately made hollow to save material without reducing strength much.
You may also notice the crack extending inward from the edge on the right side. That, too, is a flaw, but didn’t lead to the failure. That crack is perpendicular to the final fracture surface and would not be affected by the bending stresses that broke the hook.
Now look at the black areas at the upper right and upper left corners of the cross-section. This is paint, and because it’s on the fracture surface, we know that cracks in those areas were already present when the hook was painted. And because they’re on the outer edges of the cross-section, where the stresses are high during bending, they are the flaws that were the most direct cause of the failure. I’m guessing the casting cracked during cooling but was not weeded out during whatever quality control process the manufacturer used.