Today, we’ll talk about manually symbolicating iOS and OS X application “crash reports.” Why? When you hear about a crash in one of your apps from a customer, the first thing you should do is try to get a copy of the crash report. But there are times when you get crash reports that aren’t automatically symbolicated, or that you can’t symbolicate by dragging into Xcode, or are partially symbolicated. When not symbolicated, you’re reading numeric addresses when you want to be reading code, like your function/class names. There are workarounds and we’ll discuss one today. Download the sample Xcode 9 project written in Objective-C to follow along. What’s a crash report, anyway? According to Apple:
With this article, I’m starting a series about all the goodies — useful tools — that can be found in Xcode. Some of these tidbits are tools everyone knows about while others are barely documented to undocumented. For example, how many of you know that you can view, inspect, and debug all your Auto Layout constraints live during app execution using the “Debug View Hierarchy” Xcode feature? I discussed that feature in detail in this article, “Troubleshooting Auto Layout using Xcode’s Debug View Hierarchy.” Today, we’ll discover two editors that ship with Xcode, the “Open As > Hex” and “Open As > Source Code” editors, both only available by right-clicking on files in the “Project Navigator” to reveal a contextual menu.
- [Download Xcode 9 framework project with full Swift 4 source from GitHub.]
- [Download Xcode 9 framework CONSUMER project with full Swift 4 source from GitHub.]
Let’s talk about Swift 4 frameworks, one method for packaging, reusing, and sharing code. We’ll build our own framework and then include it in our own app. We could’ve talked about static libraries, but frameworks offer more advanced features — and will let us expand on code maintainability options in future discussions. (If you want to have that static versus dynamic library discussion, read this excellent article, but we won’t be debating the topic herein.) From Apple (my emphasis added):
Suppose your supervisor or customer gives you a new project to work on: “I want you to start helping out on my iOS project, ‘Blocks-in-Objective-C.’ Please get a copy of the code, make these changes, test, and then check your new code into the repo. By the way, we’re using Git for source control.” Have you used Git before? Do you know it well? (Does anyone truly understand Git?) Today, I’ll show you how to accomplish that task just assigned by your supervisor or customer.
Since this is an iOS blog, I’m assuming you’ve installed Xcode and therefore Git is installed on your Mac. (If you need to install Git, click here.)
- [Download Xcode 8.2.1 project with full Swift 3 source from GitHub.]
- [Download Xcode 8.2.1 playground with full Swift 3 source from GitHub.]
How would you enable or disable multiple user interface controls using one IBOutlet and one IBAction? For example, you might need to disable a UITextBox and UISegmentedControl because a user’s login has expired. Perhaps a user hasn’t filled in some required fields on a form, so you want to disable several buttons. Watch the following video to see how I built a Swift 3 app to use a UISwitch to enable or disable four controls all at one time — and I demonstrated the object-oriented programming (OOP) principle of polymorphism:
Today, we’ll cover the topic of storing a user’s “default settings” inside your app — not forcing the user to go to a Settings bundle. The key to doing this is to save the user’s preferences to a persistent store whenever the user changes those preferences (or at least when the app goes into the background, but definitely before the app is terminated). But saving/writing those preferences is not enough. You must also read those preferences from the persistent store every time the app opens so that the user will always see their default settings. User settings/preferences must be synchronized with the persistent store.
I’m talking about saving simple pieces of data, like a user’s preferences for the background color of views, preferred language (i.e., English, Hindi, Portuguese, Spanish), preferred measuring units (metric or English), etc. Apple’s Human Interface Guidelines don’t explicitly forbid in-app settings. In fact, they explicitly permit them:
Note: Apps are not required to use a Settings bundle to manage all preferences. For preferences that the user is likely to change frequently, the app can display its own custom interface for managing those preferences.
Today’s tutorial covers transitions — segues — from one source storyboard scene to another destination scene, and unwind segues leading back from destination to source… I created a project to help you follow along with this tutorial, written in Swift 3, against the iOS 10 SDK, and using the Xcode 8.2.1 IDE. Please download the project. The app produced by the project is shown in action in the following video. Please watch before continuing on:
Segues don’t exist in a vacuum. I’ve introduced a UINavigationController into the mix. Of course, you’ll see a few UIViewControllers. I’ve also used a UITableView and managed its complexity by breaking it into logical pieces by using Swift “extensions.” As you proceed, you’ll have to grasp concepts like Auto Layout and managing a table view’s data source.
I’m going to show you how you can create IBOutlets, find your existing ones, and delete them. There will be times when you need to delete outlets, for example, if you connected the wrong component, have to change your design, misspelled an outlet, etc. You can’t do iOS without doing IBOutlets. An outlet is a connection you must create to allow your user interface (UI) to communicate with your code. For example, if you have a UIView on a storyboard scene, like a UIViewController, you may want to change that view’s background color during app execution. You may also need the bounds or frame of the view. If you have a UIButton, you may want to dynamically enable or disable it depending on some runtime condition. Say you have two UITextFields, “username” and “password,” and a UIButton containing the text “Login.” With IBOutlets, you could write your code so that the login button’s isEnabled property becomes true only when the username and password fields are filled with data. You would also want the text contained in the username and password fields once the user taps “Login.” IBOutlets form a connection between UI components like UILabel, UITextField, and UIView and their backing view controller that manages their behavior and presentation.
Let’s talk about source/version control, why it’s so important, and how you can easily put all your iOS code under source/version control management (SCM). I’m going to show you the manual steps involved in putting your code into a Git SCM “repository” (repo) so you fully understand how source/version control works. Jump straight to the tutorial if you’re already familiar with the concept of source control. I can’t explain everything about SCM in one blog post, but I’ll get you started and provide many online resources for you to reference. Why am I using Git? Like it or not, Git has become the de facto standard in SCM systems, mainly because it “is a free and open source [and] distributed version control system.” I don’t buy into the “Git is easy to learn” argument. I find Git to be overly complicated, cryptic, and generally requiring more steps to accomplish source control tasks than say centralized SCM systems like TFS or Subversion/SVN. Git does have some advantages over other SCM products, and it even becomes quite efficacious once you pay your dues learning how to use it properly.
NOTE: This article was first published on Jan 18, 2017. Since that time, I realized I missed one aspect of the project renaming process. Re-read the article or jump straight to the new content.
Sometimes you need to rename your Xcode projects. Not too long ago, this would’ve been problematic. Apple has built a project renaming feature into Xcode, but it’s not good enough for my needs. I’ll show you how I have to go above and beyond the standard functionality to get what I really want. Let’s walk through a concrete example, renaming an Xcode project we’ve been talking about in the post entitled “The UICollectionView is much more than a grid or matrix”.