Category Archives: Bug Reports

Internal Typealias Promotion

In some scenarios it might be useful to declare a typealias internally to a module, to make it easier to implement the functionality of the module itself, but less useful to export that typealias to clients of the module. For example, consider an image manipulation framework that can work with NSImage or UIImage instances, depending on the platform. Internally to the module, I might define:

#if os(macOS)
	typealias RSPlatformNativeImage = NSImage
#else
	typealias RSPlatformNativeImage = UIImage
#endif

Then I can implement methods, including public facing methods like:

public func monochromeImage(fromImage image: RSPlatformNativeImage) -> RSPlatformNativeImage { ... }

Since I haven’t marked my typealiases as ‘public’, they won’t be exported to clients, but the above will also fail to compile. Swift requires that public methods work only with public types. This makes sense, because if the types aren’t public, how are clients expected to be able to work with them?

But if I mark the typealiases public, I impose a new type “RSPlatformNativeImage” on clients, when as far as they are concerned, this method operates on either an NSImage or UIImage. They might quickly get the idea that RSPlatformNativeImage is just a typealias, but it’s a bit of unwanted clutter on the public-facing API.

Obviously I can solve this by adding more platform-specific directives to the module so that whole functions are declared as working with either NSImage or UIImage, but it would be nice if Swift would help me out here. Instead of giving a compiler error, Swift could simply export the method using the public type that the typealias resolves to. In which case a client of the module for iOS would see the method as:

public func monochromeImage(fromImage image: UIImage) -> UIImage { ... }

And for Mac:

public func monochromeImage(fromImage image: NSImage) -> NSImage { ... }

Handling internal typealiases like this would cause the behavior for Swift clients to match what is already being done for Objective-C clients. The generated Module-Swift.h for this method in a Mac project is:

- (NSImage * _Nonnull) monochromeImageFromImage:(NSImage * _Nonnull)image SWIFT_WARN_UNUSED_RESULT;

Thus for Objective-C clients the clutter of the typelias definition is tidied away, but for Swift clients, it must still be dealt with. I filed a bug requesting this behavior in the Swift bug tracking system.

Helpless Help Menu

I was alerted by Christian Tietze of a pretty bad usability bug in macOS High Sierra. If you are running a Mac app, click the “Help” menu, and then dismiss it, whatever UI element you were focused on in the app loses its focus and does not regain it after dismissing the menu.

The problem is so bad that tabbing, clicking other UI elements, even switching to another app and back does not restore focus on the window’s responders. If the focus was on an NSTextView, such as the editor in MarsEdit, then the blinking cursor continues to animate, but keystrokes are ignored and simply cause the app to beep.

Christian filed a bug, and shared a workaround: set the delegate of the Help menu to your app’s delegate, and listen for the “menuDidClose” delegate method. If it’s the Help menu, restore focus manually.

I generalized this workaround to an approach that should work for whatever window, and whatever responder is currently focused when the Help menu is opened. By saving the window and the responder at “menuWillOpen” time, it can be precisely restored afterwards:

private weak var lastKeyWindow: NSWindow? = nil
private weak var lastResponder: NSResponder? = nil

func menuWillOpen(_ menu: NSMenu) {
   if menu == NSApp.helpMenu {
      if let activeWindow = NSApp.keyWindow {
         self.lastKeyWindow = activeWindow

         if let activeResponder = activeWindow.firstResponder {
            self.lastResponder = activeResponder
         }
      }

      // If the responder is a field editor, then save 
      // the delegate, which is e.g. the NSTextField being edited,
      // rather than the ephemeral NSTextView which will be 
      // removed when editing stops.
      if let textView = lastResponder as? NSTextView,
         textView.isFieldEditor {
         if let realTarget = textView.delegate as? NSResponder {
            lastResponder = realTarget
         }
      }
   }
}

func menuDidClose(_ menu: NSMenu) {
   if menu == NSApp.helpMenu {
      if doWorkaround {
         if let actualKeyWindow = self.lastKeyWindow {
            actualKeyWindow.makeKeyAndOrderFront(nil)
            actualKeyWindow.makeFirstResponder(self.lastResponder)
         }
      }
   }
}

Note that I didn’t clear out the weak var references to the lastKeyWindow and lastResponder. The reason is because part of the bug here involved NSMenu’s menuWillOpen and menuDidClose getting called more often than they probably should be. It’s probably the root issues that is causing the Help menu to excessively take control of the key window. It turns out we are going to get called on menuDidClose twice, so we need to be sure the desired target window and responder are still available the second time around.

As Christian points out, the workaround fixes the worst aspect of the bug: locking up the UI so that typing is ignored, but the focus ring around the target text field doesn’t always get redrawn as expected. My theory is that the focus ring animation is in the process of drawing when the second “menu will open” event is generated, causing the Help menu to reactive itself. The field being reactivate again very shortly after somehow doesn’t trigger the need to redraw the focus ring as you might expect.

I filed an additional bug, Radar #39436005, including a sample project that demonstrates both the bug and the workaround. Until Apple fixes this, Mac developers may want to implement a workaround along the lines demonstrated here. Given the horrible user experience associated with this bug, hopefully Apple will fix it promptly!

App Store Upload Failures

I’ve been running into failures to connect to iTunes Connect through Application Loader. Others corroborate similar problems uploading through Xcode. The nut of the problem comes down to a failure to authenticate a specific Apple ID. The failure string is “Unable to process authenticateWithArguments request at this time due to a general error”:

Image of the Sign In window for Application Loader showing a failure message

Whatever is going on, it’s somewhat sporadic. It started failing for me about 48 hours ago, and briefly started working again yesterday, but only for a few hours. Changes of network, computer, even clearing out all the app preferences and data for Application Loader, seem to have no impact on the issue.

I’ve filed a bug with Apple (Radar #36435867), and discovered a workaround you can use in a pinch: add another Developer ID to your team. I was able to grant admin privileges to a second Apple ID I control, and use it to log in and upload to my account. I’m not sure if this workaround requires a “company” style developer account, or if it can also be used for individual accounts.

Treat Warnings as Errors in Swift

For years I have maintained a zero-tolerance policy for warnings in shipping code. To help me enforce this, my “Release” build configurations define the build setting that induces Xcode to “treat warnings as errors”:

GCC_TREAT_WARNINGS_AS_ERRORS = YES

The comedy of this build setting is that it references “GCC,” a compiler that increasingly few of us even remember Apple ever using for macOS or iOS development. Apple’s fork of the popular open-source compiler was the standard for years, until Apple debuted clang, which is built on the LLVM framework.

It’s always been kind of annoying that, as time moved on, we were stuck specifying important build settings with names that included “GCC,” but I accepted it. After all, I configure the vast majority of these settings in “.xcconfig” files that I reuse in all my projects, so I almost never interact with them directly.

As I’ve started to shift some of my code from Objective-C to Swift, I assumed that my ancient GCC build setting would ensure that I don’t ship any builds with warnings. But today I realized that I had built a release build that didn’t treat a warning as an error. What’s the deal?

It looks like Apple has decided to break with tradition and establish a new build setting for Swift:

SWIFT_TREAT_WARNINGS_AS_ERRORS = YES

Adding this to my .xcconfig file breaks the build when a warning is generated, and prevents me from accidentally shipping code that is known to be vulnerable to unexpected behavior. I think it would have been a nice touch if Apple had inferred SWIFT_TREAT_WARNINGS_AS_ERRORS when GCC_TREAT_WARNINGS_AS_ERRORS is set, so I’ve filed a bug requesting that it does. Radar #35352318.

Swatch Your Step

Shortly after macOS 10.13 was released, I received an oddly specific bug report from a customer, who observed that the little square “swatches” in the standard Mac color panel no longer had any effect on MarsEdit’s rich text editor.

Screenshot of the macOS standard color panel.

I was able to reproduce the problem in the shipping 3.7.11 version of MarsEdit, which for various reasons is still built using an older version of Xcode, against the 10.6 SDK. The MarsEdit 4 Beta, which is built against the 10.12 SDK, does not exhibit the problem.

It’s not unusual for the behavior of Apple’s frameworks to vary based on the version of SDK an application was built against. The idea is usually to preserve the old behaviors of frameworks, so that any changes do not defy the expectations of a developer who has not been able to build and test their app against a later SDK. Sometimes, the variations in behavior lead to bugs like this one.

Using a totally straightforward demo app, consisting only of an NSTextView and a button to bring up the color panel, I was able to confirm that the bug affects an app that links against the macOS 10.9 SDK, but does not affect an app that links against the 10.10 SDK.

I filed Radar #34757710: “NSColorPanel swatches don’t work on apps linked against 10.9 or earlier.” I don’t know of a workaround yet, other than compiling against a later SDK.

Sandbox Inheritance Tax

I ran into a subtle bug with Xcode 9 that I think is worth sharing. Specifically, this bug affects Mac applications that:

  1. Are sandboxed.
  2. Launch a sandboxed subprocess with NSTask (or posix_spawn).
  3. Configure the subprocess to inherit the parent’s sandbox.

When such an app is compiled with Xcode 9, the subprocess will crash whenever the parent process launches it. A canonical example of something that might suffer from this problem is a bundled crash-monitor. I embed one with my apps to keep an eye on the running status of the parent process, and to present a crash-reporting interface to users if the host app terminates prematurely. When I build and run my app with Xcode 9, the bundled crash monitor dies instantly upon being launched.

It took me a while to realize that the subprocess is dying because it fails to satisfy the contract for inheriting a sandbox. From Apple’s “Enabling App Sandbox Inheritance“:

To enable sandbox inheritance, a child target must use exactly two App Sandbox entitlement keys: com.apple.security.app-sandbox and com.apple.security.inherit. If you specify any other App Sandbox entitlement, the system aborts the child process.

Well, that’s funny because my child process does specify only those two keys, but the system is aborting it anyway. It turns out that Xcode 9 is inserting a third entitlement without my permission. Clicking on the detail of the “Process Product Packaging” build phase in Xcode’s log navigator, I can see that there are three entitlements for my target:

Xcode build log detail showing the wrong entitlements.

When my subprocess is launched, the system sees that extra “com.apple.security.get-task-allow” entitlement in the context of “com.apple.security.inherit”, and unceremoniously crashes my the child process.

I’m not sure what Apple’s reasoning is for imposing this entitlement on sandboxed targets, but it appears to be doing so across the board, for literally every sandboxed target in my app. I confirmed that all of my apps, XPC processes, helper tools, etc., are all getting this bonus entitlement.

I searched Xcode’s files, and discovered the entitlement listed in this file inside the Xcode app bundle:

Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Xcode/PrivatePlugIns/IDEOSXSupportCore.ideplugin/Contents/Resources/BaseEntitlements.plist

Putting aside the question of whether it’s appropriate for Xcode to surreptitiously add entitlements that are not specified by the developer’s own list of permissions, the addition of the entitlement for these particular targets, ones that inherit their parent’s sandbox, turns out to be a fatal move.

Ideally I would be able to work around this by adding a custom build phase to manually tweak the generated entitlements file, removing the unwanted key. But the “Process Product Packaging” build phase happens so late in the build process that it’s after the last user-specified custom build phase. There’s no room in Xcode’s current design for fixing up the problematic entitlements before they are incorporated into the signed product. As far as I can tell the only clean workaround would be to redundantly re-sign the child app with a custom script, and corrected entitlements, after Xcode’s build process is completed.

I filed Radar #34628449, “Sandboxed project build with Xcode 9 cannot launch child process.”

Update: Colin Barrett pointed out on Twitter that the entitlement in question here, “com.apple.security.get-task-allow”, may be required in order to attach to and debug a process. If true, then I think this is something that was handled in a different way in Xcode 8. I can confirm that my apps do not have the entitlement imposed on them by Xcode 8, yet I am able to attach to and debug them.

If Apple changed the debugger infrastructure in Xcode 9 so that the relationship between the debugger and target processes is more locked down, requiring a specific entitlement, then that’s probably a good thing. But if this change was made without thinking about the implications for the above-cited “strict two entitlement” rule for sandbox inheritance, then probably some flexibility needs to be applied to that rule.

Finally, as I noted above the entitlement is being applied to all my targets. What I didn’t clarify is that the entitlement is added even when Building and Archiving. A release build’s binaries are endowed with this additional entitlement, which may also bring additional security vulnerabilities to the app.

I would not ship a sandboxed Mac app that is built with Xcode 9, until we understand more about when Xcode applies this entitlement, and whether it can be prevented for Release builds at the very least.

Update 2: I’ve learned that Xcode’s “Export Archive” functionality causes the unwanted entitlement to be removed. Apparently the assumption is that everybody creates Xcode archives as part of their build and release process. I am sure this is true for most (all?) iOS deployments, but for Developer-ID signed apps on the Mac, there has traditionally been less of an incentive to do this. Got a properly signed Mac application? Zip it up, put it on a web server, and you’re done.

I’m not sure yet whether I’ll switch my build process to use archiving, or whether I’ll pull some other stunt to redo the code signing with corrected entitlements. In any case this has been quite an adventure today getting to the bottom of this. I updated my bug report with Apple to request that they provide some standard build flag that would prevent the problematic entitlement from being added from the start. In the mean time, I’ll explore one of the workarounds and get my builds back to fully functional!

Better Swift Completion

Apple released Xcode 9 earlier this week, and in spite of a few glitches here and there, I have found the update to be an overall improvement over Xcode 8. It’s nice that Apple continues to invest in the core tools for Mac and iOS developers.

I’ve been dabbling in more and more Swift development lately, and it’s brought to light a shortcoming in Xcode’s code completion which has unfortunately not improved in Xcode 9: completion of Swift function calls when there is a large quantity of candidates.

Take for example NSAttributedString. If I want to initialize a new instance in Swift, I type “NSAttributedString(” to bring up the list of compatible init methods I can choose from:

SwiftCompletion

The problem at this point is that I have to navigate the menu by hand. I can’t narrow down the list of completions any further by typing, because the very next character I type will be interpreted as the manual filling out of parameters of the NSAttributedString initializer.

BadCompletion

This is a situation where Objective-C gets much nicer treatment in the editor. Because completion in Objective-C begins when I start typing “init”, and because the named first parameter is part of the init message name, I can winnow down the results quite a bit:

Pasted Image 9 22 17 11 24 AM

Better still, because Xcode performs a fuzzy match on the typing, I can proceed to type the names of additional parameters to zero in completely on the variation I want:

MEAppController AppDelegate m Edited

When I accept the completion, all of my typing is replaced with the expected, templated parameter placeholders for the chose initializer.

I filed Radar #34594940 requesting better completion for Swift.

JavaScript OSA Handler Invocation

When Apple added support to macOS to support JavaScript for Automation, they did so in a way that more or less allows folks who invoke AppleScripts to invoke JavaScript for Automation scripts as if they were exactly the same. An abstraction in Apple’s Open Script Architecture (OSA) makes it easy for script-running tools to theoretically handle any number of scripting languages without concern for the implementation details of those languages.

This mostly works, but I recently received a bug report that shed light on a problem with Apple’s implementation of JavaScript with respect to invoking a specific named handler. The OSA provides a mechanism for loading and running a specific handler, or function, within a script. My app FastScripts takes advantage of this to query a script about whether it would prefer to be invoked in another process or not. Unfortunately, when it comes to JavaScript, Apple’s implementation runs the whole script in addition to running just the specific, named handler.

If you’ve got Xcode handy, you can use this simple playground content to observe the problem:

import OSAKit

if let javaScriptLanguage = OSALanguage(forName: "JavaScript") {
   let scriptSource = "Application('Safari').activate();" +
         "function boo() { ObjC.import('Cocoa'); $.NSBeep(); }"
   let myScript = OSAScript(source: scriptSource, language: javaScriptLanguage)

  // Only the behavior of boo should be observed
  myScript.executeHandler(withName: "boo", arguments: [], error: nil)
}

// Give time for the beep to sound
RunLoop.current.run(until: Date(timeIntervalSinceNow:5))

The named function “boo()” only invokes NSBeep, so when this playground is run, all that should happen is a beep should be emitted from the Mac. Instead, when it runs Safari becomes the active application. This is because in addition to running the “boo()” handler, it also runs the whole script at the top level.

A workaround to the bug is to wrap the top level functionality of a script in a “run()” handler, so where the scriptSource is declared above, instead use:

   let scriptSource = "function run() { Application('Safari').activate(); }" +
         "function boo() { ObjC.import('Cocoa'); $.NSBeep(); }"

I hope this helps the one other person on earth who cares about invoking JavaScript for Automation methods indvidually! (Radar #33962901, though I’m not holding my breath on this one!)

Xcode GitHub Integration

Apple’s beta release of Xcode 9 features impressive improvements to its source control features, including streamlined integration with GitHub. There’s even a fancy “Open in Xcode” button when you go to clone a project:

Screen capture of the GitHub interface for cloning a project

This integration is amazing. You just click the button, specify a save folder in Xcode, and boom! You’re off and …

Screen capture of build failure indicating a missing signing certificate

Oh, right. Code signing. The otherwise stellar GitHub integration in Xcode underscores a longstanding deficiency in how it manages code signing identities for multi-team, collaborative projects. Precisely the kinds of projects you’re liable to find on GitHub.

The problem could be solved, or at least diminished greatly, by providing some mechanism for declaring that a project should be code signed “with the user’s own default developer team.” The default branch of any open source project targeting Apple platforms, would specify the DEVELOPMENT_TEAM as something like:

DEVELOPMENT_TEAM = Automatic

Xcode would provide a user-level setting for “Default Development Team”, and in the absence of any overriding setting, that team would be used whenever a project was configured as above.

I wrote about this problem once before, but with all the work being put into streamlining the experience of cloning from and pushing to GitHub, now is an ideal time for Apple to embrace a fix. Radar #32614751.

Another issue that stops short the cloning, and immediate building and running, of open source projects, is the need to fulfill external dependencies. In some cases this might require manually downloading and installing libraries, or cloning projects, but in the vast majority of cases the dependencies will be specified using built-in Git submodule support, or a popular package manager. In each of these cases, it should be trivial for Xcode to detect that the project it has just cloned also has dependencies:

  • Git submodules: there is a .gitmodules directory.
  • Carthage: there is a Cartfile file.
  • CocoaPods: there is a Podfile file.
  • Swift Package Manager: there is a Swift.package file.

If Xcode sees evidence of any of these techniques at play, it could do the favor of checking them out immediately after cloning the project. Radar #32615265.

The GitHub integration coming in Xcode 9 provides a nearly effortless capability for cloning, building, and running open source projects that target Apple platforms. Ideally it would also go the extra mile and provide for variable, dynamic development teams, as well as conduct a rudimentary check for dependencies that must be checked out before commencing work on the project.

Implicit Swift Dependencies

If you’re developing in Swift for Mac or iOS, you need to ensure that any standard Swift libraries are also copied into your app bundle. Typically this is handled automatically by Xcode when it detects the presence of any Swift files in your app. If your app is entirely Objective-C, but you link against your own frameworks that themselves depend on Swift, you have to ensure the required libraries are embedded. This can be done by setting the “Always Embed Swift Standard Libraries” checkbox in your target’s build settings to “Yes”:

AlwaysEmbed

When this option is set, Xcode scans the bundled frameworks in your app and, if any of them contains Swift code, it copies the pertinent libraries into your app’s bundle.

This approach falls down a bit when it comes to Unit Testing targets. Because a Unit Test bundle doesn’t typically copy the framework it is testing into its own bundle, Xcode seems to deduce dependencies by examining the list of frameworks the test bundle links to. If you enable the “Always Embed” option above for a Unit Testing bundle, then any framework the bundle links against will be examined for Swift code, and the required libraries copied in.

But what if none of the linked frameworks themselves require Swift, but they depend upon other frameworks that do? In projects of a substantial size, you may have higher-level frameworks implemented entirely in Objective-C, that depend upon lower level frameworks that use Swift. In this scenario, Xcode’s CopySwiftLibs build phase does not identify the deeper dependency, and neglects to embed the required Swift libraries. When your unit tests run, you’ll see a runtime error like this:

The bundle “RSTextFilteringTests” couldn’t be loaded because it is damaged or missing necessary resources. Try reinstalling the bundle.
(dlopen_preflight([...]/RSTextFilteringTests): Library not loaded: @rpath/libswiftAppKit.dylib
  Referenced from: [...]/RSAppKit.framework/Versions/A/RSAppKit
  Reason: image not found)
Program ended with exit code: 82

So “Always Embed Swift Standard Libraries” doesn’t always embed them. I’ve filed Radar #30832923, requesting that the CopySwiftLibs build phase look harder for Swift dependencies. In my opinion it should look not only at the directly linked frameworks, but at any developer-supplied frameworks that those in turn depend upon. This would cause “Always Embed” to behave as expected when a developer adds Swift dependencies to frameworks at any level of their code base.

There are many possible workarounds to the problem, and each has its own drawbacks. Here are a few:

  1. Add a Swift-based unit test file to your test bundle. This simple workaround will work in most situations, because the test itself will impose many Swift library dependencies on your bundle. There is a shortcoming, though: if the test code doesn’t generate all the Swift dependencies that your frameworks do, you’ll still be left with missing Swift libraries. For example if a dependent library requires the Swift library for Apple’s Contacts.framework, your Swift test file is not sufficient to cue Xcode to copy the required libSwiftContacts library.
  2. Manually link to Swift-dependent frameworks. Suppose your unit tests target HighLevel.framework, and LowLevel.framework depends upon Swift. By adding LowLevel.framework to the list of linked libraries for your testing bundle, you will cue Xcode to also embed the required Swift libraries for that framework. This has the advantage of ensuring that whatever Swift libraries are required get copied, but it has the drawback of requiring explicit dependency on a lower level framework from your unit test bundle.
  3. Stop! Abort mission! Revert to Objective-C only. Many Swift dabblers probably feel this emotion from time to time. The unexpected costs of adding a modest amount of Swift to a project are frustrating, and one can’t help but wonder whether they would be better off waiting until Swift support is more baked in to the system. The obvious downside of this approach is that Apple’s progress with Swift is moving quickly, and the longer you put off testing the waters, the harder it may be for you to catch up when ignoring it is no longer a viable option.

The workaround I’ve settled on for now is #2. Adding unnecessary direct dependencies to my test bundle feels a little inappropriate, but it is both easily undone in the future, and unlikely to cause any real problems in practice.

In the course of investigating this problem, it also occurred to me that unit test bundles in particular are such a special case, that Apple should probably give them special treatment to eliminate a number of pitfalls. I filed Radar #30832983 suggesting that unit test bundles should default to “Always Embed Swift Standard Libraries,” on the assumption that Swift code may be present in some library.

Thinking further on that point, it seems that Unit Tests could be safely run in an environment in which all Swift support libraries are available at runtime to be resolved by DYLD. Because test bundles are not built to be shipped to customers, it’s of primary that they link and run successfully. Such an approach would do away with the need for Unit Test bundles to either specify that Swift libraries be bundled, or to fret about which of those libraries in particular need to be copied.