As I write this, I have just pressed the submit button on my first app written in Swift: Sun & Moon. I covered it briefly before, but in short, it’s an app for checking the rise and set times of the sun and moon either locally or at a city somewhere on the planet. It was a project both to familiarize myself more with Swift and to test out iAd as a revenue source.
In developing the app I expected the major hurdle to be learning Swift itself. It wasn’t, and I was actually pleasantly surprised by most of the design choices made with the language. Instead, I encountered more problems with the immaturity of the tooling and build processes than anything else.
The biggest time sink was definitely the accumulation of time needed to decipher and resolve the cryptic errors reported by Xcode. While many of these may have been obvious or avoided entirely with more experience, the fact that they hid the underlying issue provides an unnecessary hurdle for learning Swift.
Expression was too complex to be solved in reasonable time
This error message was an enigma, particularly for myself without any real Swift experience yet. Shouldn’t a modern computer be able to handle a relatively simple floating point expression without even a stutter? Why then was the compiler choking? Only by doing what the error suggested, splitting the expression into smaller chunks, was I able to figure out the actual cause: the values stored in the
components object needed to be explicitly cast to
Double, something totally unneeded in the Objective-C world.
Had this error message been the one originally shown the solution would have been much more obvious.
Expected #else or #endif at end of configuration block
The main Sun & Moon app and its Today widget share some code related to checking for the IAP purchase that unlocks the widget and removes the ads. They use a compiler-defined constant to segregate the exclusive blocks. Prior to Xcode 7.2 this led to an error if the #endif line was the last in the file.
For most of iOS development’s history CocoaPods has been the de facto standard for integrating open source libraries. With Objective-C it functions by building everything into a static library that’s bundled directly into the binary. With Swift it was changed to build individual frameworks for each Pod that are copied into the app package during a late build phase. This functions fine (in development anyway) but fails catastrophically when attempting to upload to iTunes Connect.
In short, bundled frameworks are not allowed in NSExtension bundles. Fortunately for this project I had no need to use any in the Today widget, so it was just a matter of ensuring it didn’t link to any Pods. For projects that do have the need, there doesn’t seem to be a solution as the GitHub issue for the problem is still open.
Other Rough Edges
The warning in the last screenshot above is one of the rough edges, and while it still works correctly with that there, I don’t like having warnings. Both Portfolio for iPad and Studio Pro are around 100,000 lines of code each. Sun & Moon is less than 10% of that. The only potential legitimate reason I can see for this warning is that because the Swift runtime is still bundled with the app binary, it is getting included in that API analysis file.
While not necessarily exclusive to Swift, this second persistent warning is just as unfixable. It’s warning about the iAd banner having an incorrect size despite being the size it wants.
Despite these complications, I do feel Swift is the right decision going forward for new projects. It’s a skill that’s going to be increasing in demand, so it only makes sense to improve my proficiency with it.
That said, I don’t plan on merging Objective-C and Swift in any of my projects for the foreseeable future. I prefer to keep the sources separate and avoid the complications that I’m sure would arise from mixing, complications that will probably only increase as the languages diverge more.