Monthly Archives: April 2019

Cryptic App Store Upload Error

I recently had cause to take another look at Swish, my iOS app for generating white noise and static visuals. OK, the reason was Apple sending me an email notification that, because it has been over three years since I last updated the app, they were going to remove it from the App Store in 30 days.

I had previously had it in mind to ship an update that supports the newest screen sizes for devices such as iPhone X, but I sort of lost track of that. This was a good motivation to get an other update out so I made a few quick improvements and set about uploading a build to Apple to “blow out the cobwebs” and see if I was missing anything else.

Upon uploading the app, I was met with this surprising error:

Screenshot of an error from Xcode indicating that \

The Info.plist indicates an iOS app, but submitting a pkg or mpkg.

Hmm. That’s weird. I’m not submitting a pkg or mpkg. At least, I don’t think I am. My Info.plist should indicate an iOS app, because Swish is an iOS app.

I racked my brain trying to figure out what was going on here, and finally ended up filing a bug to Apple. Luckily, they got back to me within a day or two with this unexpected advice:

Please remove the LSMinimumSystemVersion from the Info.plist.

I had added the “minimum system version” to the Info.plist because I decided this update would support only iOS 11 and higher. I didn’t understand why that value would have anything to do with my issue, but I dutifully followed their advice, submitted the app, and … it worked perfectly!

Doing a little research, I discovered that LSMinimumSystemVersion is for macOS only, and that the iOS counterpart is simply called MinimumOSVersion. But, here’s the catch: the Xcode build process generates and inserts that MinimumOSVersion plist entry automatically, based on the deployment target for your app.

I hope this helps some frustrated Mac developer who is simply following old habits, and makes the mistake of adding LSMinimumSystemVersion to their iOS app’s Info.plist. Remove it, and your App Store uploads should work again!

Toggle System Grayscale Mode

A colleague recently asked whether it was possible to connect a custom keyboard shortcut to the system-wide “Use grayscale” setting in the macOS Voiceover system preferences:

Screenshot of macOS preference options for accessibility options inlcuding 'Use grayscale'

I could not find any easy way to do this, and searching the web for solutions revealed that most people are addressing this want by using GUI scripting to automate literally opening System Preferences and clicking the pertinent checkbox.

I thought there must be a way to do this in a more streamlined fashion. Couldn’t the option be automated via AppleScript or something? After some brief research, my conclusion was “no.”

At this point I put on my “hacker hat” and proceeded to analyze the System Preferences code that handles the configuration. It’s a binary in /System/Library/PreferencePanes, and the following Terminal command got me on the right path:

cd /System/Library/PreferencePanes/UniversalAccessPref.prefPane/Contents/MacOS/
nm UniversalAccessPref | grep gray

In short, that means “dump all the symbols (nm) from the VoiceOver preference pane, and search them (grep) for the word ‘gray'”. Here’s what it spits out:

0000000000057210 S _OBJC_IVAR_$_UAPDisplayViewController._grayscaleCheckbox
                 U _UAGrayscaleIsEnabled
                 U _UAGrayscaleKey
                 U _UAGrayscaleSetEnabled

These look to me like exactly the names of functions that the preference pane is calling in order to check the current state, and to set the updated state, of the “Use grayscale” checkbox. The capital “U” stands for “Unimplemented.” I.e. it expects to find these symbols, function names in this case, in another library. But which library?

otool -L UniversalAccessPref

The “otool -L” command will dump all the libraries that the preference pane “links to,” meaning the libraries it expects to load functions or data from. There’s a huge list of frameworks in the output, but the most interesting one to me is:

/System/Library/PrivateFrameworks/UniversalAccess.framework/Versions/A/UniversalAccess

The framework name “UniversalAccess” correlates strongly with the “UA” prefix on the pertinent function names we dug up above. Great, so how do we call these? They’re private system functions which means you should not rely on them for production code, but for a quick hack to make toggling grayscale easier? It’s a reasonable risk in my opinion. Here’s a simple C program that takes advantage of the private methods to simply toggle grayscale mode on or off, depending on the current setting.

If you wanted to assign this functionality to a keystroke, as originally suggested, the easiest way in my opinion is to use an app like my own FastScripts. You could drop the compiled binary above into your ~/Library/Scripts folder, and run it directly from FastScripts. Or, if you don’t want to fuss around with compiling a C program, just copy and paste this AppleScript:

-- Line up a Python script for dynamically loading 
-- the private framework  and invoking the required
-- private methods to get current grayscale mode
-- and set it to the opposite value.
set toggleGrayScript to "python -c 'from ctypes import cdll
lib = cdll.LoadLibrary(\"/System/Library/PrivateFrameworks/UniversalAccess.framework/UniversalAccess\")
lib.UAGrayscaleSetEnabled(lib.UAGrayscaleIsEnabled() == 0)
'"
do shell script toggleGrayScript

This script takes advantage of Python’s ability to dynamically load an arbitrary shared library and invoke its exported functions. I wondered if I might be able to use AppleScript’s own “use framework” functionality but I couldn’t quite figure it out.

Hopefully this has been instructive generally for folks who are interested in hacking at system frameworks, and specifically for folks who were looking for an AppleScript for quickly toggling macOS grayscale mode on and off.