Category Archives: Xcode

Interface Builder: View Is Clipping Its Content

If you have Xcode’s “Show live issues” enabled, you’re used to seeing (usually) helpful warnings and notices about your source code and interface files. These notices appear even if you haven’t yet built your project:

Image of Xcode Interface Builder warning about a view clipping its content.

If you click the “View is clipping its content” notice, it takes you right to the view in question:

Image of a popup button on the Interface Builder canvas.

At this point you can usually just “size to fit” and Interface Builder will use its knowledge of the control’s class, and that class’s ability to size itself to suit its content. Or, if you’re using Auto Layout, it might mean that you need to ask Interface Builder to update the items’s frame, allowing Auto Layout to essentially size to fit for you.

In this case however I have a conundrum: both “size to fit” and AutoLayout insist this is the proper size and placement for the control, yet Interface Builder is still convinced the control will clip its content (the text of the menu item title).

What happens if I naively attempt to increase the width of the popup button?

Image of a popup button with error messages indicating it is the wrong width.

The clipping area is gone, as Interface Builder is convinced the button is now wide enough, but that width is in conflict with what Auto Layout is convinced is the right width.

I can’t win: if I let Auto Layout have it’s way, I get an annoying clipping notice. If I let the clipping notice have its way, Auto Layout throws a fit.

One workaround, when working with Auto Layout, is to provide a bogus constraint that forces the width of the popup button to the width that I’ve manually imposed. By setting it to “Remove at Build Time” it should not have any effect on the behavior of your interface, except in Xcode itself.

WidthConstraint

See that empty “Identifier” field? I have actually taken advantage of that field as an opportunity to add a memo to myself for future reference: “Work around bug 25938”. This references my internal bug tracking the issue, so I can re-acquaint myself with the problem if I find myself wondering about this bogus constraint in the future.

It seems to me the bug here is either that NSPopUpButton sizes to fit at too narrow a size, technically causing “clipping” of its subviews. Alternatively, Interface Builder’s deduction of a view’s size causing clipping has some bug in it. Either way, I’ve filed the issue as Radar #30222922.

Update, January 28, 2017: Thanks to a tweet from Mark Lilback, I discovered the notice about clipping is a bit less pervasive than I thought. The notice only seems to appear when Xcode has the xib file actively open for editing with Interface Builder. What this means practically is that you have to click on the xib file at some point and have the editor appear for it, before the notice appears. It also means that if you cause Xcode to close the file for editing, the notice disappears. You can close any file in Xcode by focusing on its editor and then selecting File -> “Close <filename>”, or by pressing Cmd-Ctrl-W.

I have always found these kinds of notices in Xcode to be somewhat unpredictable. The fact that the file has to be actively opened for editing, combined with the fact that files remain open in Xcode after their editor is visually swapped out, explains most of the apparent inconsistencies I’ve seen.

Unbuffering Jenkins Output

For years I have used Jenkins to manage all my automated Mac and iOS builds. I have jobs set up to build and release apps “on demand,” as well as integration builds that kick off whenever a change is made to a pertinent source code repository.

For years I have also put up with a small but vexing nuisance that when something goes wrong with a build, I have to search in the most unlikely place for pertinent informational messages printed by my build scripts: at the very bottom of the log.

I had chalked it up for so long to being a nuanced Jenkins bug, that I never took the time to get down to basics and really unwrap what is going on. Today, I did that, and also came up with an easy solution.

I use a custom script to drive the whole process for each of my automated builds. This script is responsible for printing diagnostic information and for invoking other tools (such as xcodebuild) to get the actual work of building, testing, and uploading done.

The problem with the misplaced log lines in my console output has to do with a feature of the scripting language I use to drive the process: standard output buffering. I use Python, but the problem could also affect you if you use a language such as Ruby to drive your automation.

Here’s a contrived example of a build script that will exhibit the problem. If you create a new, empty Jenkins build job, and configure it with a single “Execute Shell” build task:

#!/usr/bin/python 

import os

print "start"
os.system("ls -ld /Applications/TextEdit.app")
print "end"

You will find the generated console output upon “building” this job is demonstrably out of order:

[workspace] $ /usr/bin/python /var/folders/wh/f_vmqvxx34d69c1pm191t0tr0000gq/T/hudson321577740740596707.sh
drwxr-xr-x@ 3 root  wheel  102 Dec 13 14:00 /Applications/TextEdit.app
start
end

The message from the “ls” subprocess prints right away, but Python buffers the output until it’s done running, leading a nonsensical printing of the “start” and “end” messages after the job is completely done.

Now I will make a tiny change, passing the “-u” parameter to the Python invocation in the script. This option is documented to “Force stdin, stdout and stderr to be totally unbuffered”:

#!/usr/bin/python -u

Running the job again in Jenkins produces the expected output in Jenkins:

[workspace] $ /usr/bin/python -u /var/folders/wh/f_vmqvxx34d69c1pm191t0tr0000gq/T/hudson3255283214356026397.sh
start
drwxr-xr-x@ 3 root  wheel  102 Dec 13 14:00 /Applications/TextEdit.app
end

This is a small annoyance in this example, but in a real-world scenario it means that the pertinent xcodebuild invocation, which I print to the console before calling, will now show up where it belongs in the console log, making it much easier for me to reason about the behavior of my automated builds when they aren’t working as they should.

Installing Symbols For WatchOS

For months I have been plagued by Xcode’s persistent failure to successfully install WatchOS device support on my Mac. If I open Xcode, and my iPhone (paired with an Apple Watch) is attached to the Mac, I am greeted by a progress indicator such as this:

InterfaceController swift

Because I don’t actually do any watchOS development, this has mostly been a mild annoyance. The bug doesn’t seem to affect the performance of my Mac, and other actions I perform in Xcode continue without delay. However, for those of you who are actually doing Watch development, if you run into this problem, you’ll be perpetually greeted by this error when you try to debug on a real device:

Xcode panel refusing to install on a device because of missing Apple Watch symbols.

The worst side-effect of this bug for me, and the problem that finally encouraged me to hunker down and solve the issue, is the fact that each attempt to “Install Symbols” is associated with a fresh download of a larger-than-200MB file from Apple to my Mac. This is no big deal on my home network, but when I’m roaming and tethered to my bandwidth-metered iPhone, it can lead to costly overage charges.

I’ve been to hell and back tracking down exactly how Xcode installs these symbols, where it fails, and how to work around the problem. I’ll give an overview of how Xcode’s symbol installation process works, and walk you through one concrete method for working around the problem, getting those precious symbols installed, and breaking the cycle of perpetual failed installations.

Symbol Installation Overview

First I want to give you a high level idea of how Xcode downloads and installs symbols. Here are the steps that take place:

  1. A device suitable for development is connected.
  2. Xcode looks for existing symbols in the suitable home directory location
  3. If symbols are not already installed, the symbol-installation process begins.
  4. A disk image file containing the required materials is downloaded to a temporary folder.
  5. The disk image file is copied to a Caches subfolder in your home directory.
  6. The disk image is mounted at a temporary location on your Mac
  7. A macOS Installer package on the disk image is used to install symbol files directly into your home folder.
  8. The temporary disk image is unmounted.
  9. The cached disk image file is deleted.

In my tests, the failure to successfully install watchOS symbols broke down in step 7, where the package is supposed to successfully copy symbol files into my home folder. I was able to determine that the Apple infrastructure responsible for the installation is failing on my Mac with a cryptic authentication error:

Could not download and install Symbols for watchOS 3.1 (14S471). Authorization is required to install the packages

The failure is not happening in Xcode per se, but in a helper tool that is part of the private PackageKit.framework. I filed Radar #29568241, in the hopes that somebody at Apple will have insight as the root cause of the problem, and how it can be fixed for good in either Xcode, or in the configurations of affected users’ Macs.

Fix It Yourself

To manually accomplish what Xcode is failing to do, we need to:

  1. Get a copy of the downloaded disk image.
  2. Copy the pertinent files out of the disk image’s installer package.
  3. Copy the pertinent files into the correct installation path in ~/Library/Developer/Xcode/

Because simply creating the directory at the installation path is enough to stop Xcode attempting to install symbols, I’m going to cover that first. Folks who don’t need or want the symbols for Watch development will solve the problem sufficiently after this step.

Determine the Installation Path

Unfortunately, the path is quite specific to the Watch device at hand, and may be difficult to guess. Here’s one way of figuring it out. Making sure you have an iPhone connected that triggers the symbol installation in Xcode, do the following:

  1. Quit Xcode.
  2. From the Terminal, navigate to Xcode’s binary executable folder:
    cd /Applications/Xcode.app/Contents/MacOS/
  3. Run Xcode with a special flag to cause additional logging to display:
    ./Xcode -DVTDownloadableLogLevel 3
  4. Wait for Xcode to launch and start installing symbols.
  5. Scan the output in Terminal for a line like this:
    Starting a download for Watch1,2 3.1 (14S471), to file path /Volumes/Data/daniel/Library/Developer/Xcode/watchOS DeviceSupport/Watch1,2 3.1 (14S471)/Symbols

    Of course, your output will be slightly different, but depending on the version of Watch and watchOS you have, the important part is relative to your home folder. In my case, I need to make sure this folder exists:

    ~/Library/Developer/Xcode/watchOS DeviceSupport/Watch1,2 3.1 (14S471)/Symbols

If you don’t care about Watch development, this is your big chance: just create that folder now. Quit and relaunch Xcode again, and you’ll see that your problems are over. No more symbol installations required. If you skim the logging output from above you’ll see that the “InstalledIfAllPathsArePresent” key in one of the dictionaries indicates that the path merely being present is enough to convince Xcode it’s “installed.”

If you do care about Watch development, you’re going to want those symbols. Let’s tackle that problem next.

Getting the Disk Image

Remember back in “Symbol Installation Overview,” I described the installation failing in step 7: where a package on a mounted volume is attempted to be installed. Unfortunately, this failure does not prevent steps 8 and 9 from proceeding, so when the whole procedure is over, there are no obvious artifacts left around to work with. The disk image, that was copied to ~/Library/Caches/com.apple.dt.Xcode/Downloads in step 5, is available for such a short period of time, you’re unlikely to nab it before Xcode deletes it upon failure.

You may have noticed in the Xcode logging output that many URLs to web resources are passed around. It’s likely that one of these contains the required disk image content, but I thought it would be safer to catch Xcode in the act and use precisely the disk image file that it itself was intending to use.

Yet another “secret” Xcode user default key can help us here. Once again, navigate to the Terminal to execute Xcode manually. This time, we’ll pass a flag that instructs it explicitly not to delete the coveted disk image file after it’s done:

./Xcode -DVTDownloadableLeaveTemporaryFiles 1

This time you’ll have to wait again until the process tries, and fails, but when you’re done you should find a suitable disk image file waiting for you at:

~/Library/Caches/com.apple.dt.Xcode/Downloads/Xcode.Symbols.Watch1,2.14S471-3.1.dmg

(Or with whatever name is suitable for the version of Watch and OS you are accommodating.)

Copying the Symbol Files Out

Double-click the disk image to mount it on your Mac. You’ll find a volume appears with a suitable device-oriented name, and a matching file within called e.g. “Watch1,1_Watch1,2.pkg”.

Warning: Do not open and install this package willy-nilly without reading the following carefully. This is a standard Installer package, and double-clicking it on your Mac will launch the system-standard Installer application. However, agreeing to let it “just install” on your Mac could have unintended consequences. The files in this package are named very similarly to many system files on your Mac, but of course these files are binaries for a ARM based Watch device, and not an x86_64 personal computer.

There are many techniques for getting the files out of an Installer Package without actually, you know, installing. You could use an app like Pacifist to extract them directly to a folder on your disk. There may also be a way to invoke the command-line “installer” tool in such a way that it simply spits the files out where you want them. For that matter, it might be safe to simply “Choose Folder…” from the Installer app, and trust that it will install everything in that folder instead of on the root of the volume.

Me? I decided to strike a semi-paranoid compromise. I used the Installer app, but instead of installing to my Mac’s main volume, I created a writable disk image in Disk Utility, and targeted that volume explicitly:

WatchHack

When the installation was complete, I had a mounted volume, filled with the contents that Xcode has presumably been intending to copy into my home folder.

WatchHack

Finish the Job

At this point you know correct install location in your home folder, and you have a copy of all the files that should be there. It should be as simple as selecting the files from “WatchHack” and dragging them to the “Symbols” folder in the appropriate ~/Library/Developer subfolder.

When the symbol files have been copied in, quit and relaunch Xcode. Not only should it avoid that nasty “Installing Symbols” phase, but building and running on your physical watchOS device should once again work as expected.

Xcode 6 On Sierra

Xcode 6 and Xcode 7 are not supported by Apple on macOS Sierra, and should not be used for production work.

But what if you have a good reason for running one or the other? Maybe you want to compare a behavior in the latest Xcode 8 with an earlier version of the app. Instead of keeping a virtual machine around, or a second partition with an older OS release, it is liberating to be able to run and test against older versions of Xcode.

So far, it appears that Xcode 7 “mostly works” in spite of being unsupported by Apple. I’ve run into some launch-time crashes, but reopening the app tends to succeed.

Xcode 6 will flat out fail to launch, because one of its internal plugins depends on a private framework (Ubiquity.framework) that is no longer present on macOS Sierra. If you were willing to hack a copy of Xcode 6, however, you could get it running. You definitely shouldn’t do this, but if you’re curious how it could be done, here’s how:

  1. Always have a backup copy of any data that is important to you.
  2. Locate a copy of /System/Library/PrivateFrameworks/Ubiquity.framework from the previous OS X release.
  3. Copy the framework to within Xcode 6’s own Contents/Frameworks bundle subfolder:
    ditto /my/old/System/Library/PrivateFrameworks/Ubiquity.framework ./Xcode.app/Contents/Frameworks/Ubiquity.framework
  4. Navigate to the problematic Xcode plugin and modify its library lookup table so that it points to the app-bundled copy of Ubiquity.framework, instead of the non-existent system-installed copy.
    cd Xcode.app/Contents/PlugIns/iCloudSupport.ideplugin/Contents/MacOS
    install_name_tool -change /System/Library/PrivateFrameworks/Ubiquity.framework/Versions/A/Ubiquity @rpath/Ubiquity.framework/Versions/A/Ubiquity ./iCloudSupport
    
  5. Now that you've modified Xcode, its code signature is invalid. You can repair it by signing it with your own credentials or with an ad hoc credential:
    codesign --deep -f -s - ./Xcode.app
    
  6. Did I mention you really shouldn't do this?

Apple has good reason to warn people off running older versions of Xcode, but if you absolutely need to get something running again, it's often possible.

Swifty SDK Changes

I’m not quite ready to leap to Swift 3.0, so when the Xcode 8 beta asked me to migrate my existing Swift code, I opted to switch to Swift 2.3.

Swift 2.3 is notable for its utter dearth of new behaviors, compared to Swift 2.2.1. Since no code changes are required, you should be able to opt in to 2.3 on Xcode 8, while continuing to build and distribute with Swift 2.2.1 on Xcode 7.

On the other hand, you may run into some system SDK changes that force you to accommodate distinctions between, for example, the macOS 10.11 and 10.12 SDKs. Here’s an example of a build failure I ran into when I set to building my app on Xcode 8:

Image of Xcode exhibiting a build-time error because of a Swift method call

“invalid use of ‘()’ to call a value of non-function type ‘Selector'”

What does it mean? It means that in the 10.11 SDK, “action” is defined as a method:

@protocol NSValidatedUserInterfaceItem
- (nullable SEL)action;
- (NSInteger)tag;
@end

While in the 10.12 SDK, it’s been upgraded to a property:

@protocol NSValidatedUserInterfaceItem
@property (readonly, nullable) SEL action;
@property (readonly) NSInteger tag;
@end

Objective-C doesn’t care whether you access the value as a property, or by invoking the method that implements the property. Swift … does.

So, the fix in Xcode 8, with the 10.12 SDK, is to delete those parentheses so Swift appreciates that it’s accessing a property. But doing so will break the build back on the 10.11 SDK. What’s a forward-looking, backward-looking developer to do? You might think you could take advantage of Swift’s #available operator, and that in fact best expresses what we’re trying to do: to behave differently depending on the specific SDK that is being used:

if #available(OSX 10.12, *) {
	thisAction = anObject.action
}
else {
	thisAction = anObject.action()
}

But this still produces a build error, because Swift compiles both code paths of an #available block. Unfortunately, I think the only way to convince Swift to absolutely ignore the problematic line is to use a Swift compiler check, instead. Note that this is a bad solution because we are fundamentally not concerned about the version of Swift being used. If Swift 2.3 were made available in Xcode 7, against earlier SDKs, then the logic of our test would fail:

#if swift(>=2.3)
	thisAction = anObject.action
#else
	thisAction = anObject.action()
#endif

In my opinion, we need a compile time, conditional code exclusion that operates on the SDK, similarly to #available. Something like “#if sdk(OSX 10.12)”. As far as I know, nothing like this exists.

I’ll report a bug to Apple requesting such functionality, but I wonder if I’m overlooking something obvious that already fits the bill. Any ideas?

Update: Radar #26895983.

Dynamic Development Team

The first Xcode 8 beta was released at WWDC, and includes a major revision to the way code signing is handled by default. You can watch the video or read the slides on Apple’s WWDC Videos page.

A major change from Xcode 7 is that Xcode now requires that every target in your project specify a development team, even when the manual code signing option is selected.

This is a nuisance to developers who have fine-tuned their code signing process such that signing is configured elsewhere: for example, in a centralized Xcode configuration file that imparts signing information to all projects in an organization.

The problem is worse for open source projects, where a project may be expected to be checked out and built by a variety of organizations. In this scenario, each organization will have to somehow automate the insertion of a valid team name and ID in the project file after every checkout or update.

The DevelopmentTeam and DevelopmentTeamName values are stored in the Xcode project file, so they can’t be defined in Xcode configuration files the way so many other settings that affect build behaviors can.

Xcode needs some mechanism for providing these values without manually, permanently altering the affected project files. I would welcome either a mechanism for specifying the values in the Xcode configuration file specified for the project, or a wildcard type value that can be selected to indicate the “default team” should be used.

(Radar #26892618)

Update: It turns out my wishes are already answered. The new PROVISIONING_PROFILE_SPECIFIER build setting will impart the desired team information to Xcode, even if provisioning profiles are not used. So, something like this in my Xcode configuration file:

PROVISIONING_PROFILE_SPECIFIER = 493CVA9A35/

Quiets all of Xcode’s gripes about requiring a team name, and doesn’t require that I tediously update every last target with explicit team information. This doesn’t exactly solve the challenge for open source projects, because organizations using an open source project will still have to override the configuration file or build settings for the projects they check out. As far as I know there is no way to define PROVISIONING_PROFILE_SPECIFIER generically, the way you can specify code signing identities as e.g. “Mac Developer”. It would be great if open source projects could declare a PROVISIONING_PROFILE_SPECIFIER (when needed) as:

PROVISIONING_PROFILE_SPECIFIER = Automatic/

And allow the host project’s prevailing team identity automatically apply. But, I am satisfied to know this at least doesn’t need to be manually set everywhere in order to continue building my projects successfully.

Scripted Swift Warnings

Since I complained yesterday about Swift’s lack of a counterpart to Objective C’s #warning directive, folks have been in touch to encourage another solution to this problem. I could take advantage of Xcode’s standardized, built-in support for text-based comments such as “// FIXME” and “// TODO”. Using this notation causes the affected source lines to show up in Xcode’s per-file function popup, and other folks affected by the issue I describe above have added scripted build phases to emit text that Xcode will treat as a warning for each of these lines.

I initially dismissed the solution out of hand, because I anticipated that searching all of my sources with every build would be excessive. I’m kind of a stickler for fast build times because I like to do quick iterations when writing and testing code. My largest source base, MarsEdit, is big but not huge. But, appreciating that computers and SSDs are fast, I decided to test the straightforward script linked above to see how much time it would add to each of my build iterations. On average, it’s about 1.2s per build. It doesn’t sound like much, but personally that would nag at me. I’ve made a fuss over build phase speeds in the past, and reported bugs against unnecessary slowdowns in Apple’s standard build phases.

Zev Eisenberg suggested on Twitter that the use of specialized search tools such as the_silver_searcher might help. It’s true, it might, but then I’d be going down a path of installing custom software, writing custom scripts, all to accommodate what is a very useful feature that I personally still believe should be built in to the language. Or, at the very least, the language’s feature set should accommodate efficiently extending it to support something like #warning.

We’ll see where things go. I may yet end up adopting a convoluted (to my mind) approach involving expensive, redundant build phase script that scans my entire source base with every build, but more likely I’ll keep scratching my head while using the one-line, inline hack that I previously described.

Artificial Swift Warnings

I’ve been tackling more and more of my coding challenges in Swift, recently. I’ve run into a number of hangups. Some attributable to the learning curve, some to bugs in Swift or Xcode, and some to features I’ve grown to love in clang and Objective C which are simply not present in Swift.

For years, I’ve been in the habit of tagging my in-progress code with “artificial warnings.” While working in code, if a concern crosses my mind, the easiest way to make sure I won’t ship the software without addressing that concern is to add it directly to the code:

#warning Step through this in a debugger and confirm it still works...

Or:

#warning This isn't implemented yet, need to handle XYZ...

These warnings serve as an active reminder of things to fix while I’m working in Xcode, since they show up in the build navigator, and are illuminated in the source code while stepping through with the debugger. And because of my strict “no warnings” policy for shipping code, they are guaranteed to show up as errors in any Release build, thus thwarting an accidental shipment of code that is known to need further refinement.

I don’t think Swift supports anything like the “#warning” preprocessor directive.

The closest I’ve come to matching this behavior is a trick that employs Swift’s willingness to emit a warning for unreachable code:

if false { "in lieu of #warning, this will do" }

Unfortunately, it only shows up in the issue navigator as “Will never be executed,” and doesn’t show the specific warning text contained in the string. But at least as soon as click on the warning, I am reminded of the concern at hand.

I don’t know if the Swift team is philosophically opposed to implementing support for #warning, or something like it. I filed an enhancement request with the Swift project. In the meantime, if false { “life goes on.” }.

Update: Many folks have suggested a build-phase script to tag warnings. I wrote more about that option in a followup post.

A Tale Of Two Optimizers

I have quipped a few times that my biggest problems with Swift so far have to do with struggles in the debugger. It seems slow, inaccurate, harder to use than in Objective C. Some of this is just a learning curve, but other aspects seemed fundamentally broken. I whined on Twitter about a scenario in which lldb seemed utterly unaware of one of my variables:

A kind Apple employee, Kate Stone, followed up with me and ultimately encouraged me to file a bug:

I obliged, filing Radar #26032843. Today, Apple got back to me with a followup, suggesting rather gently that I may have neglected to disable optimization in my target. Rookie move! The kind of behavior I was seeing in the debugger is exactly what happens when lldb can’t make as much sense of your code because of inlined functions, loops that have been restructured, etc.

In fact, I had correlated the symptoms with such a problem, but when I went to check on the status of my optimization settings, everything looked fine. Why? Because I was looking, by habit, at the Clang LLVM “Code Generation” settings for optimization:

MarsEdit xcodeproj

See? Optimization disabled. Just as it is for all my projects, and all my targets, because I define it once in my centralized Debug “.xcconfig” file, to be sure I never screw it up:

// We only specify an optimization setting for Debug builds.
// We rely upon Apple's default settings to produce reasonable
// choices for Release builds
GCC_OPTIMIZATION_LEVEL = 0

So why does debugging Swift fail so hard for me? Because Swift doesn’t use that optimization setting. Scrolling down a little farther, I find the culprit in Swift’s own compiler settings section:

MarsEdit xcodeproj

So the lesson is that new Swift developers coming from a legacy of Objective C, C++, or C development need to take stock of Swift compiler settings because they are liable to be rooted in completely different build settings. On the one hand, I’m glad Apple is finally able to get away from a build setting like “GCC_OPTIMIZATION_LEVEL” (though keeping the name in the GCC -> LLVM transition prevented problems like this back then), but on the other hand, it’s kind of annoying to have to express high level directives that affect whether my code will be debuggable or not using multiple build settings.

At least, because I am not an animal, this will also only ever need to be done once, with an edit to the pertinent “.xcconfig” file:

// We only specify an optimization setting for Debug builds, we rely upon
// Apple's default settings to produce reasonable choices for Release builds
GCC_OPTIMIZATION_LEVEL = 0
SWIFT_OPTIMIZATION_LEVEL = -Onone

Now if you’ll excuse me I’m going to take a tour of other Swift-specific compiler settings to make sure I’m not shooting myself in the foot in some other way!

Careful What You Wish For

I am a well-known proponent of bug filing. In fact, I filed a bug last year that argued Xcode should apply the custom Code Signing Flags for a project when code signing the bundled Swift libraries that are installed in in an app’s bundle.

I noticed that at some point along the way, Apple did fix the bug! Exciting! Time to rejoice, no? Well, no. Because while the fix for the bug addressed my original complaint, it brought a new headache which I hadn’t anticipated.

For my app MarsEdit, I supply a custom designated requirement for the code signing phase. The long and short of this approach is that through careful specification of a designated requirement, you can arrange it so that if the user stores an item in the keychain from one version of your app (say the Mac App Store version), then the same app can access the data later without prompting the user, even if it has a different bundle ID, or is signed by a different identity (say, because it’s a direct sale version).

The problem I’m running into now, as I dabble with adding Swift-based code to MarsEdit, is the bundled Swift libraries are being signed with my app’s custom designated requirement. Oops. This never would have happened if Apple hadn’t … fixed the bug I reported.

I’m not sure what the right solution is, or even how to best approach a workaround. The copying of Swift libraries and their subsequent signing is not only opaque to developers, but it happens after the entire user-configurable build process is done. It seems as though to work around the problem in such a way that I can still supply a designated requirement for my app, I may need to avoid adding the flag to OTHER_CODE_SIGNING_FLAGS, and amend the designated requirement on my own sometime after the Xcode build process is complete.

I find the code signing configuration options to be pretty troubling for this reason, among others. The highest level code signing identity (and now flags) are used implicitly by Xcode for some code signing operations that are opaque to developers. It puts us in a bind when something subtle turns out to be not quite right with the resulting built product.

I filed a new bug, Radar #25579693, to raise the issue with Apple about the can of worms that fixing my previous report has caused. In the mean time, I’m on the hunt for workarounds! I’ll update this post when I feel I’ve got something good.