Insidious Bugs
š Insidious Bugs #1: Today Extensions
This app could not be installed at thisĀ time.
Today Lickability is relaunching Insidious Bugs on our blog. Insidious Bugs is an occasional series in which we share stories of overcoming obscure issues in iOS development with the goal of saving you the time we lost, should you encounter the issues yourself.
The Bug
In this first entry, we conquer an instance of Xcodeās friendly āThis app could not be installed at this timeā message. We encountered this when attempting to run our project that includes a Today Extension, or widget, in the iOS Simulator.
Uhhhhhhh⦠okay?
The Solution
Wait, what?
Would you believe that all it took to solve this issue was this seemingly useless file? Well, that and many, many hours of failed attempts.
How We GotĀ Here
āThis app could not be installed at this timeā doesnāt give us a lot to work with, but letās explore the somewhat unique setup that got us here.
We recently added Today Extensions to multiple projects, which all share the same layout. We tend to keep things DRY (donāt repeat yourself), so we made our approach generic and reusable across multiple projects via a shared framework. In our framework, the Today Extension displays an arbitrary number of cells that have a thumbnail image and two labels. The framework doesnāt care what type of content is to be displayed, whether itās social media posts, news, reminders, etc.āit simply formats and displays the data written to the shared container by the host app in the exact same way. Hereās an example:
Youād buy this app,Ā right?
Hooray! This will save us time and tedious boilerplate as we add our Today Extensions to our projects. We simply need to add the framework and associate the view controller in MainInterface.storyboard
(part of the Today Extensionās target) with the one found in the framework. At least thatās what we thought. Everything compiled just fine, but we couldnāt debug our app. āThis app could not be installed at this time.ā š¤ Since Xcodeās message didnāt point us in any particular direction on how to resolve the bug, we searched log files for anything that was amiss. Every time weād attempt to build and run, a message similar to the following was printed to mobile\_installation.log.0
within the simulatorās logs folder:
<err> (0x700008983000) -[MIExecutableBundle makeExecutableWithError:]: 1162: Failed to chmod /Users/Michael/Library/Developer/CoreSimulator/Devices/51417E58-232D-45D5-9DAB-EB4C6F0AA301/data/Library/Caches/com.apple.containermanagerd/Bundle/Application/0D7DF887-D2D6-45F7-86DB-AACE8F2AE875/LickabilityTweets.app/PlugIns/TodayExtension.appex/TodayExtension : No such file or directory (NSPOSIXErrorDomain:2 (null))
This error was more descriptive, but still didnāt lead us to a solution. āWhy wouldnāt the app extension exist on disk after a build succeeded?ā we asked, before making dozens of trial and error attempts across several hours to no avail.
Eventually, we found that moving the view controller back to the Today Extension target would resolve the issue, but we werenāt satisfied with duplicating that file across multiple projects. In a stroke of genius (read: luck) we asked each other, āWait⦠is it the fact that the view controller needs to be a part of the extension target, or is it just that we linked something to the target that made the difference?ā After all, our āCompile Sourcesā build phase required nothing, since by design, any executable code used by the widget would live in our shared framework.
What a lonely targetĀ š¢
So we just added something to our target to see if it made any difference. A single Swift file without any code.
Build Succeeded! Installing! Success! It worked⦠that was it?!
š š”š
We thought we had it. But at least we could build and run now. On launch of the Today Extension target, Xcodeās console would display the following:
Unknown class \_TtC19SharedExtensionCode19TodayViewController in Interface Builder file.
It seemed as though despite the fact that we were selecting the appropriate view controller class from the appropriate framework within MainInterface.storyboard
, our class was still nowhere to be found at run time. After much more trial and error, we added a bit more code to FixEmptyTarget.swift
. We wanted to make sure everything was properly linked. We imported our shared framework into the file to see if it built (it did) and wrote some test code to see if we could actually make reference to the view controller class (we could). š§ āHow come we can reference this view controller from a different framework in code, but not in a storyboard?ā we pondered. We tried running this, just to see if anything more helpful would print to the console with our reference to the disappearing view controller in code, andā¦
Whaaaaaaaaaaaaaaaaaaaaat š¤Æ
Michael: That⦠did it?
Andrew: Itās time to relaunch Insidious Bugs.
Simply referencing our view controller in code and adding an otherwise useless file to our target solved this mysterious series of problems, and now we finally have our Today Extension framework. The full, documented version of FixEmptyTarget.swift
looks like the following:
Bananas, right? We sincerely hope you donāt encounter an issue like this in your travels. And if you do, we hope this post helped you get back up and running quickly!
Radars
Here are the bugs weāve filed for Apple about these issues:
- Today Extension with no linked files fails to install in the simulator (39237943, closed as intended behavior)
- Follow-up: Difficult to understand error message with today extension that has no linked files (39974757)
- View controller referenced only from a storyboard not found at runtime (39238390, Closed as duplicate of 4691676)