Before we can start creating iOS applications, we need to set up the development environment. In this tutorial, I show you how to register as an Apple developer and install the development tools you need to get started.
1. Requirements & Prerequisites
The primary focus of this tutorial is getting started with Xcode. Xcode is an outstanding Integrated Development Environment (IDE) developed by Apple. The vast majority of OS X, iOS, watchOS, and tvOS developers rely on Xcode for building applications.
Xcode is only compatible with Apple's OS X operating system and I am therefore assuming that you have a Mac capable of running Xcode. I will be using Xcode 7.1 throughout this series.
This particular version of Xcode requires OS X 10.10.5 or higher. Even though it is possible to create iOS applications with an older version of Xcode, I recommend that you also use Xcode 7.1 to make sure that you don't run into unexpected issues along the way.
2. Join the Apple Developer Program
Apple recently changed its Apple Developer Program. Members of the Apple Developer Program can now create and publish applications for OS X, iOS, watchOS, and tvOS. The Apple Developer Program is still paid, though.
If you're just testing the waters and don't want to enroll just yet, then you can still follow along as long as you have an Apple ID. As of 2015, it is possible to develop applications for Apple's platforms with nothing more than an Apple ID. As long as you're thirteen years or older, anyone can create an Apple ID and get started with Xcode.
If you plan to submit your applications to the App Store, then you're required to enroll for the paid Apple Developer Program. The paid Apple Developer Program has three enrollment types, individual, organization, and enterprise. Apple also has an iOS Developer University Program for educational institutions.
At the time of writing, the individual and organization enrollment types cost $99 per year. The enterprise program is more expensive at $299 per year. The enterprise program is aimed at companies and organizations that intend to deploy in-house applications, applications that are not distributed through Apple's App Store.
Step 1: Create an Apple ID
Before you can start developing iOS applications, you need an Apple ID. You also need one to enroll in the Apple Developer Program. Chances are that you already have an Apple ID. You can create one for free on Apple's website. It only takes a few minutes to create one.
Step 2: Enroll in Apple's Developer Program
You can complete this series without enrolling in the Apple Developer Program, but keep in mind that you won't be able to submit applications to the App Store. If you enroll in the Apple Developer Program, you can develop for OS X, iOS, watchOS, and tvOS. Visit Apple's developer website for more information about the Apple Developer Program.
If you decided to enroll in Apple's Developer Program, then head over to the Apple Developer Program website and click Enroll in the top right. Sign in with your Apple ID and follow the steps. The process can take a few days to complete since Apple manually approves each application. For more information, visit Apple's developer support center.
3. Install Xcode
The name Xcode can be somewhat confusing at first. The name is often used to refer to the entire toolset for OS X, iOS, watchOS, and tvOS development, and that toolset includes the Xcode IDE, the simulator for running applications, and the actual OS X, iOS, watchOS, and tvOS SDKs (Software Development Kit). However, it's important to understand that the Xcode application itself is just an IDE and when I use the name Xcode I'm typically referring to just that.
You can download Xcode in one of two ways, through Apple's developer website or through the App Store on OS X. The advantage of the App Store on OS X is that updating Xcode is easier and faster.
The advantage of downloading Xcode through Apple's developer website is that you can download developer previews. If you like living on the edge, then you'll like working with the developer previews. Since you are new to iOS development, I suggest you download and install Xcode through the App Store so you can work with the most recent stable release.
Open the App Store, search for Xcode, and start the installation process. Xcode is several gigabytes in size so you may want to grab a cup of coffee or, even better, go for a walk.
4. Create Your First Application
You've barely touched your computer and we are already set up and ready to create iOS applications. If you're familiar with the process of setting up the Android SDK, then I'm sure you can appreciate this simplicity.
With Xcode installed, it is time to launch it for the first time. If all went well, you should see the Welcome to Xcode window, which contains a few useful links and helps you create a new application. To create your first iOS application, select Create a new Xcode project from the list of options.
What is an Xcode project? An Xcode project is a folder or package that contains all the necessary files and components to manage and build your application. You'll become more familiar with Xcode projects during this series.
Xcode makes it easy to create a new Xcode project by offering a handful of useful project templates. The Single View Application template is a good choice for your first application. Select it from the list of iOS > Application templates and click Next.
The next window lets you configure your Xcode project. Fill in the fields as shown in the screenshot below and click Next. In an upcoming article in this series, I will explain each of the configuration options in more detail. The focus of this article is getting your first application up and running in the simulator.
In the final step, Xcode asks you to specify a location for storing your new Xcode project. It doesn't really matter where you save the project as long as you can find it later. You'll also notice that Xcode offers the option to create a local Git repository for your project. I highly recommend that you use source control for any type of development. Git is an excellent choice and it is the most popular SCM (Source Control Management) system in the OS X and iOS community.
It's important to get familiar with source control management if this is new to you. Source control is indispensable in software development for various reasons. To begin using Git, you can visit Git's website or read its Wikipedia entry. There's also an excellent book by Scott Chacon that discusses Git in more detail.
In the rest of this series on iOS development, I won't bother you with source control. Even though source control is important, I don't want to overcomplicate this series by adding an extra layer of complexity.
5. Build & Run
You have successfully set up your first Xcode project. Believe it or not, running your application in the simulator is only one click away. There's a large play button on the far left of the Xcode toolbar.
Before you run your application, make sure that the active scheme is set to iPhone 6 or one of the other iOS Simulators. We will cover schemes in more detail later on in the series. Take a look at the next screenshot to make sure you're on the same page.
Are you ready to build and run your very first iOS application? Click the play button in the top right to build your project and run your application in the simulator. Alternatively, you can press Command + R or select Run from Xcode's Product menu. If all went well, you should see the simulator running your application. Of course, your application doesn't do anything useful yet. We'll fix that later in this series.
6. Simulator
The simulator is a valuable tool in your arsenal. Building and running an iOS application in the simulator is faster than deploying an application to a physical device. There is one caveat, however. For various reasons, the simulator doesn't perfectly mimic an iOS device.
For example, the simulator doesn't have a camera or an accelerometer, its GPS capabilities are limited to a list of predefined locations and routes, and user interaction is limited to gestures that require one or two fingers. Also, keep in mind that the simulator draws power and resources from the machine it runs on. This means that the simulator isn't suitable for testing application performance.
The point is that you should always test an application on a physical device before submitting it to the App Store or distributing it to testers. Even if you only have one device to test with, it is critical to test your applications on a physical device instead of relying solely on the simulator.
In spite of its shortcomings, the simulator is a very capable tool. Select the simulator and take a look at its menu and the various options it provides. The simulator is perfectly suited for testing user interfaces on different form factors, mimicking simple gestures, simulating memory warnings, or taking screenshots for the App Store. You'll find it a very useful tool for iOS development.
7. Physical Devices
As of 2015, running an application on a physical device is possible for every Apple developer, even if you don't enroll in the paid Apple Developer Program. That said, running an application on a physical device involves a few extra steps. These steps include configuring your project and setting up the device you plan to test with. Because this is a fairly complex topic, especially if you are new to iOS development, I will thoroughly explain how to do this in a separate article in this series.
8. Third Party Development Tools
I would like to end this article by listing a handful of third party tools that make iOS development easier and more enjoyable. Note that these applications are by no means required for iOS development, but knowing that they exist may save you a lot of frustration in the future.
Dash: Dash is a superb documentation browser and code snippet manager that I use constantly during development. Dash is a great alternative for Xcode's built-in documentation browser. It supports dozens of languages and frameworks, which means that you can use it for almost any type of development.
Tower: Tower is one of the best OS X applications for working with Git. Git is a command line tool, but some people prefer to use a graphical user interface instead. If you are not a command line superhero, then you'll definitely appreciate what Tower has to offer. Another great alternative is SourceTree, developed by Atlassian.
TextExpander: TextExpander is a popular utility for managing text snippets linked to custom keyboard shortcuts. Many developers use it for development, but you can use it wherever you like. It also supports placeholders for even more customizability.
Fabric: Fabric, owned by Twitter, is a suite of tools for mobile development. It allows developers to distribute test builds, collect crash reports, and integrate analytics. There are a number of alternatives that you may want to look into, such as HockeyApp and Apple's own TestFlight platform.
Conclusion
I hope you agree that setting up the development environment for iOS development is easy. With Xcode installed, we can start exploring the iOS SDK. That will be the focus of the rest of this series.
If you have any questions or comments, you can leave them in the comments below or reach out to me on Twitter.
Provisioning an application for testing on a physical device or for App Store distribution can be a nightmare for beginners. Every iOS developer has to tackle this hurdle at some point, though. In this article, I give you a good understanding of how to provision an application for testing on a physical device.
This tutorial covers two scenarios:
deploying an application with a free Apple ID
deploying an application as a member of the Apple Developer Program
Introduction
In 2015, Apple revamped their developer offering. Two changes in particular are worth pointing out.
In the past, Apple had separate programs for OS X, iOS, and Safari development. This is no longer the case. With the release of watchOS and tvOS, Apple merged their existing developer programs into one program, the Apple Developer Program.
This means that you no longer need to enroll in multiple programs if you want to develop for OS X and iOS. If you enroll in the Apple Developer Program, you can develop for OS X, iOS, watchOS, tvOS, and Safari.
Another significant change relates to Apple's free developer offering. In the past, it was possible to create a free developer account. With such an account, however, you weren't able to deploy iOS applications to a physical device.
This restriction has now been lifted. Anyone with an Apple ID can start developing for Apple's platforms and can deploy applications to physical devices. This is very good news for anyone interested in developing for one of Apple's platforms.
If you plan to publish an application to one of Apple's App Stores, then you need to enroll in the Apple Developer Program. This is something we discussed in the previous article of this series.
1. Apple ID
Deploying an application to a physical device with an Apple ID is straightforward. But keep in mind that the types of applications you can deploy with a free Apple ID are limited to some extent. I recommend that you take a look at Apple's overview if you want to know more about what's possible and what isn't.
Let's see what steps are involved to run an iOS application on an iPhone or iPad with a free Apple ID. If you don't have an Apple ID, then I suggest you create one on Apple's website before continuing with this tutorial. It only takes a few minutes to create one.
Step 1: Register as a Developer
Visit Apple's developer website and click Member Center at the top. After signing in with your Apple ID, you are asked to agree to Apple's Developer Agreement. Read the agreement, check the checkbox if you agree, and click Submit. You are now a registered Apple developer.
Step 2: Create a Project
Fire up Xcode and create a project like we did in the previous tutorial. I've chosen for the Single View Application template and configured the project as shown below. Tell Xcode where you'd like to store the project's files and click Create.
Step 3: Add an Account
After creating the project, Xcode shows you the General tab of the project's only target. In the Identity section, Xcode warns us that we cannot run the application on a device. The warning at the bottom of the Identity section tells us that Xcode is unable to find a code signing identity and Team is set to None. You can easily fix this by signing in with your Apple ID.
Select Xcode from the menu bar and choose Preferences... to open Xcode's preferences window.
If you open the Accounts tab, you can see that no accounts are listed yet.
Click the plus button in the bottom left and choose Add Apple ID... from the list of options.
Enter your Apple ID and password in the dialog and click Add. If this doesn't work for you, then make sure you've first registered as an Apple developer as I showed you earlier. If adding your Apple ID is successful, then it should now show up in the list of accounts on the left.
Step 4: Update Team
Close the preferences window and head back to the General tab of the project's target. In the Identity section, set Team to the account you added a moment ago. Even though you've now specified a team, Xcode still shows you a warning.
Wait a second? Why don't we try clicking the Fix Issue button. There's a reason why it's there. Right? If you click the Fix Issue button, Xcode will take care of the nitty gritty details to make sure you can run your application on a physical device.
Step 5: Trust the Developer
If you try to run the application on your device, then you will still run into a problem. Do you also see the following dialog?
Xcode shows us a pretty cryptic error message and it took me a few minutes to figure out what was going on. If you look at your device, then you'll see that the application is installed. If you tap the icon to launch it, you'll find out what the problem is. The operating system tells us that the application is from an untrusted developer.
Fortunately, the operating system also gives us a hint. Open the Settings application and navigate to General > Profiles. Select the profile with your Apple ID and tap Trust "<Apple ID>". Choose Trust from the dialog that shows up to finish the process. You should now be able to run the application on your device.
Remember that you need to trust the developer again, if you delete every application from that particular developer.
2. Apple Developer Program
If you've chosen to enroll in the Apple Developer Program, then the steps you need to take to provision an application are different. The upside is that the restrictions imposed on a free developer account are absent for members of the Apple Developer Program. The first thing you need to do is create a development certificate.
Step 1: Create a Certificate Signing Request
A certificate is an electronic document that links your digital identity with other information, such as your name, email, and organization information. A development certificate consists of a secret private key and a shared public key. If you are familiar with SSL certificates for securing websites, then you probably already know what a certificate is and how it works.
Xcode uses the private key of the certificate to cryptographically sign your application binary. To obtain a development certificate, you first need to create a certificate signing request or CSR.
You can create a CSR using OS X's Keychain Access utility, which you can find in the Applications > Utilities folder. Open the Keychain Access menu, select Certificate Assistant and choose Request a Certificate From a Certificate Authority....
Fill out the form by entering your name and the email address with which you signed up for the Apple Developer Program. Leave the certificate authority email address (CA Email Address) blank and make sure to check Saved to disk to save the certificate signing request to your machine. Leave Let me specify key pair information unchecked.
Click Continue, specify a location to save the CSR, and click Save. Browse to the location you specified to make sure the CSR was generated. In Keychain Access, under the Keys category, you can see that the private and public keys have been added to your login keychain.
Step 2: Create a Development Certificate
Open a browser and navigate to Apple's developer website. Click Member Center at the top, sign in with your developer account, and choose Certificates, Identifiers & Profiles.
On the next page, select Certificates from the iOS Apps section.
Click the plus button in the top right to add a new certificate. From the list of options, choose iOS App Development. That's the type of certificate we're interested in. Click Continue at the bottom.
The next page outlines the steps to create a CSR. Since we already have a CSR you can click Continue at the bottom.
Upload the CSR and click Generate at the bottom.
That's it. Click the Download button to download the development certificate. After downloading the development certificate, double click it to install it in Keychain Access. Make sure to back the certificate up, because you don't want to lose it.
If Keychain Access prompts you to add the certificate to the login keychain, then you can safely click Add.
In Keychain Access, select My Certificates on the left and locate the certificate you added to make sure you've installed it correctly.
Step 3: Add a Device
You cannot run an iOS application on a random device. You need to specify which devices can run your iOS application by marking one or more iOS devices for development in the developer portal.
Navigate to the Certificates, Identifiers & Profiles section of the developer portal, select the Devices tab in the iOS Apps section, and click the plus button in the top right. To register a device, enter a name for the device and its UDID. The UDID is an identifier that uniquely identifies an iOS device. Note that the UDID is not the same as the device's serial number.
You can find the UDID of a device by connecting the device to your machine, launching Xcode, and choosing Devices from the Window menu. The forty character alphanumeric string next to Identifier is the device's UDID.
Step 4: Create an App ID
An App ID is an identifier that uniquely identifies an application on iOS. It's much like the device's UDID, which uniquely identifies a device. The App ID is used by the operating system for security reasons and it's an essential component of Apple's Push Notification and iCloud services, among others.
The App ID of an application consists of your application's bundle identifier prefixed with a unique ten character bundle seed ID generated by Apple. What is a bundle identifier? Think back to the first project you created in the previous tutorial. Even though I didn't cover the bundle identifier in detail, you implicitly specified a bundle identifier for your project by giving your application a name and specifying an organization identifier.
By default, the bundle identifier is your application's name prefixed with your project's organization identifier. You can change the bundle identifier to whatever you like. It's recommended to adopt the reverse domain name notation, for example, com.tutsplus.my-first-application. The complete App ID would then be xxxxxxxxxx.com.tutsplus.my-first-application.
To create a new App ID in the developer portal, navigate to the Certificates, Identifiers & Profiles section, click iOS Apps, and choose App IDs from the menu on the left. To create a new App ID, click the plus button in the top right.
Start by giving your App ID a descriptive name so you can find it later. Leave the App ID prefix field untouched. In the section App ID Suffix, enter your application's bundle identifier. Make sure you enter it in the section labeled Explicit App ID.
You can also opt for a Wildcard App ID and replace the application name in the bundle identifier with an asterisk, for example, com.tutsplus.*. This is useful if you intend to create a suite of applications that need to share keychain access or don't require keychain access at all. The asterisk or wildcard character needs to be the last component of the bundle identifier.
Step 5: Create a Provisioning Profile
With the development certificate and the App ID in place, it's time to create a provisioning profile for your application. Before we start, it might be useful to explain what a provisioning profile is, because this is something that confuses many new iOS developers.
Apple's documentation defines a provisioning profile as "a collection of assets that uniquely ties developers and devices to an authorized iOS Development Team and enables a device to be used for testing." In other words, a provisioning profile contains the information that the operating system needs to verify whether an application is permitted to run on a specific device. This implies that the provisioning profile needs to be installed on each device the application needs to run on.
Let's create a provisioning profile for your application. In the Certificates, Identifiers & Profiles section of the developer portal, select the Provisioning Profiles tab in the iOS Apps section. Click the plus button in the top right to create a new provisioning profile. Select iOS App Development in the Development section and click Continue.
In the next step, select the App ID you created a few minutes ago and click Continue.
Select the development certificate from the list of certificates to associate the new provisioning profile with the correct certificate. Click Continue.
You now need to select the devices you wish to link to the provisioning profile. Remember that only these devices will be able to run your application during development.
Give the provisioning profile a descriptive name so you can easily find it later. Click Generate and download the provisioning profile to your development machine. Double click the provisioning profile to add it to Xcode.
If you wish to add more devices to an already existing provisioning profile, then you can do so by editing the provisioning profile. All you need to do is download the new provisioning profile and install it on every device you wish to test with. In other words, you don't need to create a new provisioning profile if all you want to do is add or remove devices.
Step 6: Configure the Project
Before you can build and run your application on your device, you need to update the build settings of the target in your Xcode project.
Open the Xcode project you created in the previous tutorial and select the project from the Project Navigator on the left. Select My First Application in the Targets section and open Build Settings at the top.
Don't be overwhelmed by the numerous build settings. Scroll through the list and search for the Code Signing section. In this section, search for the Code Signing Identity subsection and set the Debug configuration to match iOS Developer. It's usually located under the Automatic heading.
Step 7: Build & Run
If you've followed the above steps, then you should now be able to build and run your application on your device. Before you run your application, make sure that you correctly set the active scheme and destination as shown below.
3. Add a Developer Account
With regards to application provisioning, Xcode can do some of the heavy lifting for you. For that to work, you need to add your developer account to Xcode. You can add your developer account by selecting Preferences... from the Xcode menu and opening the Accounts tab.
Click the plus button in the bottom left and choose Add Apple ID... from the list of options. Enter your credentials and click Add.
By adding your developer account to Xcode, it can communicate with the developer portal on your behalf. This makes some tasks a lot easier.
Conclusion
Creating and managing certificates, provisioning profiles, App IDs, and test devices can be a daunting task—and it often is for most developers. I hope that this article has given you a sturdy foundation.
Don't hesitate to read this article a few times to really understand how the different pieces fit together. It will make debugging issues related to provisioning much easier and I can guarantee you that you will run into such issues at some point in your iOS development career.
If you have any questions or comments, you can leave them in the comments below or reach out to me on Twitter.
Provisioning an application for testing on a physical device or for App Store distribution can be a nightmare for beginners. Every iOS developer has to tackle this hurdle at some point, though. In this article, I give you a good understanding of how to provision an application for testing on a physical device.
This tutorial covers two scenarios:
deploying an application with a free Apple ID
deploying an application as a member of the Apple Developer Program
Introduction
In 2015, Apple revamped their developer offering. Two changes in particular are worth pointing out.
In the past, Apple had separate programs for OS X, iOS, and Safari development. This is no longer the case. With the release of watchOS and tvOS, Apple merged their existing developer programs into one program, the Apple Developer Program.
This means that you no longer need to enroll in multiple programs if you want to develop for OS X and iOS. If you enroll in the Apple Developer Program, you can develop for OS X, iOS, watchOS, tvOS, and Safari.
Another significant change relates to Apple's free developer offering. In the past, it was possible to create a free developer account. With such an account, however, you weren't able to deploy iOS applications to a physical device.
This restriction has now been lifted. Anyone with an Apple ID can start developing for Apple's platforms and can deploy applications to physical devices. This is very good news for anyone interested in developing for one of Apple's platforms.
If you plan to publish an application to one of Apple's App Stores, then you need to enroll in the Apple Developer Program. This is something we discussed in the previous article of this series.
1. Apple ID
Deploying an application to a physical device with an Apple ID is straightforward. But keep in mind that the types of applications you can deploy with a free Apple ID are limited to some extent. I recommend that you take a look at Apple's overview if you want to know more about what's possible and what isn't.
Let's see what steps are involved to run an iOS application on an iPhone or iPad with a free Apple ID. If you don't have an Apple ID, then I suggest you create one on Apple's website before continuing with this tutorial. It only takes a few minutes to create one.
Step 1: Register as a Developer
Visit Apple's developer website and click Member Center at the top. After signing in with your Apple ID, you are asked to agree to Apple's Developer Agreement. Read the agreement, check the checkbox if you agree, and click Submit. You are now a registered Apple developer.
Step 2: Create a Project
Fire up Xcode and create a project like we did in the previous tutorial. I've chosen for the Single View Application template and configured the project as shown below. Tell Xcode where you'd like to store the project's files and click Create.
Step 3: Add an Account
After creating the project, Xcode shows you the General tab of the project's only target. In the Identity section, Xcode warns us that we cannot run the application on a device. The warning at the bottom of the Identity section tells us that Xcode is unable to find a code signing identity and Team is set to None. You can easily fix this by signing in with your Apple ID.
Select Xcode from the menu bar and choose Preferences... to open Xcode's preferences window.
If you open the Accounts tab, you can see that no accounts are listed yet.
Click the plus button in the bottom left and choose Add Apple ID... from the list of options.
Enter your Apple ID and password in the dialog and click Add. If this doesn't work for you, then make sure you've first registered as an Apple developer as I showed you earlier. If adding your Apple ID is successful, then it should now show up in the list of accounts on the left.
Step 4: Update Team
Close the preferences window and head back to the General tab of the project's target. In the Identity section, set Team to the account you added a moment ago. Even though you've now specified a team, Xcode still shows you a warning.
Wait a second? Why don't we try clicking the Fix Issue button. There's a reason why it's there. Right? If you click the Fix Issue button, Xcode will take care of the nitty gritty details to make sure you can run your application on a physical device.
Step 5: Trust the Developer
If you try to run the application on your device, then you will still run into a problem. Do you also see the following dialog?
Xcode shows us a pretty cryptic error message and it took me a few minutes to figure out what was going on. If you look at your device, then you'll see that the application is installed. If you tap the icon to launch it, you'll find out what the problem is. The operating system tells us that the application is from an untrusted developer.
Fortunately, the operating system also gives us a hint. Open the Settings application and navigate to General > Profiles. Select the profile with your Apple ID and tap Trust "<Apple ID>". Choose Trust from the dialog that shows up to finish the process. You should now be able to run the application on your device.
Remember that you need to trust the developer again, if you delete every application from that particular developer.
2. Apple Developer Program
If you've chosen to enroll in the Apple Developer Program, then the steps you need to take to provision an application are different. The upside is that the restrictions imposed on a free developer account are absent for members of the Apple Developer Program. The first thing you need to do is create a development certificate.
Step 1: Create a Certificate Signing Request
A certificate is an electronic document that links your digital identity with other information, such as your name, email, and organization information. A development certificate consists of a secret private key and a shared public key. If you are familiar with SSL certificates for securing websites, then you probably already know what a certificate is and how it works.
Xcode uses the private key of the certificate to cryptographically sign your application binary. To obtain a development certificate, you first need to create a certificate signing request or CSR.
You can create a CSR using OS X's Keychain Access utility, which you can find in the Applications > Utilities folder. Open the Keychain Access menu, select Certificate Assistant and choose Request a Certificate From a Certificate Authority....
Fill out the form by entering your name and the email address with which you signed up for the Apple Developer Program. Leave the certificate authority email address (CA Email Address) blank and make sure to check Saved to disk to save the certificate signing request to your machine. Leave Let me specify key pair information unchecked.
Click Continue, specify a location to save the CSR, and click Save. Browse to the location you specified to make sure the CSR was generated. In Keychain Access, under the Keys category, you can see that the private and public keys have been added to your login keychain.
Step 2: Create a Development Certificate
Open a browser and navigate to Apple's developer website. Click Member Center at the top, sign in with your developer account, and choose Certificates, Identifiers & Profiles.
On the next page, select Certificates from the iOS Apps section.
Click the plus button in the top right to add a new certificate. From the list of options, choose iOS App Development. That's the type of certificate we're interested in. Click Continue at the bottom.
The next page outlines the steps to create a CSR. Since we already have a CSR you can click Continue at the bottom.
Upload the CSR and click Generate at the bottom.
That's it. Click the Download button to download the development certificate. After downloading the development certificate, double click it to install it in Keychain Access. Make sure to back the certificate up, because you don't want to lose it.
If Keychain Access prompts you to add the certificate to the login keychain, then you can safely click Add.
In Keychain Access, select My Certificates on the left and locate the certificate you added to make sure you've installed it correctly.
Step 3: Add a Device
You cannot run an iOS application on a random device. You need to specify which devices can run your iOS application by marking one or more iOS devices for development in the developer portal.
Navigate to the Certificates, Identifiers & Profiles section of the developer portal, select the Devices tab in the iOS Apps section, and click the plus button in the top right. To register a device, enter a name for the device and its UDID. The UDID is an identifier that uniquely identifies an iOS device. Note that the UDID is not the same as the device's serial number.
You can find the UDID of a device by connecting the device to your machine, launching Xcode, and choosing Devices from the Window menu. The forty character alphanumeric string next to Identifier is the device's UDID.
Step 4: Create an App ID
An App ID is an identifier that uniquely identifies an application on iOS. It's much like the device's UDID, which uniquely identifies a device. The App ID is used by the operating system for security reasons and it's an essential component of Apple's Push Notification and iCloud services, among others.
The App ID of an application consists of your application's bundle identifier prefixed with a unique ten character bundle seed ID generated by Apple. What is a bundle identifier? Think back to the first project you created in the previous tutorial. Even though I didn't cover the bundle identifier in detail, you implicitly specified a bundle identifier for your project by giving your application a name and specifying an organization identifier.
By default, the bundle identifier is your application's name prefixed with your project's organization identifier. You can change the bundle identifier to whatever you like. It's recommended to adopt the reverse domain name notation, for example, com.tutsplus.my-first-application. The complete App ID would then be xxxxxxxxxx.com.tutsplus.my-first-application.
To create a new App ID in the developer portal, navigate to the Certificates, Identifiers & Profiles section, click iOS Apps, and choose App IDs from the menu on the left. To create a new App ID, click the plus button in the top right.
Start by giving your App ID a descriptive name so you can find it later. Leave the App ID prefix field untouched. In the section App ID Suffix, enter your application's bundle identifier. Make sure you enter it in the section labeled Explicit App ID.
You can also opt for a Wildcard App ID and replace the application name in the bundle identifier with an asterisk, for example, com.tutsplus.*. This is useful if you intend to create a suite of applications that need to share keychain access or don't require keychain access at all. The asterisk or wildcard character needs to be the last component of the bundle identifier.
Step 5: Create a Provisioning Profile
With the development certificate and the App ID in place, it's time to create a provisioning profile for your application. Before we start, it might be useful to explain what a provisioning profile is, because this is something that confuses many new iOS developers.
Apple's documentation defines a provisioning profile as "a collection of assets that uniquely ties developers and devices to an authorized iOS Development Team and enables a device to be used for testing." In other words, a provisioning profile contains the information that the operating system needs to verify whether an application is permitted to run on a specific device. This implies that the provisioning profile needs to be installed on each device the application needs to run on.
Let's create a provisioning profile for your application. In the Certificates, Identifiers & Profiles section of the developer portal, select the Provisioning Profiles tab in the iOS Apps section. Click the plus button in the top right to create a new provisioning profile. Select iOS App Development in the Development section and click Continue.
In the next step, select the App ID you created a few minutes ago and click Continue.
Select the development certificate from the list of certificates to associate the new provisioning profile with the correct certificate. Click Continue.
You now need to select the devices you wish to link to the provisioning profile. Remember that only these devices will be able to run your application during development.
Give the provisioning profile a descriptive name so you can easily find it later. Click Generate and download the provisioning profile to your development machine. Double click the provisioning profile to add it to Xcode.
If you wish to add more devices to an already existing provisioning profile, then you can do so by editing the provisioning profile. All you need to do is download the new provisioning profile and install it on every device you wish to test with. In other words, you don't need to create a new provisioning profile if all you want to do is add or remove devices.
Step 6: Configure the Project
Before you can build and run your application on your device, you need to update the build settings of the target in your Xcode project.
Open the Xcode project you created in the previous tutorial and select the project from the Project Navigator on the left. Select My First Application in the Targets section and open Build Settings at the top.
Don't be overwhelmed by the numerous build settings. Scroll through the list and search for the Code Signing section. In this section, search for the Code Signing Identity subsection and set the Debug configuration to match iOS Developer. It's usually located under the Automatic heading.
Step 7: Build & Run
If you've followed the above steps, then you should now be able to build and run your application on your device. Before you run your application, make sure that you correctly set the active scheme and destination as shown below.
3. Add a Developer Account
With regards to application provisioning, Xcode can do some of the heavy lifting for you. For that to work, you need to add your developer account to Xcode. You can add your developer account by selecting Preferences... from the Xcode menu and opening the Accounts tab.
Click the plus button in the bottom left and choose Add Apple ID... from the list of options. Enter your credentials and click Add.
By adding your developer account to Xcode, it can communicate with the developer portal on your behalf. This makes some tasks a lot easier.
Conclusion
Creating and managing certificates, provisioning profiles, App IDs, and test devices can be a daunting task—and it often is for most developers. I hope that this article has given you a sturdy foundation.
Don't hesitate to read this article a few times to really understand how the different pieces fit together. It will make debugging issues related to provisioning much easier and I can guarantee you that you will run into such issues at some point in your iOS development career.
If you have any questions or comments, you can leave them in the comments below or reach out to me on Twitter.
Do you want to learn more about creating map applications for Android? How about Python machine learning? Or perhaps you'd like a refresher on the essentials of GitHub? Our latest batch of eBooks covers all these subjects and more.
What You’ll Learn
In the past couple of months we’ve made 16 new eBooks available for Envato Tuts+ subscribers to download. Here’s a selection of those eBooks, and a summary of what you can learn from them.
1. Python Machine Learning
Machine learning and predictive analytics are transforming the way businesses and other organizations operate. Python Machine Learning gives you access to the world of predictive analytics and demonstrates why Python is one of the world’s leading data science languages. If you want to ask better questions of data, or need to improve and extend the capabilities of your machine learning systems, this practical data science book is invaluable.
2. Mastering Social Media Mining With R
Mastering Social Media Mining With R will teach you how to solve powerful business cases by applying machine learning techniques on social media data. You will learn about important and recent developments in the field of social media, along with a few advanced topics such as Open Authorization (OAuth). Through practical examples, you will access data from R using APIs of various social media sites such as Twitter, Facebook, Instagram, GitHub, Foursquare, LinkedIn, Blogger, and other networks.
With this handy guide, you will be ready to embark on your journey as an independent social media analyst.
3. Yii2 by Example
Yii is a high-performance PHP framework best for developing Web 2.0 applications. It provides fast, secure, and professional features to create robust projects. Yii2 by Example contains a series of practical project examples for developers starting from scratch. Each section contains the most relevant theories for every topic as you walk through developing each project, focusing on key aspects that commonly confuse users.
4. Mastering Python Scientific Computing
In today's world, along with theoretical and experimental work, scientific computing has become an important part of scientific disciplines. Python is among the top choices for developing scientific workflow, and this book helps existing Python developers to master this domain using Python.
The main things to learn in the book are the concept of scientific workflow, managing scientific workflow data, and performing computation on this data using Python. The book discusses NumPy, SciPy, SymPy, matplotlib, Pandas and IPython with several example programs.
5. GitHub Essentials
Whether you are an experienced developer or a novice, learning to work with Version Control Systems is a must in the software development world. Git is the most popular tool for that purpose, and GitHub was built around it leveraging its powers by bringing it to the web. GitHub Essentials will take you through everything from creating a repository to writing documentation, managing teams, configuring settings, and more.
6. WordPress 4.0 Site Blueprints: Second Edition
This book will take you through the process of creating ten popular kinds of site using WordPress with free plugins and themes. Without writing too much code, you’ll be able to create a store, a video streaming site, a team communications site, a jobs board, and more. This book is a one-stop solution to resolve all your worries about creating a website that will give the best experience to your users.
7. Learning Android Google Maps
Learning Android Google Maps helps you to overcome the most common problems faced by users and helps you create a successful map application without any hassle. It starts with a brief description of how to set up an environment and obtain an API key to create your map application. Then you'll learn about adding markers, overlays, and information windows to the map in detail. You will then dive deep into customizing various types of maps and working with location data and Google Street view.
By the end of this book, you will be able to create succinct map applications in Android using Google Maps efficiently.
8. PhoneGap Essentials
PhoneGap is an open-source framework that allows you to quickly build cross-platform mobile apps using HTML5, JavaScript, and CSS.
In PhoneGap Essentials, you’ll develop an app that uses various device capabilities through different plugins, learn how to build an app in the cloud with PhoneGap’s Build service, and much more.
9. Amazon S3 Cookbook
Amazon S3 is one of the most famous cloud object storage services, which is highly scalable, low-latency, and economical. Amazon S3 Cookbook teaches you to successfully implement pro-level practices, techniques, and solutions in Amazon S3.
Start Learning With a Yearly Subscription
Subscribe to Envato Tuts+ for access to our library of hundreds of eBooks. With a Yearly subscription, you can download up to five eBooks per month, while the Yearly Pro subscription gives you unlimited access.
Even though we've already learned quite a bit in this series on iOS development, I'm sure you are eager to start building iOS applications that do something cool or useful. In this tutorial, your wish is granted. Using Xcode, you are going to create an iOS project from scratch, modify the project's source code, and run your application in the simulator or on a physical device.
Introducing Colorific
Colorific is the name of the application that you are about to build. The idea behind Colorific is simple, every time the user touches the screen of the device, the color of the screen changes. Even though the concept is basic, Colorific is perfect for getting started and exploring the ins and outs of iOS development.
1. Create a New Xcode Project
As we saw earlier in this series, every iOS application goes through life as an Xcode project. What is an Xcode project? An Xcode project is a container or repository that contains the files, assets, and information that are required to build one or more products.
Note that this isn't limited to a project's source code and assets, such as images and other media. A project also keeps track of the connections between its various elements and it knows how to build the final products from its elements.
Fire up Xcode and create a new Xcode project by choosing New > Project... from the File menu. You can accomplish the same by pressing Shift + Command + N.
If Xcode's welcome window pops up when you launch Xcode, then I suggest you close it so you learn how to create a new project using Xcode's menu.
2. Choose an Application Template
Getting started with a new application or project is easy in Xcode thanks to the application templates that are included. For the application that we're about to create, we need the Single View Application template. Feel free to take a look at the other application templates, but make sure to choose the Single View Application template for Colorific.
3. Configure the Project
After selecting the Single View Application template and clicking the Next button, Xcode presents you with a list of options to configure your new project. Let's take a look at the various options.
Product Name: The product name will be the name of your application. I have named my application Colorific, but feel free to name your application whatever you like.
Organization Name: The organization name can be your own name or the name of your company. Xcode uses the organization name for various purposes, such as adding a copyright notice to each source file.
Organization Identifier: The organization identifier is a unique string that Xcode uses (together with the product name) to create the application's bundle identifier. Apple recommends adopting the reverse domain name notation to avoiding naming collisions. Note that the domain that you use has no ties to DNS (Domain Name System). For example, my company is named Code Foundry BVBA and is located in Belgium, which means that my company identifier is be.codefoundry. However, I could just as well use be.code-foundry or com.codefoundry. For the purpose of this tutorial, I've set the company identifier to com.tutsplus.
Bundle Identifier: Even though you cannot specify the bundle identifier when creating a new Xcode project, you can change it once you've created your project. By default, the bundle identifier is the combination of the organization identifier and the product name. Keep in mind that spaces in the product name are replaced with dashes in the bundle identifier, because the bundle identifier cannot contain whitespace.
Language: The current version of Xcode supports both Objective-C and Swift. This series is focused on iOS development using Swift 2.1 so that's the option I've taken for this project.
Devices: In the current version of Xcode (7 at the time of writing), the devices drop down menu contains three options, Universal, iPhone, and iPad. This configuration option tells Xcode which devices your project targets. By selecting the first option, Universal, your project targets both the iPad and iPhone device families. The iPod Touch is a member of the iPhone device family as you might have guessed.
Use Core Data: If you check this checkbox, Xcode will create a few additional files and add some boilerplate code to help you get started with Core Data, Apple's persistence framework for OS X and iOS. Because Core Data isn't a topic for beginners, we're going to leave this checkbox unchecked.
Include Unit Tests: Testing is an important aspect of software development. Xcode has built-in support for unit testing. To keep things simple, however, we're going to ignore this option for now.
Include UI Tests: Xcode 7 is the first version of Apple's IDE that has built-in support for user interface testing. This is a big deal for OS X and iOS developers. User interface testing is beyond the scope of this series, though.
You should now have a good grasp of the different configuration options when setting up a new Xcode project. For this project, I recommend that you use the options as shown in the above screenshot. Note that most options can easily be changed after you've created your project. Click Next when you're finished configuring your project.
4. Save the Project
In the next step, Xcode asks you where you want to save your new project. You may have noticed the little checkbox at the bottom of the window labeled Create Git repository on My Mac. The gray text below the checkbox reads Xcode will place your project under version control.
As I mentioned earlier in this series, source control is indispensable in software development. This series will not cover this topic in detail, but if you're serious about software development, then I highly recommend reading up on source control.
Git is the most popular SCM (Source Code Management) system in the Cocoa community. However, it's perfectly possible to use a different SCM system, such as SVN or Mercurial.
Tell Xcode where you want to save your project, check the checkbox to authorize Xcode to create a Git repository for the project, and click Create at the bottom of the dialog.
5. Exploring Xcode's User Interface
Before we move on, I want to take a few minutes to explore Xcode's user interface. There are four distinct areas:
a toolbar at the top
a sidebar on the left
a main view in the center
a sidebar at the right
Toolbar
The toolbar at the top contains the buttons and menus that you'll find yourself using most often. As we saw earlier in this series, the buttons to run and stop an application also live in the toolbar.
The display in the center of the toolbar is similar to the display you find in iTunes. It displays information about your project's state or what Xcode is currently doing in the background. It will tell you, for example, when a build succeeds or fails.
The two segmented controls on the right of the toolbar can be used to customize Xcode's user interface. Play around with the various controls to find out how each of them changes the user interface of Xcode.
Navigator
The main purpose of the left sidebar is for navigation and it's often referred to as Xcode's navigator.
The navigator has different tabs with the Project Navigator at the far left. The selection in the left sidebar determines what is shown in Xcode's main view, the workspace.
Main View or Workspace
The main view or workspace is the area where you'll spend most of your time. It's Xcode's workhorse and displays whatever's selected in the navigator.
Inspector
While the left sidebar controls what's being displayed in Xcode's main view, the contents of the right sidebar reflect what's being displayed or selected in the main view.
The right sidebar, also known as the inspector, adapts itself to whatever the user selects in the main view.
6. Exploring the Project
It's time to take a look at the project itself. The project's contents are displayed in the Project Navigator, the first tab in the left sidebar. Select the first item in the Project Navigator to see the project details in the main view.
The main view is composed of two sections, a sidebar on the left and a detail view on the right. In the sidebar, you see two items, your project with one item and targets with one item.
It's good to know early on what the difference is between a project and a target. Remember that a project is a repository for the files, assets, and data that are required to build one or more products. A target refers to one of those products. A target contains the necessary instructions to build a product with the project's resources. This means that a project can contain multiple targets to build multiple products. As you can see, an Xcode project is more than just a folder with a bunch of files in it.
7. Build & Run: Take 1
Before we start modifying the source code of the project, it may be interesting to build and run your new project to see what the application template has given us for free. Click the Run button in the top left and make sure that the active scheme is configured to run the application in the simulator by selecting iPhone 6 or another simulator for iPhone.
If all went well, the simulator should launch your application and display an empty, white view with the familiar status bar at the top.
8. Modify the User Interface
Let's get our hands dirty and modify the application's user interface. Open the Project Navigator and select the file named Main.storyboard. A file with a .storyboard extension is a user interface file. In this file, we create the user interface of the application.
The storyboard contains one item, a view controller with the white view you saw in the simulator a few moments ago. The workspace is composed of a sidebar showing the object representation of the scenes of the storyboard. The largest part of the workspace contains the scenes or the user interface of the application.
Select the object named View in the View Controller Scene in the left sidebar and see how the workspace and the right sidebar update their contents. A bunch of tabs appear at the top of the right sidebar. Each tab contains a collection of attributes related to the object named View.
The lower half of the right sidebar contains a section with four tabs. The third tab is represented by an image of a three-dimensional box. This box is how objects are commonly displayed in Xcode.
Select the tab with the box icon and scroll through the list that appears. The list is referred to as the Object Library and contains various user interface elements, such as buttons, sliders, and switches.
At the start of this tutorial, I told you we were going to create a functional application. The user should be able to touch the screen to change its color.
There are multiple approaches to detect touches in an iOS application. One solution is to use a button. In the Object Library, find the item named Button and drag it from the Object Library to the white view in Xcode's workspace.
The user should be able to touch any part of the screen, which means the button should cover the entire screen. Have you noticed the six, tiny squares at the button's edges? By moving the tiny squares, you can modify the button's dimensions. Adjust the size of the button to make it cover the entire screen. Don't worry about the status bar at the top of the screen.
The view behind the button is the view that will change color when the user touches the screen. At the moment, the button is blocking the view from the user's view so we need to modify the button's attributes.
You may have noticed that the button has been added to the list of objects in the left sidebar, below the object named View. Select the button from the list of objects and select the Attributes Inspector in the right sidebar—the fourth tab from the left. We only need to make two adjustments.
Start by changing the type of the button from System to Custom. This will make the button transparent.
The second change we need to make is instructing the user what to do by changing the button's title. The text field next to the label Title currently reads Button. Change this to Tap to Change Color and set the Text Color to black to make it more readable.
9. Add an Action to the View Controller
If you're familiar with the MVC (Model-View-Controller) pattern, then you have a head start learning iOS development. The MVC pattern is a pattern found in many languages and frameworks, such as Laravel and Ruby on Rails.
The view in our user interface falls in the V category of the MVC pattern. A view is controlled by a controller. Take a look at the file names in the Project Navigator on the left. ViewController.swift represents a view controller that controls the view in our user interface.
What does a view controller do? A view controller can do whatever you want, but it's in the first place responsible for handling everything that happens in the view that it manages. This includes, for example, touches from the user. If the user taps the button in the view, it's the view controller's responsibility to handle the touch event.
How do we handle a touch event? In the case of our button, we add an action to the view controller. An action is a fancy name for a method. What is a method? A method is a Swift function. Wait. What? Don't worry about the terminology too much at this point. The next two posts will cover the Swift programming language in more detail. What you need to remember is that a method is like a method in Ruby and PHP, or a function in JavaScript.
If you invoke a method of a view controller, it does something in response. In other words, if a user taps the button and we connect a method to that touch event, the view controller will do something in response to the touch event.
To add an action to the view controller that manages the view in the application's user interface, we need to make some changes to the file named ViewController.swift. We only need to add a few lines of code to ViewController.swift. Take a look at how I modified the file's contents.
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func changeColor(sender: UIButton) {
}
}
Even though we won't focus on the syntax in this tutorial, it's fairly easy to understand what's going on. The name of the action or method is changeColor(_:) and it has one parameter, sender. The type of the parameter is UIButton. What is UIButton? Patience grasshopper.
10. Implement the Action
We've added an action to the view controller, but the action doesn't do much. The action doesn't have a body or implementation yet. To implement the changeColor(_:) action, we need to add one or more statements between the curly braces as shown in the code snippet below. I'm not going to explain each line of code in detail, but I'll give you the gist of what's happening.
@IBAction func changeColor(sender: UIButton) {
// Generate Random Numbers
let r = CGFloat(arc4random() % 255)
let g = CGFloat(arc4random() % 255)
let b = CGFloat(arc4random() % 255)
// Create Color
let color = UIColor(red: (r/255.0), green: (g/255.0), blue: (b/255.0), alpha: 1.0)
// Update View
view.backgroundColor = color
}
As you may know, it's possible to break a color down into the three primary colors, red, green, and blue. In our action, we generate three random numbers between 0 and 255, and use these numbers to create a random color.
The method we use to create the color is very descriptive, init(red:green:blue:alpha:). With the last line of our action, we set the background color of the view in our user interface to this new, randomly generated color.
Comments are important when writing code. Did you spot the comments I added to the implementation of changeColor(_:)? Single line comments start with two forward slashes , //, whereas multiline comments start with /* and end with */.
11. Connect the Action
The method is implemented, but nothing spectacular will happen if we build and run the application. Give it a try if you don't believe me.
What's missing is a connection between the button and the view controller's action. How should the view controller know that the changeColor(_:) action needs to be triggered when the button is tapped?
Making this connection is simple. Open the storyboard by selecting Main.storyboard and select the View Controller object in the View Controller Scene.
With the View Controller object selected, open the Connections Inspector in the right sidebar—the first tab from the right. If you've followed the steps correctly, you should see the action we created in the Received Actions section.
You should see an empty circle on the right of the changeColor(_:) action. Click and drag from the circle to the button in the view controller's view.
A menu pops up when you release the mouse. The menu contains a list of touch event types. The touch event that we're interested in is named Touch Up Inside. This event is triggered when a user touches the button and lifts her finger. This is the most common behavior for buttons.
After connecting the button and the action, you should see that the right sidebar reflects the connection you just made. Great. You've successfully completed your first real application.
12. Build & Run: Take 2
Build and run your application in the simulator and start tapping the simulator's screen. Every time you tap the screen, its color should change to a new, random color. How cool is that?
Conclusion
We've covered a lot of ground in this tutorial. Even though this post was quite lengthy, we didn't actually do very much. If you know the theory, you can create Colorific in less than five minutes. If you ran into a problem during this tutorial, then make sure to download the source files from GitHub.
In the next two installments, we will explore the basics of the Swift programming language. This will prepare you for the interesting stuff in the rest of the series.
If you have any questions or comments, you can leave them in the comments below or reach out to me on Twitter.
Even though we've already learned quite a bit in this series on iOS development, I'm sure you are eager to start building iOS applications that do something cool or useful. In this tutorial, your wish is granted. Using Xcode, you are going to create an iOS project from scratch, modify the project's source code, and run your application in the simulator or on a physical device.
Introducing Colorific
Colorific is the name of the application that you are about to build. The idea behind Colorific is simple, every time the user touches the screen of the device, the color of the screen changes. Even though the concept is basic, Colorific is perfect for getting started and exploring the ins and outs of iOS development.
1. Create a New Xcode Project
As we saw earlier in this series, every iOS application goes through life as an Xcode project. What is an Xcode project? An Xcode project is a container or repository that contains the files, assets, and information that are required to build one or more products.
Note that this isn't limited to a project's source code and assets, such as images and other media. A project also keeps track of the connections between its various elements and it knows how to build the final products from its elements.
Fire up Xcode and create a new Xcode project by choosing New > Project... from the File menu. You can accomplish the same by pressing Shift + Command + N.
If Xcode's welcome window pops up when you launch Xcode, then I suggest you close it so you learn how to create a new project using Xcode's menu.
2. Choose an Application Template
Getting started with a new application or project is easy in Xcode thanks to the application templates that are included. For the application that we're about to create, we need the Single View Application template. Feel free to take a look at the other application templates, but make sure to choose the Single View Application template for Colorific.
3. Configure the Project
After selecting the Single View Application template and clicking the Next button, Xcode presents you with a list of options to configure your new project. Let's take a look at the various options.
Product Name: The product name will be the name of your application. I have named my application Colorific, but feel free to name your application whatever you like.
Organization Name: The organization name can be your own name or the name of your company. Xcode uses the organization name for various purposes, such as adding a copyright notice to each source file.
Organization Identifier: The organization identifier is a unique string that Xcode uses (together with the product name) to create the application's bundle identifier. Apple recommends adopting the reverse domain name notation to avoiding naming collisions. Note that the domain that you use has no ties to DNS (Domain Name System). For example, my company is named Code Foundry BVBA and is located in Belgium, which means that my company identifier is be.codefoundry. However, I could just as well use be.code-foundry or com.codefoundry. For the purpose of this tutorial, I've set the company identifier to com.tutsplus.
Bundle Identifier: Even though you cannot specify the bundle identifier when creating a new Xcode project, you can change it once you've created your project. By default, the bundle identifier is the combination of the organization identifier and the product name. Keep in mind that spaces in the product name are replaced with dashes in the bundle identifier, because the bundle identifier cannot contain whitespace.
Language: The current version of Xcode supports both Objective-C and Swift. This series is focused on iOS development using Swift 2.1 so that's the option I've taken for this project.
Devices: In the current version of Xcode (7 at the time of writing), the devices drop down menu contains three options, Universal, iPhone, and iPad. This configuration option tells Xcode which devices your project targets. By selecting the first option, Universal, your project targets both the iPad and iPhone device families. The iPod Touch is a member of the iPhone device family as you might have guessed.
Use Core Data: If you check this checkbox, Xcode will create a few additional files and add some boilerplate code to help you get started with Core Data, Apple's persistence framework for OS X and iOS. Because Core Data isn't a topic for beginners, we're going to leave this checkbox unchecked.
Include Unit Tests: Testing is an important aspect of software development. Xcode has built-in support for unit testing. To keep things simple, however, we're going to ignore this option for now.
Include UI Tests: Xcode 7 is the first version of Apple's IDE that has built-in support for user interface testing. This is a big deal for OS X and iOS developers. User interface testing is beyond the scope of this series, though.
You should now have a good grasp of the different configuration options when setting up a new Xcode project. For this project, I recommend that you use the options as shown in the above screenshot. Note that most options can easily be changed after you've created your project. Click Next when you're finished configuring your project.
4. Save the Project
In the next step, Xcode asks you where you want to save your new project. You may have noticed the little checkbox at the bottom of the window labeled Create Git repository on My Mac. The gray text below the checkbox reads Xcode will place your project under version control.
As I mentioned earlier in this series, source control is indispensable in software development. This series will not cover this topic in detail, but if you're serious about software development, then I highly recommend reading up on source control.
Git is the most popular SCM (Source Code Management) system in the Cocoa community. However, it's perfectly possible to use a different SCM system, such as SVN or Mercurial.
Tell Xcode where you want to save your project, check the checkbox to authorize Xcode to create a Git repository for the project, and click Create at the bottom of the dialog.
5. Exploring Xcode's User Interface
Before we move on, I want to take a few minutes to explore Xcode's user interface. There are four distinct areas:
a toolbar at the top
a sidebar on the left
a main view in the center
a sidebar at the right
Toolbar
The toolbar at the top contains the buttons and menus that you'll find yourself using most often. As we saw earlier in this series, the buttons to run and stop an application also live in the toolbar.
The display in the center of the toolbar is similar to the display you find in iTunes. It displays information about your project's state or what Xcode is currently doing in the background. It will tell you, for example, when a build succeeds or fails.
The two segmented controls on the right of the toolbar can be used to customize Xcode's user interface. Play around with the various controls to find out how each of them changes the user interface of Xcode.
Navigator
The main purpose of the left sidebar is for navigation and it's often referred to as Xcode's navigator.
The navigator has different tabs with the Project Navigator at the far left. The selection in the left sidebar determines what is shown in Xcode's main view, the workspace.
Main View or Workspace
The main view or workspace is the area where you'll spend most of your time. It's Xcode's workhorse and displays whatever's selected in the navigator.
Inspector
While the left sidebar controls what's being displayed in Xcode's main view, the contents of the right sidebar reflect what's being displayed or selected in the main view.
The right sidebar, also known as the inspector, adapts itself to whatever the user selects in the main view.
6. Exploring the Project
It's time to take a look at the project itself. The project's contents are displayed in the Project Navigator, the first tab in the left sidebar. Select the first item in the Project Navigator to see the project details in the main view.
The main view is composed of two sections, a sidebar on the left and a detail view on the right. In the sidebar, you see two items, your project with one item and targets with one item.
It's good to know early on what the difference is between a project and a target. Remember that a project is a repository for the files, assets, and data that are required to build one or more products. A target refers to one of those products. A target contains the necessary instructions to build a product with the project's resources. This means that a project can contain multiple targets to build multiple products. As you can see, an Xcode project is more than just a folder with a bunch of files in it.
7. Build & Run: Take 1
Before we start modifying the source code of the project, it may be interesting to build and run your new project to see what the application template has given us for free. Click the Run button in the top left and make sure that the active scheme is configured to run the application in the simulator by selecting iPhone 6 or another simulator for iPhone.
If all went well, the simulator should launch your application and display an empty, white view with the familiar status bar at the top.
8. Modify the User Interface
Let's get our hands dirty and modify the application's user interface. Open the Project Navigator and select the file named Main.storyboard. A file with a .storyboard extension is a user interface file. In this file, we create the user interface of the application.
The storyboard contains one item, a view controller with the white view you saw in the simulator a few moments ago. The workspace is composed of a sidebar showing the object representation of the scenes of the storyboard. The largest part of the workspace contains the scenes or the user interface of the application.
Select the object named View in the View Controller Scene in the left sidebar and see how the workspace and the right sidebar update their contents. A bunch of tabs appear at the top of the right sidebar. Each tab contains a collection of attributes related to the object named View.
The lower half of the right sidebar contains a section with four tabs. The third tab is represented by an image of a three-dimensional box. This box is how objects are commonly displayed in Xcode.
Select the tab with the box icon and scroll through the list that appears. The list is referred to as the Object Library and contains various user interface elements, such as buttons, sliders, and switches.
At the start of this tutorial, I told you we were going to create a functional application. The user should be able to touch the screen to change its color.
There are multiple approaches to detect touches in an iOS application. One solution is to use a button. In the Object Library, find the item named Button and drag it from the Object Library to the white view in Xcode's workspace.
The user should be able to touch any part of the screen, which means the button should cover the entire screen. Have you noticed the six, tiny squares at the button's edges? By moving the tiny squares, you can modify the button's dimensions. Adjust the size of the button to make it cover the entire screen. Don't worry about the status bar at the top of the screen.
The view behind the button is the view that will change color when the user touches the screen. At the moment, the button is blocking the view from the user's view so we need to modify the button's attributes.
You may have noticed that the button has been added to the list of objects in the left sidebar, below the object named View. Select the button from the list of objects and select the Attributes Inspector in the right sidebar—the fourth tab from the left. We only need to make two adjustments.
Start by changing the type of the button from System to Custom. This will make the button transparent.
The second change we need to make is instructing the user what to do by changing the button's title. The text field next to the label Title currently reads Button. Change this to Tap to Change Color and set the Text Color to black to make it more readable.
9. Add an Action to the View Controller
If you're familiar with the MVC (Model-View-Controller) pattern, then you have a head start learning iOS development. The MVC pattern is a pattern found in many languages and frameworks, such as Laravel and Ruby on Rails.
The view in our user interface falls in the V category of the MVC pattern. A view is controlled by a controller. Take a look at the file names in the Project Navigator on the left. ViewController.swift represents a view controller that controls the view in our user interface.
What does a view controller do? A view controller can do whatever you want, but it's in the first place responsible for handling everything that happens in the view that it manages. This includes, for example, touches from the user. If the user taps the button in the view, it's the view controller's responsibility to handle the touch event.
How do we handle a touch event? In the case of our button, we add an action to the view controller. An action is a fancy name for a method. What is a method? A method is a Swift function. Wait. What? Don't worry about the terminology too much at this point. The next two posts will cover the Swift programming language in more detail. What you need to remember is that a method is like a method in Ruby and PHP, or a function in JavaScript.
If you invoke a method of a view controller, it does something in response. In other words, if a user taps the button and we connect a method to that touch event, the view controller will do something in response to the touch event.
To add an action to the view controller that manages the view in the application's user interface, we need to make some changes to the file named ViewController.swift. We only need to add a few lines of code to ViewController.swift. Take a look at how I modified the file's contents.
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func changeColor(sender: UIButton) {
}
}
Even though we won't focus on the syntax in this tutorial, it's fairly easy to understand what's going on. The name of the action or method is changeColor(_:) and it has one parameter, sender. The type of the parameter is UIButton. What is UIButton? Patience grasshopper.
10. Implement the Action
We've added an action to the view controller, but the action doesn't do much. The action doesn't have a body or implementation yet. To implement the changeColor(_:) action, we need to add one or more statements between the curly braces as shown in the code snippet below. I'm not going to explain each line of code in detail, but I'll give you the gist of what's happening.
@IBAction func changeColor(sender: UIButton) {
// Generate Random Numbers
let r = CGFloat(arc4random() % 255)
let g = CGFloat(arc4random() % 255)
let b = CGFloat(arc4random() % 255)
// Create Color
let color = UIColor(red: (r/255.0), green: (g/255.0), blue: (b/255.0), alpha: 1.0)
// Update View
view.backgroundColor = color
}
As you may know, it's possible to break a color down into the three primary colors, red, green, and blue. In our action, we generate three random numbers between 0 and 255, and use these numbers to create a random color.
The method we use to create the color is very descriptive, init(red:green:blue:alpha:). With the last line of our action, we set the background color of the view in our user interface to this new, randomly generated color.
Comments are important when writing code. Did you spot the comments I added to the implementation of changeColor(_:)? Single line comments start with two forward slashes , //, whereas multiline comments start with /* and end with */.
11. Connect the Action
The method is implemented, but nothing spectacular will happen if we build and run the application. Give it a try if you don't believe me.
What's missing is a connection between the button and the view controller's action. How should the view controller know that the changeColor(_:) action needs to be triggered when the button is tapped?
Making this connection is simple. Open the storyboard by selecting Main.storyboard and select the View Controller object in the View Controller Scene.
With the View Controller object selected, open the Connections Inspector in the right sidebar—the first tab from the right. If you've followed the steps correctly, you should see the action we created in the Received Actions section.
You should see an empty circle on the right of the changeColor(_:) action. Click and drag from the circle to the button in the view controller's view.
A menu pops up when you release the mouse. The menu contains a list of touch event types. The touch event that we're interested in is named Touch Up Inside. This event is triggered when a user touches the button and lifts her finger. This is the most common behavior for buttons.
After connecting the button and the action, you should see that the right sidebar reflects the connection you just made. Great. You've successfully completed your first real application.
12. Build & Run: Take 2
Build and run your application in the simulator and start tapping the simulator's screen. Every time you tap the screen, its color should change to a new, random color. How cool is that?
Conclusion
We've covered a lot of ground in this tutorial. Even though this post was quite lengthy, we didn't actually do very much. If you know the theory, you can create Colorific in less than five minutes. If you ran into a problem during this tutorial, then make sure to download the source files from GitHub.
In the next two installments, we will explore the basics of the Swift programming language. This will prepare you for the interesting stuff in the rest of the series.
If you have any questions or comments, you can leave them in the comments below or reach out to me on Twitter.
One of the most effective marketing tools is definitely word of mouth. Social proof is a very
powerful stimulus when it comes to decision making. While people easily ignore
traditional advertising, few people tend to ignore advice from a
trusted source, such as a friend.
In 2011, Google and Ipsos OTX carried out a survey that revealed interesting results. If recommendations are complemented by discount coupons that recipients can redeem, the
probability that they will download the app or will start to use it
again are much higher. This is something developers and app publishers may want to keep in mind.
The truth is that very few mobile app publishers and developers make use of a referral system that is based on recommendations. The
reason is almost always technical. Keeping track of discount codes, implementing deep linking within apps, and setting up a backend are some of the hurdles developers need to take to make this work. As a result, most people don't bother or give up.
Fortunately, Google developed a system that overcomes these obstacles, App Invites. With App Invites, Google offers a powerful interface through which developers can
grow their mobile app's audience by letting existing users invite their contacts to try the app.
App Invites is included in Google Play services and is also available on iOS. It optimizes your app
install rates by reducing friction and providing some context, such as the app's
general information and its rating on the app store, at every step of the user
invitation flow.
In this tutorial, I will show you how to implement this powerful tool in your own Android application.
1. Project Setup
Step 1: Create the Project
I will use a very simple project to show you how to share invites for your app. The first thing you need to do is create a new
project. In Android Studio, choose File > New > New Project. Name your app and set your company's web
domain to let Android Studio define the package name of your app.
The minimum SDK version that the app can support can be as
low as Android Gingerbread (API level 9). This means that you can target almost every device running Android, 99.97% at the time of writing. However, keep in mind that App Invites only work on devices that include Google's Play store since it is based on the Google Play services plugin.
Generate a blank Activity and name it MainActivity.java.
Step 2: Add Google Play Services and Support Libraries
With the new project opened in Android Studio, open the Project tab on the left and expand Gradle Scripts. It contains two files with the same name, build.gradle. The first file is the top-level build.gradle. The second file is the app-level build.gradle.
Open the top-level build.gradle and add the
following classpath for Google Play services.
To enable the Google Play services plugin, add the following line below apply plugin: 'com.android.application'.
apply plugin: 'com.google.gms.google-services'
Android Studio will ask you to synchronize the project files. Before
you do, however, open AndroidManifest.xml and add the Google Play services version within the application tag.
Save the changes and click Sync Now. We're not done yet. Android Studio will throw an error that tells you that the Google Play services plugin requires a configuration file, google-services.json. Let's fix that now.
2. Add Configuration File
Step 1: Visit Google Developer Platform
You frist need to visit the Google Developers website to enable Google services for your app. The project is then added to your personal developer console, which means that you have to be authenticated as a Google user before proceeding.
Enter the name you chose for your app and specify its
package name. If you don’t remember the app's package name, then open the app-level build.gradle. You can find it under defaultConfig > applicationId.
Fill out the rest of the form and click the button at the bottom labeled Choose and configure services.
Step 2: Generate Certificate Fingerprint
The next part is a bit trickier. Google will ask you for the
certificate fingerprint. To obtain the certificate fingerprint, you need to open the command line and execute the following command.
If you're testing your app locally, the key name is androiddebugekey and its default location is %USERPROFILE%\.android\debug.keystore on
Windows and ~/.android/debug.keystore on Unix systems, such as OS X and Linux. This is what the command looks like for testing locally.
The keytool utility will prompt you to enter a password. The default password for the debug keystore is android. This will yield the SHA1
fingerprint of your debug certificate, which looks something like this.
However, if you need the release certificate
fingerprint, then you need to specify the certificate's name, location, and password.
Step 3: Add Configuration File
After entering the certificate fingerprint, you can enable App Invites by clicking the Enable App Invites button at the bottom. You should now be able to
download the configuration file by clicking Download google-services.json.
To complete this step, copy the downloaded file to the app/ or mobile/
directory of your project.
3. Sending Invitations
Step 1: Define Layout
With the project configured, we are ready for the next step. For the launcher Activity, define a simple layout like the one shown below. It contains a button and a label.
In the onCreate method the MainActivity class, add anonCreateListener to the button.
button = findViewById(R.id.invite);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// do something, will you?
}
});
The invitation will be sent as an Intent. You can specify a message that users can customize before sending the invites to their
friends. You can also set a call to action, a background image, and a deep link that
your app can handle once the invitation is received. You can even define the minimum SDK version (setAndroidMinimumVersionCode)
and a target application ID for other platforms, such as iOS (setOtherPlatformsTargetApplication).
Create the Intent in the body of the onClick method.
Intent intent = new AppInviteInvitation.IntentBuilder(INVITATION_TITLE)
.setMessage(INVITATION_MESSAGE)
.setCallToActionText(INVITATION_CALL_TO_ACTION)
.build();
startActivityForResult(intent, REQUEST_INVITE);
Add the following strings to make all this work.
private static final
String INVITATION_TITLE = "Call your friends",
INVITATION_MESSAGE = "Hey! Would you like to get a 50% discount for this awesome app? :)",
INVITATION_CALL_TO_ACTION = "Share";
That's all there is to it. When the Intent is started, a custom Activity shows up that lets the user choose how they'd like to send the invitation (email or text message), the message of the invitation, and the recipients.
The intent is started by calling startActivityForResult. It is possible to fetch the result of the intent. Once the user has hit the send button, they are brought back to the activity that started the intent. At that moment, you can do whatever is necessary in onActivityResult, such as hiding the button or tracking invites through analytics.
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_INVITE) {
if (resultCode == RESULT_OK) {
// You successfully sent the invite,
// we can dismiss the button.
button.setVisibility(View.GONE);
String[] ids = AppInviteInvitation.getInvitationIds(resultCode, data);
StringBuilder sb = new StringBuilder();
sb.append("Sent ").append(Integer.toString(ids.length)).append(" invitations: ");
for (String id : ids) sb.append("[").append(id).append("]");
Log.d(getString(R.string.app_name), sb.toString());
} else {
// Sending failed or it was canceled using the back button
showMessage("Sorry, I wasn't able to send the invites");
}
}
}
4. Deep Linking
Step 1: Send Deep Link Data
When a user receives the invitation and clicks the included link, the invitation flow branches according to whether or not the app is
already installed on the recipient's smartphone. If the app is already present, it will automatically receive an Intent containing the optional deep link data.
However, if the recipient doesn't have the app installed installed, they are given the chance to do so. When the app is first launched, the app will receive an Intent containing the deep link data. This way, the discount you may want to provide will always be available
to the recipient. This overcomes the issues we talked about earlier.
Let's explore deep linking in more detail. Set the deep link of the Intent we created in the onCreate method.
Intent intent = new AppInviteInvitation.IntentBuilder(INVITATION_TITLE)
.setMessage(INVITATION_MESSAGE)
.setDeepLink(Uri.parse("tutsplus://code.coupon/50"))
.setCallToActionText(INVITATION_CALL_TO_ACTION)
.build();
Step 2: Intent Filtering for Custom URLs
The first thing you need to do to handle custom
deep links is telling your app how they are made and which Activity should take care of them. Add a new Activity to your project and name it DetailsActivity.
Open AndroidManifest.xml and add the following snippet to the <activity android:name=".DetailsActivity"> tag.
We are telling the system the following. If it invokes
the action VIEW on a URL whose scheme is tutsplus and whose host is code.coupon, your
app can handle it using the DetailsActivity class.
In order to receive and parse the custom URL, you first have to create an auto-managed GoogleApiClient with access to App Invites. We do this in the onCreate method of the MainActivity class.
GoogleApiClient googleApiClient = new GoogleApiClient.Builder(this)
.addApi(AppInvite.API)
.enableAutoManage(this, new GoogleApiClient.OnConnectionFailedListener() {
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d(getString(R.string.app_name), "onConnectionFailed:" + connectionResult);
showMessage("Sorry, the connection has failed.");
}
})
.build();
Step 3: Receiving and Parsing the Deep Link
To check for invitations and to launch the deep link Activity, you can use the getInvitation method, which was introduced in Google Play services 8.3. Add the following code snippet to the onCreate method of the MainActivity class.
AppInvite.AppInviteApi.getInvitation(googleApiClient, this, true)
.setResultCallback(
new ResultCallback<AppInviteInvitationResult>() {
@Override
public void onResult(AppInviteInvitationResult result) {}
});
Setting the last parameter of the method to true tells the plugin to automatically call the activity responsible for handling the deep link,
the DetailsActivity class in our example. This is the reason why the body of the onResult method is empty.
Open activity_details.xml and add two TextView objects like shown below.
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context="com.tutsplus.code.appinvites.DetailsActivity"><TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center"
android:text="Awesome!"
android:textAppearance="@style/TextAppearance.AppCompat.Title"
android:textSize="45sp" /><TextView
android:id="@+id/discount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
android:layout_marginBottom="100dp"
android:gravity="center"
android:text="You accepted the invitation, and this gives you the right to a %s percent discount :)"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:textSize="20sp" /></RelativeLayout>
Next, open DetailsActivity and override the onStart method.
To check if the Intent contains deep link data, you have to
rely on the hasReferral method. The URL parsing is very straightforward as you can see below.
@Override
protected void onStart() {
super.onStart();
Intent intent = getIntent();
if (AppInviteReferral.hasReferral(intent)) {
// Extract the information from the Intent
String deepLink = AppInviteReferral.getDeepLink(intent);
Log.d(getString(R.string.app_name),
"Found Referral: " + AppInviteReferral.getInvitationId(intent) + ":" + deepLink);
String[] array = deepLink.split("/");
if (array.length > 0) {
TextView tv = (TextView) findViewById(R.id.discount);
tv.setText(String.format(tv.getText().toString(), array[array.length-1]));
}
}
}
Conclusion
In this article, you learned how to implement Google's App Invites in your app, using the Google Play services plugin. This tool lets you increase the audience of your app by allowing users to send invitations to their Google contacts. You should now be able to develop a referral system by leveraging App Invites, letting
your users recommend your app to their friends using personalized, contextual
invitations.
tag:code.tutsplus.com,2005:PostPresenter/cms-25321What You'll Be Creating
Introduction
One of the most effective marketing tools is definitely word of mouth. Social proof is a very
powerful stimulus when it comes to decision making. While people easily ignore
traditional advertising, few people tend to ignore advice from a
trusted source, such as a friend.
In 2011, Google and Ipsos OTX carried out a survey that revealed interesting results. If recommendations are complemented by discount coupons that recipients can redeem, the
probability that they will download the app or will start to use it
again are much higher. This is something developers and app publishers may want to keep in mind.
The truth is that very few mobile app publishers and developers make use of a referral system that is based on recommendations. The
reason is almost always technical. Keeping track of discount codes, implementing deep linking within apps, and setting up a backend are some of the hurdles developers need to take to make this work. As a result, most people don't bother or give up.
Fortunately, Google developed a system that overcomes these obstacles, App Invites. With App Invites, Google offers a powerful interface through which developers can
grow their mobile app's audience by letting existing users invite their contacts to try the app.
App Invites is included in Google Play services and is also available on iOS. It optimizes your app
install rates by reducing friction and providing some context, such as the app's
general information and its rating on the app store, at every step of the user
invitation flow.
In this tutorial, I will show you how to implement this powerful tool in your own Android application.
1. Project Setup
Step 1: Create the Project
I will use a very simple project to show you how to share invites for your app. The first thing you need to do is create a new
project. In Android Studio, choose File > New > New Project. Name your app and set your company's web
domain to let Android Studio define the package name of your app.
The minimum SDK version that the app can support can be as
low as Android Gingerbread (API level 9). This means that you can target almost every device running Android, 99.97% at the time of writing. However, keep in mind that App Invites only work on devices that include Google's Play store since it is based on the Google Play services plugin.
Generate a blank Activity and name it MainActivity.java.
Step 2: Add Google Play Services and Support Libraries
With the new project opened in Android Studio, open the Project tab on the left and expand Gradle Scripts. It contains two files with the same name, build.gradle. The first file is the top-level build.gradle. The second file is the app-level build.gradle.
Open the top-level build.gradle and add the
following classpath for Google Play services.
To enable the Google Play services plugin, add the following line below apply plugin: 'com.android.application'.
apply plugin: 'com.google.gms.google-services'
Android Studio will ask you to synchronize the project files. Before
you do, however, open AndroidManifest.xml and add the Google Play services version within the application tag.
Save the changes and click Sync Now. We're not done yet. Android Studio will throw an error that tells you that the Google Play services plugin requires a configuration file, google-services.json. Let's fix that now.
2. Add Configuration File
Step 1: Visit Google Developer Platform
You frist need to visit the Google Developers website to enable Google services for your app. The project is then added to your personal developer console, which means that you have to be authenticated as a Google user before proceeding.
Enter the name you chose for your app and specify its
package name. If you don’t remember the app's package name, then open the app-level build.gradle. You can find it under defaultConfig > applicationId.
Fill out the rest of the form and click the button at the bottom labeled Choose and configure services.
Step 2: Generate Certificate Fingerprint
The next part is a bit trickier. Google will ask you for the
certificate fingerprint. To obtain the certificate fingerprint, you need to open the command line and execute the following command.
If you're testing your app locally, the key name is androiddebugekey and its default location is %USERPROFILE%\.android\debug.keystore on
Windows and ~/.android/debug.keystore on Unix systems, such as OS X and Linux. This is what the command looks like for testing locally.
The keytool utility will prompt you to enter a password. The default password for the debug keystore is android. This will yield the SHA1
fingerprint of your debug certificate, which looks something like this.
However, if you need the release certificate
fingerprint, then you need to specify the certificate's name, location, and password.
Step 3: Add Configuration File
After entering the certificate fingerprint, you can enable App Invites by clicking the Enable App Invites button at the bottom. You should now be able to
download the configuration file by clicking Download google-services.json.
To complete this step, copy the downloaded file to the app/ or mobile/
directory of your project.
3. Sending Invitations
Step 1: Define Layout
With the project configured, we are ready for the next step. For the launcher Activity, define a simple layout like the one shown below. It contains a button and a label.
In the onCreate method the MainActivity class, add anonCreateListener to the button.
button = findViewById(R.id.invite);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// do something, will you?
}
});
The invitation will be sent as an Intent. You can specify a message that users can customize before sending the invites to their
friends. You can also set a call to action, a background image, and a deep link that
your app can handle once the invitation is received. You can even define the minimum SDK version (setAndroidMinimumVersionCode)
and a target application ID for other platforms, such as iOS (setOtherPlatformsTargetApplication).
Create the Intent in the body of the onClick method.
Intent intent = new AppInviteInvitation.IntentBuilder(INVITATION_TITLE)
.setMessage(INVITATION_MESSAGE)
.setCallToActionText(INVITATION_CALL_TO_ACTION)
.build();
startActivityForResult(intent, REQUEST_INVITE);
Add the following strings to make all this work.
private static final
String INVITATION_TITLE = "Call your friends",
INVITATION_MESSAGE = "Hey! Would you like to get a 50% discount for this awesome app? :)",
INVITATION_CALL_TO_ACTION = "Share";
That's all there is to it. When the Intent is started, a custom Activity shows up that lets the user choose how they'd like to send the invitation (email or text message), the message of the invitation, and the recipients.
The intent is started by calling startActivityForResult. It is possible to fetch the result of the intent. Once the user has hit the send button, they are brought back to the activity that started the intent. At that moment, you can do whatever is necessary in onActivityResult, such as hiding the button or tracking invites through analytics.
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_INVITE) {
if (resultCode == RESULT_OK) {
// You successfully sent the invite,
// we can dismiss the button.
button.setVisibility(View.GONE);
String[] ids = AppInviteInvitation.getInvitationIds(resultCode, data);
StringBuilder sb = new StringBuilder();
sb.append("Sent ").append(Integer.toString(ids.length)).append(" invitations: ");
for (String id : ids) sb.append("[").append(id).append("]");
Log.d(getString(R.string.app_name), sb.toString());
} else {
// Sending failed or it was canceled using the back button
showMessage("Sorry, I wasn't able to send the invites");
}
}
}
4. Deep Linking
Step 1: Send Deep Link Data
When a user receives the invitation and clicks the included link, the invitation flow branches according to whether or not the app is
already installed on the recipient's smartphone. If the app is already present, it will automatically receive an Intent containing the optional deep link data.
However, if the recipient doesn't have the app installed installed, they are given the chance to do so. When the app is first launched, the app will receive an Intent containing the deep link data. This way, the discount you may want to provide will always be available
to the recipient. This overcomes the issues we talked about earlier.
Let's explore deep linking in more detail. Set the deep link of the Intent we created in the onCreate method.
Intent intent = new AppInviteInvitation.IntentBuilder(INVITATION_TITLE)
.setMessage(INVITATION_MESSAGE)
.setDeepLink(Uri.parse("tutsplus://code.coupon/50"))
.setCallToActionText(INVITATION_CALL_TO_ACTION)
.build();
Step 2: Intent Filtering for Custom URLs
The first thing you need to do to handle custom
deep links is telling your app how they are made and which Activity should take care of them. Add a new Activity to your project and name it DetailsActivity.
Open AndroidManifest.xml and add the following snippet to the <activity android:name=".DetailsActivity"> tag.
We are telling the system the following. If it invokes
the action VIEW on a URL whose scheme is tutsplus and whose host is code.coupon, your
app can handle it using the DetailsActivity class.
In order to receive and parse the custom URL, you first have to create an auto-managed GoogleApiClient with access to App Invites. We do this in the onCreate method of the MainActivity class.
GoogleApiClient googleApiClient = new GoogleApiClient.Builder(this)
.addApi(AppInvite.API)
.enableAutoManage(this, new GoogleApiClient.OnConnectionFailedListener() {
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d(getString(R.string.app_name), "onConnectionFailed:" + connectionResult);
showMessage("Sorry, the connection has failed.");
}
})
.build();
Step 3: Receiving and Parsing the Deep Link
To check for invitations and to launch the deep link Activity, you can use the getInvitation method, which was introduced in Google Play services 8.3. Add the following code snippet to the onCreate method of the MainActivity class.
AppInvite.AppInviteApi.getInvitation(googleApiClient, this, true)
.setResultCallback(
new ResultCallback<AppInviteInvitationResult>() {
@Override
public void onResult(AppInviteInvitationResult result) {}
});
Setting the last parameter of the method to true tells the plugin to automatically call the activity responsible for handling the deep link,
the DetailsActivity class in our example. This is the reason why the body of the onResult method is empty.
Open activity_details.xml and add two TextView objects like shown below.
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context="com.tutsplus.code.appinvites.DetailsActivity"><TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center"
android:text="Awesome!"
android:textAppearance="@style/TextAppearance.AppCompat.Title"
android:textSize="45sp" /><TextView
android:id="@+id/discount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
android:layout_marginBottom="100dp"
android:gravity="center"
android:text="You accepted the invitation, and this gives you the right to a %s percent discount :)"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:textSize="20sp" /></RelativeLayout>
Next, open DetailsActivity and override the onStart method.
To check if the Intent contains deep link data, you have to
rely on the hasReferral method. The URL parsing is very straightforward as you can see below.
@Override
protected void onStart() {
super.onStart();
Intent intent = getIntent();
if (AppInviteReferral.hasReferral(intent)) {
// Extract the information from the Intent
String deepLink = AppInviteReferral.getDeepLink(intent);
Log.d(getString(R.string.app_name),
"Found Referral: " + AppInviteReferral.getInvitationId(intent) + ":" + deepLink);
String[] array = deepLink.split("/");
if (array.length > 0) {
TextView tv = (TextView) findViewById(R.id.discount);
tv.setText(String.format(tv.getText().toString(), array[array.length-1]));
}
}
}
Conclusion
In this article, you learned how to implement Google's App Invites in your app, using the Google Play services plugin. This tool lets you increase the audience of your app by allowing users to send invitations to their Google contacts. You should now be able to develop a referral system by leveraging App Invites, letting
your users recommend your app to their friends using personalized, contextual
invitations.
On Android, the AsyncTask class is commonly used to perform operations on a background thread. In this video, I show you how an AsyncTask works and how you can use it in your projects.
A Bit More Detail
Learn more about Android development on Envato Tuts+:
This is part of a new series of quick video tutorials on Envato Tuts+. We’re aiming to introduce a range of subjects, all in 60 seconds–just enough to whet your appetite. Let us know in the comments what you thought of this video and what else you’d like to see explained in 60 seconds!
More and more mobile applications offer the ability to send messages to other users using the application. In many games, for example, you can chat with fellow gamers while chat applications allow you to talk to whomever you like. The possibilities are endless. Adding user chat to an application can be an important feature of your application.
Building a solution to enable users to chat with one another is a daunting task many developers prefer to sidestep. Fortunately, there's no need to reinvent the wheel. Magnet Message is an open source mobile messaging framework that is ideal for this use case. They offer iOS and Android support as well as a REST API. Getting started with Magnet Message is quick and easy thanks to their sandbox environment.
In this tutorial, you will learn how to integrate Magnet Message in an iOS application using Swift 2. You will learn how easy it is to set up Magnet Message in a project and send messages to other users of your application. Let's start by creating an account and setting up the sandbox.
Prerequisites
Even though the Magnet library for iOS is written in Objective-C, in this tutorial I'll be working with Xcode 7.1 and Swift 2.1. You can download Xcode 7.1 from Apple's developer website or from the App Store.
1. Creating a Magnet Account
Before we can start integrating Magnet into a mobile application, we need a Magnet account. A Magnet account gives you access to a sandbox environment for development as well as a number of sample applications to learn from. To follow along, navigate to Magnet's Developer website, click Try Itat the top, and sign up with an email address.
2. Creating a Sandbox Application
Your free Magnet account gives you access to a range of resources, including a sandbox you can use for development. Go to developer.magnet.com and go to the sandbox. You immediately notice that the sandbox already contains three applications. Each of these applications corresponds with one of the sample applications.
For this tutorial, we'll create a new application. Click the green plus button in the top right to create a new application and name it MessageMe.
When you click Save, the sandbox automatically opens the application and shows you a Getting Started guide. Click the Apple logo at the top to show the instructions for iOS.
You can skip the instructions, because I'll be guiding you through the setup process. There is one resource we need to get started, a property containing the configuration for the Magnet application. In the second step of the Build the App section, you can see a link to download MagnetMax.plist. Click the link to download the property list to your machine. We'll be needing it in a few moments.
If you open MagnetMax.plist, you'll see that it contains three key-value pairs, BaseURL, ClientID, ClientSecret. This information will be used by Magnet's library to talk to the Magnet Message backend.
3. Setting Up the Project
Launch Xcode 7.1 and choose the Single View Application template from the list of iOS > Application templates.
Name the application MessageMe, set Language to Swift, Devices to iPhone, and leave the checkboxes at the bottom unchecked. Tell Xcode where you'd like to save the project and click Create.
4. Setting Up CocoaPods
As I mentioned earlier, Magnet has developed an open source library for interacting with the Magnet Message backend. The easiest way to integrate the library in an Xcode project is through CocoaPods. Close the project you just created, open a Terminal window, and navigate to the root of the project. Create a Podfile for your project by executing the pod init command from the command line.
The Podfile lives at the root of your project. Open it in a text editor and replace its contents with the following.
source 'https://github.com/CocoaPods/Specs'
source 'https://github.com/magnetsystems/Specs'
platform :ios, '9.0'
use_frameworks!
target 'MessageMe' do
pod 'MagnetMax', '~> 2.0'
end
From the command line, execute the pod install command to install the dependencies specified in the Podfile. This will install the MagnetMax library that Magnet provides for interacting with the Magnet Message API. It will also create a workspace that we'll use from now on. After completing the installation process, open MessageMe.xcworkspace at the root of your project.
5. Setting Up Magnet
Step 1: Adding MagnetMax.plist
Setting up and configuring Magnet is very easy to do. Earlier in this tutorial, you downloaded MagnetMax.plist from Magnet's sandbox. Add this property list to the MessageMe project in the MessageMe workspace. Because MagnetMax.plistcontains sensitive data, I have excluded it from source control so you won't find it in the source files of this tutorial.
Step 2: Import MagnetMax Framework
Open AppDelegate.swift and add an import statement for the MagnetMax framework we installed through CocoaPods.
import UIKit
import MagnetMax
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
...
}
Step 3: Setting Up Magnet
In application(_:didFinishLaunchingWithOptions:), call setupWithConfiguration(_:) on the MagnetMax class, passing in the name of the configuration in MagnetMax.plist that we want to work with.
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Setting Up Magnet
let configurationFile = NSBundle.mainBundle().pathForResource("MagnetMax", ofType: "plist")
let configuration = MMPropertyListConfiguration(contentsOfFile: configurationFile!)
MagnetMax.configure(configuration!)
return true
}
Step 4: Build and Run
Build and run the target on a physical device or in the simulator to make sure everything is set up correctly. Make sure you've correctly followed the above steps if you run into problems.
6. Registering a User
Before a user can send messages to another user, she needs to create an account in our application. Magnet's account system is simple and transparent, and registering a user is straightforward to implement. In this section, we'll create a simple form to enable users to create an account or, if they already have an account, sign in to their account.
Step 1: Creating Classes
Before we create the user interface, we need to create two UIViewController subclasses, MessageViewController and SignInViewController. The first view controller will be in charge of sending messages. The second view controller will manage user registration as well as the sign in process.
Step 2: Creating User Interface
Open Main.storyboard, select the view controller that's already present, and choose Embed In > Navigation Controller from Xcode's Editor menu. Open the Object Library on the right and add a bar button item to the view controller's navigation bar. With the bar button item selected, set System Item to Compose in the Attributes Inspector.
Drag a view controller from the Object Library and set its class to MessageViewController in the Identity Inspector. Create a segue from the compose bar button item to the message view controller, setting Kind to Present Modally. Add a navigation bar at the top of the message view controller and add a bar button item on the left. In the Attributes Inspector, set System Item to Done.
Add two regular buttons to the message view controller and place them in a view. This makes it easier to hide both buttons when necessary. Set the titles of the button to Sign In and Create Account respectively.
Finally, add another view controller and set its class to SignInViewController in the Identity Inspector. Add a navigation bar at the top and add a bar button item on the left. Set System Item to Cancel in the Attributes Inspector. Add two text fields to the view controller, one for the user's username and one for the user's password. Don't forget to check Secure Text Entry in the Attributes Inspector for the password text field. Last but not least, add a button below the text fields and set its title to Sign In.
Create a segue from the Sign In button of the message view controller to the sign in view controller and set the segue's identifier to SegueSignIn. Repeat this step for the Create Account button and set the segue's identifier to SegueCreateAccount. Both segues should be of kind Show.
Step 3: Creating Outlets
Open MessageViewController.swift and declare an outlet for the view in which the Sign In and Create Account buttons are located. Note that I've also created an action for the Done button in the navigation bar. Don't forget to connect the outlet and the action in the storyboard. For ease of use, I've also declared two constants for the segue identifiers.
import UIKit
class MessageViewController: UIViewController {
let SegueSignIn = "SegueSignIn"
let SegueCreateAccount = "SegueCreateAccount"
@IBOutlet weak var buttonsView: UIView!
// MARK: -
// MARK: Actions
@IBAction func done(sender: UIBarButtonItem) {
dismissViewControllerAnimated(true, completion: nil)
}
}
Open SignInViewController.swift and declare three outlets and a helper variable as shown below. The helper variable will help us determine whether the user tapped the Sign In or the Create Account button. I've also created actions for the Sign In and Cancel buttons. Wire everything up in the storyboard before continuing.
import UIKit
class SignInViewController: UIViewController {
@IBOutlet weak var signInButton: UIButton!
@IBOutlet weak var usernameTextField: UITextField!
@IBOutlet weak var passwordTextField: UITextField!
var hasAccount = true
// MARK: -
// MARK: Actions
@IBAction func signIn(sender: UIButton) {
}
@IBAction func cancel(sender: UIBarButtonItem) {
}
}
Step 4: Delegate Protocol
When the user is successfully signed in, the message view controller needs to be notified. We can do this by creating a delegate protocol. At the top of SignInViewController.swift, I've added an import statement for the MagnetMax library and declared the SignInViewControllerDelegate protocol. The protocol contains one method, controller(_:didSignInWithUser:), which we'll invoke when the user is successfully signed in. We also need to declare a delegate property of type SignInViewControllerDelegate? to keep a reference to the delegate of the sign in view controller.
import UIKit
import MagnetMax
protocol SignInViewControllerDelegate {
func controller(controller: SignInViewController, didSignInWithUser user: MMUser)
}
class SignInViewController: UIViewController {
@IBOutlet weak var signInButton: UIButton!
@IBOutlet weak var usernameTextField: UITextField!
@IBOutlet weak var passwordTextField: UITextField!
var delegate: SignInViewControllerDelegate?
var hasAccount = true
...
}
Step 5: Signing In
The first thing we need to do is implement prepareForSegue(_:sender:) in the MessageViewController class. In this method, we check which button the user tapped and configure the SignInViewController instance accordingly by setting its hasAccount property.
// MARK: -
// MARK: Prepare for Segue
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == SegueSignIn {
let signInViewController = segue.destinationViewController as! SignInViewController
// Configure Sign In View Controller
signInViewController.hasAccount = true
signInViewController.delegate = self
} else if segue.identifier == SegueCreateAccount {
let signInViewController = segue.destinationViewController as! SignInViewController
// Configure Sign In View Controller
signInViewController.hasAccount = false
signInViewController.delegate = self
}
}
Note that we also set the delegate property of the sign in view controller. This means that the MessageViewController class needs to conform to the SignInViewControllerDelegate protocol as shown below. The implementation of the controller(_:didSignInWithUser:) method is empty for now. Don't forget to add an import statement for the MagnetMax library to avoid compiler warnings.
Let's focus now on the interesting part, the actions of the SignInViewController class. Before we implement the signIn(_:) and cancel(_:) actions, I'd like to implement the viewDidLoad() method to update the title of the Sign In button based on the value of the hasAccount property.
The signIn(_:) action is more interesting. In this action, we make sure the user has entered valid data, a username and a password, and then invoke a helper method based on the value of the hasAccount property.
@IBAction func signIn(sender: UIButton) {
guard let username = usernameTextField.text else {
showAlertWithTitle("Username Required", message: "Enter a valid username.")
return
}
guard let password = passwordTextField.text else {
showAlertWithTitle("Password Required", message: "Enter a valid password.")
return
}
guard !username.isEmpty && !password.isEmpty else {
showAlertWithTitle("Error", message: "Enter a valid username and password.")
return;
}
// Create Credential
let credential = NSURLCredential(user: username, password: password, persistence: .None)
if hasAccount {
signInWithCredential(credential)
} else {
createAccountWithCredential(credential)
}
}
The showAlertWithTitle(_:message:) method is a private convenience method for displaying an alert to the user.
The createAccountWithCredential(_:) method is another private helper method for registering the user. We start by creating an instance of the MMUser class. This class represents a user for the Magnet Message backend. We register the user by invoking registerWithCredential(_:success:failure:), passing in an NSURLCredential object and two closures.
private func createAccountWithCredential(credential: NSURLCredential) {
// Create User
let user = MMUser()
// Configure User
user.userName = credential.user
user.password = credential.password
// Register User
user.register({ (user) -> Void in
// Sign User In
self.signInWithCredential(credential)
}) { (error) -> Void in
print(error)
if error.code == 409 {
// Account Already Exists
self.signInWithCredential(credential)
} else {
// Notify User
self.showAlertWithTitle("Error", message: "We were unable to create an account. Please try again.")
}
}
}
If registration is successful, we immediately sign the user in by invoking signInWithCredential(_:). If something went wrong, we inspect the error that was passed to us. If the error's code is equal to 409, we know the user accidentally created an account with existing credentials. It's then acceptable to sign the user in instead of showing them an alert. If registrations fails, we show the user an alert.
The signInWithCredential(_:) method isn't too complicated. If logging in is successful, we initialize the message module by invoking initModule(_:success:failure:) on MagnetMax. We store the username in the user defaults database and notify the delegate, passing it the MMUser instance. We also dismiss the sign in view controller. If signing the user in is unsuccessful, we show the user an alert.
private func signInWithCredential(credential: NSURLCredential) {
MMUser.login(credential, success: { () -> Void in
MagnetMax.initModule(MMX.sharedInstance(), success: { () -> Void in
// Store Username in User Defaults
NSUserDefaults.standardUserDefaults().setObject(credential.user, forKey: "username")
// Notify Delegate
self.delegate?.controller(self, didSignInWithUser: MMUser.currentUser()!)
// Pop View Controller
self.dismissViewControllerAnimated(true, completion: nil)
}, failure: { (error) -> Void in
print(error)
// Notify User
self.showAlertWithTitle("Error", message: "We were unable to sign you in. Please make sure that the credentials you entered are correct.")
})
}) { (error) -> Void in
print(error)
// Notify User
self.showAlertWithTitle("Error", message: "We were unable to sign you in. Please make sure that the credentials you entered are correct.")
}
Run the application on a physical device or in the simulator to test what we've got so far. Note that the username cannot contain spaces. You should now be able to register as a user.
7. Creating the Form
Step 1: Creating User Interface
When the user is signed in, she should be able to send messages to other people using the application. Let's start by creating a form for composing the message. Before we revisit Main.storyboard, we're going to declare a few outlets and an action.
We start by declaring an outlet named messageView. We show this view when the user is signed in. At the same time, we hide buttonsView, which contains the Sign In and Create Account buttons.
The message view will contain a text field to enter recipients, a text field for the message itself, a switch to include the location of the user in the message, and a button to send the message. Also note that the MessageViewController class conforms to the UITextFieldDelegate protocol. I'll explain why that is later in this tutorial.
I've also added two actions. The sendMessage(_:) action will be triggered by tapping the Send Message button. The locationSwitchDidChange(_:) action will be invoked when the user flips the switch on.
import UIKit
import MagnetMax
class MessageViewController: UIViewController, UITextFieldDelegate, SignInViewControllerDelegate {
let SegueSignIn = "SegueSignIn"
let SegueCreateAccount = "SegueCreateAccount"
@IBOutlet weak var messageView: UIView!
@IBOutlet weak var buttonsView: UIView!
@IBOutlet weak var sendButton: UIButton!
@IBOutlet weak var locationSwitch: UISwitch!
@IBOutlet weak var messageTextField: UITextField!
@IBOutlet weak var recipientsTextField: UITextField!
...
@IBAction func sendMessage(sender: UIButton) {
}
@IBAction func locationSwitchDidChange(sender: UISwitch) {
}
...
}
The user interface of the message view controller changes quite a bit as you can see below. There are a few things to point out.
The message view controller should be set as the delegate of the recipients text field, the top text field.
The location switch should be set to off in the Attributes Inspector and the locationSwitchDidChange(_:) action needs to be wired up to the Value Changed event.
Wire the Touch Up Inside event to the sendMessage(_:) action we declared a moment ago in the MessageViewController class.
Step 2: Showing the Form
We only show the form when the user is signed in. We can easily do this through property observers. Start by creating a property, user, of type MMXUser? in the message view controller and add a didSet property observer to it. In the didSet property observer we invoke a helper method, updateView().
var user: MMUser? {
didSet {
updateView()
}
}
The implementation of the updateView() method is simple. We also implement a setupView() method, which we invoke in the viewDidLoad() method of the MessageViewController class.
The only thing left to make this work is update the user property of the message view controller in the controller(_:didSignInWithUser:) delegate method.
Run the application, sign in to your account, and make sure the form is shown in the message view controller.
8. Fetching the User's Location
Fetching the user's location is pretty simple, especially in iOS 9. Since iOS 9, the CLLocationManager class declares a method, requestLocation(), to ask the operating system for the location of the device. Let's see how this works.
Step 1: Updating Info.plist
To make this work, we first need to add an entry to the target's Info.plist. What we need to add is a message informing the user why we need access to their location. Open the target's Info.plist in Xcode and add a new row with key NSLocationWhenInUseUsageDescription and value MessageMe would like to use your current location.
Step 2: Declaring Properties
We also need to declare two properties in the MessageViewController class, a property for the location manager and a property for the current location. Both are optionals.
import UIKit
import MagnetMax
import CoreLocation
class MessageViewController: UIViewController, UITextFieldDelegate, CLLocationManagerDelegate, SignInViewControllerDelegate {
let SegueSignIn = "SegueSignIn"
let SegueCreateAccount = "SegueCreateAccount"
@IBOutlet weak var messageView: UIView!
@IBOutlet weak var buttonsView: UIView!
@IBOutlet weak var sendButton: UIButton!
@IBOutlet weak var locationSwitch: UISwitch!
@IBOutlet weak var messageTextField: UITextField!
@IBOutlet weak var recipientsTextField: UITextField!
var locationManager: CLLocationManager?
var currentLocation: CLLocation?
...
}
Note that we also add an import statement for the CoreLocation framework and we conform the MessageViewController class to the CLLocationManagerDelegate protocol.
Step 3: Requesting Permission
We then update the locationSwitchDidChange(_:) method, which is triggered when the value of the location switch changes. We invoke requestLocation() when the switch is on.
The requestLocation() method is a private helper method in which we set up the location manager. Before we ask the operating system for the location of the device, we verify that we have permission to do so. If we don't, we first ask for the user's permission by invoking requestWhenInUseAuthorization().
// MARK: -
// MARK: Helper Methods
private func requestLocation() {
if locationManager == nil {
// Initialize Location Manager
let locationManager = CLLocationManager()
// Configure Location Manager
locationManager.delegate = self
// Set Location Manager
self.locationManager = locationManager
}
if CLLocationManager.authorizationStatus() == .AuthorizedWhenInUse {
// Request Location
locationManager?.requestLocation()
} else {
// Ask User for Permission
locationManager?.requestWhenInUseAuthorization()
}
}
By requesting the user's permission, the user will be prompted for permission. After the user makes its decision, allowing or denying permission, a delegate method is invoked, locationManager(_:didChangeAuthorizationStatus:). In this method, we request the location if we are allowed to do so.
In locationManager(_:didUpdateLocations:), we store the location in the currentLocation property.
9. Selecting Recipients
Step 1: Creating RecipientsViewController Class
The final piece of the puzzle is selecting recipients to send the message to. Create a new class, RecipientsViewController, and add an import statement for the MagnetMax library. At the top, declare a protocol, RecipientsViewControllerDelegate, to inform the delegate which recipients the user selected. The delegate will be the message view controller. We also need a property to keep a reference to the delegate.
The user interface is pretty straightforward. Add a navigation bar at the top and add two bar button items to it, Cancel on the left and Done on the right. Add a table view to the view controller, set its dataSource and delegate outlets, and add a search bar at the top of the table view. It's important that the view controller is the delegate of the search bar.
Finally, create a manual segue from the message view controller to the recipients view controller. Set the segue's identifier to SegueRecipients and Kind to Show in the Attributes Inspector.
Step 3: Implementing Delegate Protocols
Open RecipientsViewController.swift and conform the RecipientsViewController controller to the UITableViewDataSource, UITableViewDelegate, and UISearchBarDelegate protocols.
Declare a constant for the reuse identifier of the table view cells and a property, users, that will act as the data source of the table view. The users property is of type [MMUser].
class RecipientsViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate {
let SearchCell = "SearchCell"
@IBOutlet weak var tableView: UITableView!
var delegate: RecipientsViewControllerDelegate?
var users: [MMUser] = []
...
}
In the viewDidLoad() method, register the UITableViewCell class for cell reuse.
The implementation of the UITableViewDataSource protocol is also straightforward. We display the username of each user that we're going to fetch from the Magnet Message backend.
More interesting is the implementation of the searchBar(_:textDidChange:) method. In this method, we invoke searchUsers(_:limit:offset:sort:success:failure:) on the MMUser class. We pass in the query, how many results we'd like to receive, an offset, a key to sort the results by, and two closures, one for success and one for failure.
When the user has made its selection and taps the Done button, we forward the selection of recipients to the delegate, the message view controller.
@IBAction func done(sender: UIBarButtonItem) {
// Fetch Selection
var selection: [MMUser] = []
if let indexPaths = tableView.indexPathsForSelectedRows {
for indexPath in indexPaths {
selection.append(users[indexPath.row])
}
}
// Notify Delegate
delegate?.controller(self, didSelectRecipients: selection)
// Dismiss View Controller
dismissViewControllerAnimated(true, completion: nil)
}
The only thing left to do is configuring the recipients view controller when the SegueRecipients segue is performed. We do this in the MessageViewController class. Update the prepareForSegue(_:sender:) as shown below.
This also means that we need to declare the SegueRecipients constant and conform the MessageViewController class to the RecipientsViewControllerDelegate protocol.
class MessageViewController: UIViewController, UITextFieldDelegate, CLLocationManagerDelegate, SignInViewControllerDelegate, RecipientsViewControllerDelegate {
let SegueSignIn = "SegueSignIn"
let SegueRecipients = "SegueRecipients"
let SegueCreateAccount = "SegueCreateAccount"
...
}
Step 5: Storing the Recipients
In the MessageViewController class, we temporarily store the recipients in a property, recipients, of type [MMUser].
var recipients: [MMUser] = []
In the controller(_:didSelectRecipients:) method of the RecipientsViewControllerDelegate protocol, we update the recipients property and the recipients text field. We could use a property observer to accomplish the same thing.
// MARK: -
// MARK: Recipients View Controller Delegate Methods
func controller(controller: RecipientsViewController, didSelectRecipients recipients: [MMUser]) {
// Update Recipients
self.recipients = recipients
var recipientsAsStrings: [String] = []
for recipient in recipients {
recipientsAsStrings.append(recipient.userName)
}
// Update Text Field
recipientsTextField.text = recipientsAsStrings.joinWithSeparator(", ")
}
Finally, we show the recipients view controller when the user taps the recipients text field. That's why the message view controller needs to be the delegate of the recipients text field.
// MARK: -
// MARK: Text Field Delegate Methods
func textFieldDidBeginEditing(textField: UITextField) {
performSegueWithIdentifier(SegueRecipients, sender: self)
}
10. Sending a Message
It's finally time to send the message. You'll be surprised by how simple this is with the MagnetMax library. We send a message in the sendMessage(_:) action.
@IBAction func sendMessage(sender: UIButton) {
guard let messageAsString = messageTextField.text else {
showAlertWithTitle("Message Required", message: "You need to enter a message.")
return
}
guard recipients.count > 0 else {
showAlertWithTitle("Recipients Required", message: "You need to have at least one recipient.")
return
}
let toRecipients = Set(recipients)
var contents: [String : String] = ["message" : messageAsString]
if let location = currentLocation {
let coordinate = location.coordinate
contents["location"] = "\(coordinate.latitude),\(coordinate.longitude)"
}
let message = MMXMessage(toRecipients: toRecipients, messageContent: contents)
message.sendWithSuccess({ (invalidUsernames) -> Void in
self.showAlertWithTitle("Message Sent", message: "Your message was successfully sent.")
}) { (error) -> Void in
print(error)
}
}
We first make sure that the required fields are filled out by the user. Location is optional. We send a message by creating an instance of the MMXMessage class, passing in the recipients and what we'd like to send. Note that Magnet Message supports rich messaging so you can add text as well as media.
To send the message, we invoke sendWithSuccess(_:failure:) on the MMXMessage object, passing in a success and failure closure. This message returns immediately and hands us the identifier of the message. We don't need that for this example. The implementation of showAlertWithTitle(_:message:) is similar to what we've seen before.
Note that you can only successfully send a message to another user if they are using the application. To test what we've built so far, you need to sign in on two devices or use the simulator.
11. Receiving Messages
Step 1: Start Observing
To receive messages from other users, we need to take care of two things in the MessageViewController. In the viewDidLoad(), we tell the MagnetMax library that we want to receive messages by invoking the start() class method.
In the viewDidLoad() method, we also add the view controller as an observer of notifications with name MMXDidReceiveMessageNotification. The MagnetMax library posts a notification with this name whenever it receives a message from the Magnet Message backend.
In didReceiveMessage(_:), we perform a number of checks using guard and then send a delivery confirmation to the Magnet Message backend to tell it that we received the message.
Even though this tutorial was fairly lengthy, I'm sure you agree that integrating Magnet Message didn't take much effort from our part. The heavy lifting is done by the MagnetMax library. Sending and receiving messages is only part of what the Magnet platform can do. Magnet provides support for media, public and private channels, and push notifications. You can read more about these features on Magnet's website.
On Android, the AsyncTask class is commonly used to perform operations on a background thread. In this video, I show you how an AsyncTask works and how you can use it in your projects.
A Bit More Detail
Learn more about Android development on Envato Tuts+:
This is part of a new series of quick video tutorials on Envato Tuts+. We’re aiming to introduce a range of subjects, all in 60 seconds–just enough to whet your appetite. Let us know in the comments what you thought of this video and what else you’d like to see explained in 60 seconds!
More and more mobile applications offer the ability to send messages to other users using the application. In many games, for example, you can chat with fellow gamers while chat applications allow you to talk to whomever you like. The possibilities are endless. Adding user chat to an application can be an important feature of your application.
Building a solution to enable users to chat with one another is a daunting task many developers prefer to sidestep. Fortunately, there's no need to reinvent the wheel. Magnet Message is an open source mobile messaging framework that is ideal for this use case. They offer iOS and Android support as well as a REST API. Getting started with Magnet Message is quick and easy thanks to their sandbox environment.
In this tutorial, you will learn how to integrate Magnet Message in an iOS application using Swift 2. You will learn how easy it is to set up Magnet Message in a project and send messages to other users of your application. Let's start by creating an account and setting up the sandbox.
Prerequisites
Even though the Magnet library for iOS is written in Objective-C, in this tutorial I'll be working with Xcode 7.1 and Swift 2.1. You can download Xcode 7.1 from Apple's developer website or from the App Store.
1. Creating a Magnet Account
Before we can start integrating Magnet into a mobile application, we need a Magnet account. A Magnet account gives you access to a sandbox environment for development as well as a number of sample applications to learn from. To follow along, navigate to Magnet's Developer website, click Try Itat the top, and sign up with an email address.
2. Creating a Sandbox Application
Your free Magnet account gives you access to a range of resources, including a sandbox you can use for development. Go to developer.magnet.com and go to the sandbox. You immediately notice that the sandbox already contains three applications. Each of these applications corresponds with one of the sample applications.
For this tutorial, we'll create a new application. Click the green plus button in the top right to create a new application and name it MessageMe.
When you click Save, the sandbox automatically opens the application and shows you a Getting Started guide. Click the Apple logo at the top to show the instructions for iOS.
You can skip the instructions, because I'll be guiding you through the setup process. There is one resource we need to get started, a property containing the configuration for the Magnet application. In the second step of the Build the App section, you can see a link to download MagnetMax.plist. Click the link to download the property list to your machine. We'll be needing it in a few moments.
If you open MagnetMax.plist, you'll see that it contains three key-value pairs, BaseURL, ClientID, ClientSecret. This information will be used by Magnet's library to talk to the Magnet Message backend.
3. Setting Up the Project
Launch Xcode 7.1 and choose the Single View Application template from the list of iOS > Application templates.
Name the application MessageMe, set Language to Swift, Devices to iPhone, and leave the checkboxes at the bottom unchecked. Tell Xcode where you'd like to save the project and click Create.
4. Setting Up CocoaPods
As I mentioned earlier, Magnet has developed an open source library for interacting with the Magnet Message backend. The easiest way to integrate the library in an Xcode project is through CocoaPods. Close the project you just created, open a Terminal window, and navigate to the root of the project. Create a Podfile for your project by executing the pod init command from the command line.
The Podfile lives at the root of your project. Open it in a text editor and replace its contents with the following.
source 'https://github.com/CocoaPods/Specs'
source 'https://github.com/magnetsystems/Specs'
platform :ios, '9.0'
use_frameworks!
target 'MessageMe' do
pod 'MagnetMax', '~> 2.0'
end
From the command line, execute the pod install command to install the dependencies specified in the Podfile. This will install the MagnetMax library that Magnet provides for interacting with the Magnet Message API. It will also create a workspace that we'll use from now on. After completing the installation process, open MessageMe.xcworkspace at the root of your project.
5. Setting Up Magnet
Step 1: Adding MagnetMax.plist
Setting up and configuring Magnet is very easy to do. Earlier in this tutorial, you downloaded MagnetMax.plist from Magnet's sandbox. Add this property list to the MessageMe project in the MessageMe workspace. Because MagnetMax.plistcontains sensitive data, I have excluded it from source control so you won't find it in the source files of this tutorial.
Step 2: Import MagnetMax Framework
Open AppDelegate.swift and add an import statement for the MagnetMax framework we installed through CocoaPods.
import UIKit
import MagnetMax
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
...
}
Step 3: Setting Up Magnet
In application(_:didFinishLaunchingWithOptions:), call setupWithConfiguration(_:) on the MagnetMax class, passing in the name of the configuration in MagnetMax.plist that we want to work with.
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Setting Up Magnet
let configurationFile = NSBundle.mainBundle().pathForResource("MagnetMax", ofType: "plist")
let configuration = MMPropertyListConfiguration(contentsOfFile: configurationFile!)
MagnetMax.configure(configuration!)
return true
}
Step 4: Build and Run
Build and run the target on a physical device or in the simulator to make sure everything is set up correctly. Make sure you've correctly followed the above steps if you run into problems.
6. Registering a User
Before a user can send messages to another user, she needs to create an account in our application. Magnet's account system is simple and transparent, and registering a user is straightforward to implement. In this section, we'll create a simple form to enable users to create an account or, if they already have an account, sign in to their account.
Step 1: Creating Classes
Before we create the user interface, we need to create two UIViewController subclasses, MessageViewController and SignInViewController. The first view controller will be in charge of sending messages. The second view controller will manage user registration as well as the sign in process.
Step 2: Creating User Interface
Open Main.storyboard, select the view controller that's already present, and choose Embed In > Navigation Controller from Xcode's Editor menu. Open the Object Library on the right and add a bar button item to the view controller's navigation bar. With the bar button item selected, set System Item to Compose in the Attributes Inspector.
Drag a view controller from the Object Library and set its class to MessageViewController in the Identity Inspector. Create a segue from the compose bar button item to the message view controller, setting Kind to Present Modally. Add a navigation bar at the top of the message view controller and add a bar button item on the left. In the Attributes Inspector, set System Item to Done.
Add two regular buttons to the message view controller and place them in a view. This makes it easier to hide both buttons when necessary. Set the titles of the button to Sign In and Create Account respectively.
Finally, add another view controller and set its class to SignInViewController in the Identity Inspector. Add a navigation bar at the top and add a bar button item on the left. Set System Item to Cancel in the Attributes Inspector. Add two text fields to the view controller, one for the user's username and one for the user's password. Don't forget to check Secure Text Entry in the Attributes Inspector for the password text field. Last but not least, add a button below the text fields and set its title to Sign In.
Create a segue from the Sign In button of the message view controller to the sign in view controller and set the segue's identifier to SegueSignIn. Repeat this step for the Create Account button and set the segue's identifier to SegueCreateAccount. Both segues should be of kind Show.
Step 3: Creating Outlets
Open MessageViewController.swift and declare an outlet for the view in which the Sign In and Create Account buttons are located. Note that I've also created an action for the Done button in the navigation bar. Don't forget to connect the outlet and the action in the storyboard. For ease of use, I've also declared two constants for the segue identifiers.
import UIKit
class MessageViewController: UIViewController {
let SegueSignIn = "SegueSignIn"
let SegueCreateAccount = "SegueCreateAccount"
@IBOutlet weak var buttonsView: UIView!
// MARK: -
// MARK: Actions
@IBAction func done(sender: UIBarButtonItem) {
dismissViewControllerAnimated(true, completion: nil)
}
}
Open SignInViewController.swift and declare three outlets and a helper variable as shown below. The helper variable will help us determine whether the user tapped the Sign In or the Create Account button. I've also created actions for the Sign In and Cancel buttons. Wire everything up in the storyboard before continuing.
import UIKit
class SignInViewController: UIViewController {
@IBOutlet weak var signInButton: UIButton!
@IBOutlet weak var usernameTextField: UITextField!
@IBOutlet weak var passwordTextField: UITextField!
var hasAccount = true
// MARK: -
// MARK: Actions
@IBAction func signIn(sender: UIButton) {
}
@IBAction func cancel(sender: UIBarButtonItem) {
}
}
Step 4: Delegate Protocol
When the user is successfully signed in, the message view controller needs to be notified. We can do this by creating a delegate protocol. At the top of SignInViewController.swift, I've added an import statement for the MagnetMax library and declared the SignInViewControllerDelegate protocol. The protocol contains one method, controller(_:didSignInWithUser:), which we'll invoke when the user is successfully signed in. We also need to declare a delegate property of type SignInViewControllerDelegate? to keep a reference to the delegate of the sign in view controller.
import UIKit
import MagnetMax
protocol SignInViewControllerDelegate {
func controller(controller: SignInViewController, didSignInWithUser user: MMUser)
}
class SignInViewController: UIViewController {
@IBOutlet weak var signInButton: UIButton!
@IBOutlet weak var usernameTextField: UITextField!
@IBOutlet weak var passwordTextField: UITextField!
var delegate: SignInViewControllerDelegate?
var hasAccount = true
...
}
Step 5: Signing In
The first thing we need to do is implement prepareForSegue(_:sender:) in the MessageViewController class. In this method, we check which button the user tapped and configure the SignInViewController instance accordingly by setting its hasAccount property.
// MARK: -
// MARK: Prepare for Segue
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == SegueSignIn {
let signInViewController = segue.destinationViewController as! SignInViewController
// Configure Sign In View Controller
signInViewController.hasAccount = true
signInViewController.delegate = self
} else if segue.identifier == SegueCreateAccount {
let signInViewController = segue.destinationViewController as! SignInViewController
// Configure Sign In View Controller
signInViewController.hasAccount = false
signInViewController.delegate = self
}
}
Note that we also set the delegate property of the sign in view controller. This means that the MessageViewController class needs to conform to the SignInViewControllerDelegate protocol as shown below. The implementation of the controller(_:didSignInWithUser:) method is empty for now. Don't forget to add an import statement for the MagnetMax library to avoid compiler warnings.
Let's focus now on the interesting part, the actions of the SignInViewController class. Before we implement the signIn(_:) and cancel(_:) actions, I'd like to implement the viewDidLoad() method to update the title of the Sign In button based on the value of the hasAccount property.
The signIn(_:) action is more interesting. In this action, we make sure the user has entered valid data, a username and a password, and then invoke a helper method based on the value of the hasAccount property.
@IBAction func signIn(sender: UIButton) {
guard let username = usernameTextField.text else {
showAlertWithTitle("Username Required", message: "Enter a valid username.")
return
}
guard let password = passwordTextField.text else {
showAlertWithTitle("Password Required", message: "Enter a valid password.")
return
}
guard !username.isEmpty && !password.isEmpty else {
showAlertWithTitle("Error", message: "Enter a valid username and password.")
return;
}
// Create Credential
let credential = NSURLCredential(user: username, password: password, persistence: .None)
if hasAccount {
signInWithCredential(credential)
} else {
createAccountWithCredential(credential)
}
}
The showAlertWithTitle(_:message:) method is a private convenience method for displaying an alert to the user.
The createAccountWithCredential(_:) method is another private helper method for registering the user. We start by creating an instance of the MMUser class. This class represents a user for the Magnet Message backend. We register the user by invoking registerWithCredential(_:success:failure:), passing in an NSURLCredential object and two closures.
private func createAccountWithCredential(credential: NSURLCredential) {
// Create User
let user = MMUser()
// Configure User
user.userName = credential.user
user.password = credential.password
// Register User
user.register({ (user) -> Void in
// Sign User In
self.signInWithCredential(credential)
}) { (error) -> Void in
print(error)
if error.code == 409 {
// Account Already Exists
self.signInWithCredential(credential)
} else {
// Notify User
self.showAlertWithTitle("Error", message: "We were unable to create an account. Please try again.")
}
}
}
If registration is successful, we immediately sign the user in by invoking signInWithCredential(_:). If something went wrong, we inspect the error that was passed to us. If the error's code is equal to 409, we know the user accidentally created an account with existing credentials. It's then acceptable to sign the user in instead of showing them an alert. If registrations fails, we show the user an alert.
The signInWithCredential(_:) method isn't too complicated. If logging in is successful, we initialize the message module by invoking initModule(_:success:failure:) on MagnetMax. We store the username in the user defaults database and notify the delegate, passing it the MMUser instance. We also dismiss the sign in view controller. If signing the user in is unsuccessful, we show the user an alert.
private func signInWithCredential(credential: NSURLCredential) {
MMUser.login(credential, success: { () -> Void in
MagnetMax.initModule(MMX.sharedInstance(), success: { () -> Void in
// Store Username in User Defaults
NSUserDefaults.standardUserDefaults().setObject(credential.user, forKey: "username")
// Notify Delegate
self.delegate?.controller(self, didSignInWithUser: MMUser.currentUser()!)
// Pop View Controller
self.dismissViewControllerAnimated(true, completion: nil)
}, failure: { (error) -> Void in
print(error)
// Notify User
self.showAlertWithTitle("Error", message: "We were unable to sign you in. Please make sure that the credentials you entered are correct.")
})
}) { (error) -> Void in
print(error)
// Notify User
self.showAlertWithTitle("Error", message: "We were unable to sign you in. Please make sure that the credentials you entered are correct.")
}
Run the application on a physical device or in the simulator to test what we've got so far. Note that the username cannot contain spaces. You should now be able to register as a user.
7. Creating the Form
Step 1: Creating User Interface
When the user is signed in, she should be able to send messages to other people using the application. Let's start by creating a form for composing the message. Before we revisit Main.storyboard, we're going to declare a few outlets and an action.
We start by declaring an outlet named messageView. We show this view when the user is signed in. At the same time, we hide buttonsView, which contains the Sign In and Create Account buttons.
The message view will contain a text field to enter recipients, a text field for the message itself, a switch to include the location of the user in the message, and a button to send the message. Also note that the MessageViewController class conforms to the UITextFieldDelegate protocol. I'll explain why that is later in this tutorial.
I've also added two actions. The sendMessage(_:) action will be triggered by tapping the Send Message button. The locationSwitchDidChange(_:) action will be invoked when the user flips the switch on.
import UIKit
import MagnetMax
class MessageViewController: UIViewController, UITextFieldDelegate, SignInViewControllerDelegate {
let SegueSignIn = "SegueSignIn"
let SegueCreateAccount = "SegueCreateAccount"
@IBOutlet weak var messageView: UIView!
@IBOutlet weak var buttonsView: UIView!
@IBOutlet weak var sendButton: UIButton!
@IBOutlet weak var locationSwitch: UISwitch!
@IBOutlet weak var messageTextField: UITextField!
@IBOutlet weak var recipientsTextField: UITextField!
...
@IBAction func sendMessage(sender: UIButton) {
}
@IBAction func locationSwitchDidChange(sender: UISwitch) {
}
...
}
The user interface of the message view controller changes quite a bit as you can see below. There are a few things to point out.
The message view controller should be set as the delegate of the recipients text field, the top text field.
The location switch should be set to off in the Attributes Inspector and the locationSwitchDidChange(_:) action needs to be wired up to the Value Changed event.
Wire the Touch Up Inside event to the sendMessage(_:) action we declared a moment ago in the MessageViewController class.
Step 2: Showing the Form
We only show the form when the user is signed in. We can easily do this through property observers. Start by creating a property, user, of type MMXUser? in the message view controller and add a didSet property observer to it. In the didSet property observer we invoke a helper method, updateView().
var user: MMUser? {
didSet {
updateView()
}
}
The implementation of the updateView() method is simple. We also implement a setupView() method, which we invoke in the viewDidLoad() method of the MessageViewController class.
The only thing left to make this work is update the user property of the message view controller in the controller(_:didSignInWithUser:) delegate method.
Run the application, sign in to your account, and make sure the form is shown in the message view controller.
8. Fetching the User's Location
Fetching the user's location is pretty simple, especially in iOS 9. Since iOS 9, the CLLocationManager class declares a method, requestLocation(), to ask the operating system for the location of the device. Let's see how this works.
Step 1: Updating Info.plist
To make this work, we first need to add an entry to the target's Info.plist. What we need to add is a message informing the user why we need access to their location. Open the target's Info.plist in Xcode and add a new row with key NSLocationWhenInUseUsageDescription and value MessageMe would like to use your current location.
Step 2: Declaring Properties
We also need to declare two properties in the MessageViewController class, a property for the location manager and a property for the current location. Both are optionals.
import UIKit
import MagnetMax
import CoreLocation
class MessageViewController: UIViewController, UITextFieldDelegate, CLLocationManagerDelegate, SignInViewControllerDelegate {
let SegueSignIn = "SegueSignIn"
let SegueCreateAccount = "SegueCreateAccount"
@IBOutlet weak var messageView: UIView!
@IBOutlet weak var buttonsView: UIView!
@IBOutlet weak var sendButton: UIButton!
@IBOutlet weak var locationSwitch: UISwitch!
@IBOutlet weak var messageTextField: UITextField!
@IBOutlet weak var recipientsTextField: UITextField!
var locationManager: CLLocationManager?
var currentLocation: CLLocation?
...
}
Note that we also add an import statement for the CoreLocation framework and we conform the MessageViewController class to the CLLocationManagerDelegate protocol.
Step 3: Requesting Permission
We then update the locationSwitchDidChange(_:) method, which is triggered when the value of the location switch changes. We invoke requestLocation() when the switch is on.
The requestLocation() method is a private helper method in which we set up the location manager. Before we ask the operating system for the location of the device, we verify that we have permission to do so. If we don't, we first ask for the user's permission by invoking requestWhenInUseAuthorization().
// MARK: -
// MARK: Helper Methods
private func requestLocation() {
if locationManager == nil {
// Initialize Location Manager
let locationManager = CLLocationManager()
// Configure Location Manager
locationManager.delegate = self
// Set Location Manager
self.locationManager = locationManager
}
if CLLocationManager.authorizationStatus() == .AuthorizedWhenInUse {
// Request Location
locationManager?.requestLocation()
} else {
// Ask User for Permission
locationManager?.requestWhenInUseAuthorization()
}
}
By requesting the user's permission, the user will be prompted for permission. After the user makes its decision, allowing or denying permission, a delegate method is invoked, locationManager(_:didChangeAuthorizationStatus:). In this method, we request the location if we are allowed to do so.
In locationManager(_:didUpdateLocations:), we store the location in the currentLocation property.
9. Selecting Recipients
Step 1: Creating RecipientsViewController Class
The final piece of the puzzle is selecting recipients to send the message to. Create a new class, RecipientsViewController, and add an import statement for the MagnetMax library. At the top, declare a protocol, RecipientsViewControllerDelegate, to inform the delegate which recipients the user selected. The delegate will be the message view controller. We also need a property to keep a reference to the delegate.
The user interface is pretty straightforward. Add a navigation bar at the top and add two bar button items to it, Cancel on the left and Done on the right. Add a table view to the view controller, set its dataSource and delegate outlets, and add a search bar at the top of the table view. It's important that the view controller is the delegate of the search bar.
Finally, create a manual segue from the message view controller to the recipients view controller. Set the segue's identifier to SegueRecipients and Kind to Show in the Attributes Inspector.
Step 3: Implementing Delegate Protocols
Open RecipientsViewController.swift and conform the RecipientsViewController controller to the UITableViewDataSource, UITableViewDelegate, and UISearchBarDelegate protocols.
Declare a constant for the reuse identifier of the table view cells and a property, users, that will act as the data source of the table view. The users property is of type [MMUser].
class RecipientsViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate {
let SearchCell = "SearchCell"
@IBOutlet weak var tableView: UITableView!
var delegate: RecipientsViewControllerDelegate?
var users: [MMUser] = []
...
}
In the viewDidLoad() method, register the UITableViewCell class for cell reuse.
The implementation of the UITableViewDataSource protocol is also straightforward. We display the username of each user that we're going to fetch from the Magnet Message backend.
More interesting is the implementation of the searchBar(_:textDidChange:) method. In this method, we invoke searchUsers(_:limit:offset:sort:success:failure:) on the MMUser class. We pass in the query, how many results we'd like to receive, an offset, a key to sort the results by, and two closures, one for success and one for failure.
When the user has made its selection and taps the Done button, we forward the selection of recipients to the delegate, the message view controller.
@IBAction func done(sender: UIBarButtonItem) {
// Fetch Selection
var selection: [MMUser] = []
if let indexPaths = tableView.indexPathsForSelectedRows {
for indexPath in indexPaths {
selection.append(users[indexPath.row])
}
}
// Notify Delegate
delegate?.controller(self, didSelectRecipients: selection)
// Dismiss View Controller
dismissViewControllerAnimated(true, completion: nil)
}
The only thing left to do is configuring the recipients view controller when the SegueRecipients segue is performed. We do this in the MessageViewController class. Update the prepareForSegue(_:sender:) as shown below.
This also means that we need to declare the SegueRecipients constant and conform the MessageViewController class to the RecipientsViewControllerDelegate protocol.
class MessageViewController: UIViewController, UITextFieldDelegate, CLLocationManagerDelegate, SignInViewControllerDelegate, RecipientsViewControllerDelegate {
let SegueSignIn = "SegueSignIn"
let SegueRecipients = "SegueRecipients"
let SegueCreateAccount = "SegueCreateAccount"
...
}
Step 5: Storing the Recipients
In the MessageViewController class, we temporarily store the recipients in a property, recipients, of type [MMUser].
var recipients: [MMUser] = []
In the controller(_:didSelectRecipients:) method of the RecipientsViewControllerDelegate protocol, we update the recipients property and the recipients text field. We could use a property observer to accomplish the same thing.
// MARK: -
// MARK: Recipients View Controller Delegate Methods
func controller(controller: RecipientsViewController, didSelectRecipients recipients: [MMUser]) {
// Update Recipients
self.recipients = recipients
var recipientsAsStrings: [String] = []
for recipient in recipients {
recipientsAsStrings.append(recipient.userName)
}
// Update Text Field
recipientsTextField.text = recipientsAsStrings.joinWithSeparator(", ")
}
Finally, we show the recipients view controller when the user taps the recipients text field. That's why the message view controller needs to be the delegate of the recipients text field.
// MARK: -
// MARK: Text Field Delegate Methods
func textFieldDidBeginEditing(textField: UITextField) {
performSegueWithIdentifier(SegueRecipients, sender: self)
}
10. Sending a Message
It's finally time to send the message. You'll be surprised by how simple this is with the MagnetMax library. We send a message in the sendMessage(_:) action.
@IBAction func sendMessage(sender: UIButton) {
guard let messageAsString = messageTextField.text else {
showAlertWithTitle("Message Required", message: "You need to enter a message.")
return
}
guard recipients.count > 0 else {
showAlertWithTitle("Recipients Required", message: "You need to have at least one recipient.")
return
}
let toRecipients = Set(recipients)
var contents: [String : String] = ["message" : messageAsString]
if let location = currentLocation {
let coordinate = location.coordinate
contents["location"] = "\(coordinate.latitude),\(coordinate.longitude)"
}
let message = MMXMessage(toRecipients: toRecipients, messageContent: contents)
message.sendWithSuccess({ (invalidUsernames) -> Void in
self.showAlertWithTitle("Message Sent", message: "Your message was successfully sent.")
}) { (error) -> Void in
print(error)
}
}
We first make sure that the required fields are filled out by the user. Location is optional. We send a message by creating an instance of the MMXMessage class, passing in the recipients and what we'd like to send. Note that Magnet Message supports rich messaging so you can add text as well as media.
To send the message, we invoke sendWithSuccess(_:failure:) on the MMXMessage object, passing in a success and failure closure. This message returns immediately and hands us the identifier of the message. We don't need that for this example. The implementation of showAlertWithTitle(_:message:) is similar to what we've seen before.
Note that you can only successfully send a message to another user if they are using the application. To test what we've built so far, you need to sign in on two devices or use the simulator.
11. Receiving Messages
Step 1: Start Observing
To receive messages from other users, we need to take care of two things in the MessageViewController. In the viewDidLoad(), we tell the MagnetMax library that we want to receive messages by invoking the start() class method.
In the viewDidLoad() method, we also add the view controller as an observer of notifications with name MMXDidReceiveMessageNotification. The MagnetMax library posts a notification with this name whenever it receives a message from the Magnet Message backend.
In didReceiveMessage(_:), we perform a number of checks using guard and then send a delivery confirmation to the Magnet Message backend to tell it that we received the message.
Even though this tutorial was fairly lengthy, I'm sure you agree that integrating Magnet Message didn't take much effort from our part. The heavy lifting is done by the MagnetMax library. Sending and receiving messages is only part of what the Magnet platform can do. Magnet provides support for media, public and private channels, and push notifications. You can read more about these features on Magnet's website.
Apple introduced the Swift programming language during its annual developer conference in 2014, much to he surprise of the developer community. The company is serious about Swift, it isn't an experiment. The goal for Swift is to power the next generation of applications for Apple's platforms.
Prerequisites
Programming
It isn't possible to cover the basics of programming and learn Swift in one or two articles. I am therefore assuming that you already have some programming experience. Ruby, PHP, or JavaScript are good starting points for learning Swift. If you come from a web development background, then you shouldn't have problems learning the basics of Swift by reading the next two articles.
Swift
In the next two articles, I show you the power of playgrounds, a feature introduced in Xcode 6. We also cover the basics of the Swift programming language, such as variables, constants, and data types, including sets, arrays, and dictionaries.
You also learn the basics of classes and structures. In the next article, we zoom in on closures, functions, protocols, and access control. That should give you enough understanding of the language to complete the rest of this series.
Objective-C
Strictly speaking, C and Objective-C aren't required if you are interested in developing for the iOS platform. That said, most of the frameworks we will use to develop iOS applications are written in C and Objective-C. This means that I'll occasionally talk about C and Objective-C. Don't worry, though, I'll make sure you understand whatever is essential to keep you on track to reach your goal, become an iOS developer.
Xcode and Swift
Throughout this series, I will be using Xcode 7.1 and Swift 2.1. If you are using an older version of Xcode, then keep in mind that you won't be working with Swift 2.1. Swift continues to change at a rapid pace and the syntax evolves with every iteration of the language. I therefore recommend using Xcode 7.1, which includes Swift 2.1.
1. Playgrounds
In 2014, Apple introduced playgrounds as part of Xcode 6. Playgrounds are great for learning the Swift programming language. With playgrounds, you can focus on the code you're writing instead of messing with project settings, files, and folders.
Let's create a playground to start learning the basics of Swift. Fire up Xcode 7.1 and choose New > Playground... from Xcode's File menu. Playgrounds support OS X, iOS, and tvOS. Set Platform to iOS and name the playground Swift in a Nutshell.
Tell Xcode where you want to save the playground and click Create. At first glance, a playground appears to be a simple file with a .playground extension, but it's actually a folder with a handful of files. Fortunately, that's not something we need to worry about. A playground is much easier to deal with than an Xcode project with dozens of files and folders.
The user interface of a playground is clean and simple. You can see the code editor on the left and the output on the right. Xcode has already populated the playground with three lines of code. The first line should look familiar if you've read the previous tutorial.
//: Playground - noun: a place where people can play
The line starts with two forward slashes, //, indicating that this line is a comment and ignored by the compiler. Comments that span multiple lines start with /* and end with */.
/*
This is a longer
comment spanning
multiple lines.
*/
Xcode also added an import statement for the UIKit framework. UIKit is the most important framework for iOS development. It defines the building blocks iOS applications are built with. In Swift, importing a framework is as simple as using the import keyword followed by the name of the framework, UIKit.
import UIKit
The last line may remind some of you of JavaScript. We use the var keyword to declare a variable, str, and assign a value to it, "Hello, playground". This example immediately shows a key feature of Swift, type inference.
var str = "Hello, playground"
The above example is a bit misleading. You may think that Swift is a weakly typed language, but nothing could be further from the truth. The str variable is of type String. Swift is smart enough to infer the type of str by looking at the value we assign to it.
The following example is equivalent. In this example, we explicitly specify the type of the str variable. The colon following the name of the variable could be read as is of type.
var str: String = "Hello, playground"
2. Variables and Constants
Swift also defines the let keyword. This keyword is used to declare a constant. The Swift programming language encourages the use of constants whenever possible. If the value of a variable doesn't change during its lifetime, it should be a constant. As the name implies, once a constant is given a value, it cannot be changed. This is illustrated in the following example.
In the above example, we declare a constant message and assign it a value. A few lines down, we assign a new value to the message constant. Because we attempt to change the value of message, the compiler throws an error. Fortunately, the compiler makes a suggestion to fix the issue, turning the message constant into a variable.
3. Data Types
Swift defines a wide range of data types, but let's take a look at some of the most common data types you'll come across.
Booleans
Let's start with a simple type, Bool. Booleans in Swift are just as simple and easy to use as they are in other languages. The following example is probably as simple as it gets in Swift.
let myBool = true
var notTrue = false
notTrue = true
Numbers
Numbers are represented by Int, UInt, Float, or Double. There are other data types for storing number values, but these are the most common ones. These data types are similar to the ones you find in other programming languages.
Because Swift is a strongly typed language, you need to deal with type conversions from time to time. For example, it's not possible to multiply an Int and a Float. Take a look at the following example to better understand the problem.
At first, this may seem like a major shortcoming of the Swift language. The truth is that this behavior is inherent to most strongly typed languages. Fortunately, the solution is simple as you can see below.
Even though it may seem as if we are casting a to a Float, that's not what's happening. We are creating or initializing a Float using the value stored in a.
There are two ways to create a variable or constant, literal syntax and initializer syntax. The constants a and b were created using literal syntax. The str variable we discussed earlier is another example of literal syntax.
To create a Float from the value stored in a, we use initializer syntax. We create the Float by using the type's name, Float, followed by two parentheses, passing in a as a parameter.
Strings
We've already encountered some strings in this tutorial. A string is nothing more than a sequence of characters. In fact, it's possible to access the collection of characters as shown in the example below.
let city = "Brussels"
let chars = city.characters
In the above example, we use a string literal. The next example illustrates how to use the initializer of the String type. The syntax is identical to what we saw in one of the previous examples about numbers and type conversion.
let country = String("Belgium")
Collections
The Swift standard library defines three common collection types, Array, Dictionary, and Set. These collection types require little explanation if you're familiar with Objective-C or any other programming language. In some languages, dictionaries are known as hashes and arrays are known as lists. The idea, however, is the same.
let myArray = [1, 2, 3, 4, 5]
let myDictionary = ["One": 1, "Two": 2, "Three": 3]
let mySet = Set(["One", "Two", "Three", "Four", "Five"])
The array and dictionary are initialized using literal syntax. Because the Set type doesn't have a literal syntax, we use the initializer syntax to create the mySet constant.
I already mentioned that Swift is a strongly typed language and this also has consequences for collection types. The following example illustrates this. We start by creating a variable arr1 of type [Int]. This means that arr1 can only contain values of type Int.
The second and third statement confirm this. Appending an integer works fine, but appending a string results in a compiler error. The compiler attempts to convert "Two" to an Int, but is unable to do so. The result is an error.
The following example will make things even more confusing. Why isn't the compiler complaining about the array containing values of different types? The reason may surprise you. The arr2 constant is of type [AnyObject].
let arr2 = [1, 2, 3, "Four", "Five"]
Any and AnyObject
The Swift standard library defines two special types, Any and AnyObject. The Any type can represent any type while the AnyObject type can represent any class or structure. If you're confused, then that's perfectly normal. Swift was designed to be strongly typed and it seems as if Any and AnyObject undermine Swift's type safety.
The reason for introducing Any and AnyObject is primarily for compatibility reasons. I already mentioned that most of the frameworks used for Cocoa development are written in C and Objective-C. Objective-C defines the id type, which represents any object. To make sure that Swift and the Cocoa frameworks can work together, the Swift standard library introduced the Any and AnyObject types. We'll learn more about this when we start working with the Cocoa frameworks.
4. Classes and Structures
Classes
If you're familiar with object-oriented programming, then you should already be familiar with classes. Classes are pretty ordinary in Swift. Take a look at the following example in which we define a class, Boat, with two properties, speed and lifeboats, and a method, deployLifeboats().
class Boat {
var speed: Float = 0
var lifeboats: Int = 2
func deployLifeboats() {
// ...
}
}
Initializing and modifying an instance of the Boat class is straightforward as you can see below. Calling a method on an instance isn't magical either. The basics of Swift classes are easy to understand. Right?
var boat = Boat()
boat.speed = 10.5
boat.lifeboats++
boat.deployLifeboats()
Structures
Let's now create a structure that looks surprisingly similar to the Boat class and find out what sets classes and structures apart in Swift.
struct Ship {
var speed: Float = 0
var lifeboats: Int = 2
func deployLifeboats() {
// ...
}
}
The following example reveals the most important difference between Swift classes and structures.
This example illustrates that classes are passed by reference while structures are passed by value. What does that mean? We initialized a Boat instance, assigned it to boat1, and set its speed property to 11.0. We assigned boat1 to boat2. This means that boat2 has a reference to boat1. Both boat1 and boat2 point to the same Boat instance. The result is that setting the speed property of boat2 also modifies the speed property of boat1.
This isn't true for structures. We repeat the same steps using the Ship structure. The end result is different though. By assigning ship1 to ship2, the value of ship1 is copied and stored in ship2. This means ship1 and ship2 point to different objects, different instances of the Ship structure. This is a very important concept to grasp so make sure you understand this before continueing.
Consequences
You've already been introduced to the common data types defined by the Swift standard library. What I didn't mention in that discussion is that every Swift data type we discussed so far is a structure.
Every collection type in Swift, for example, is a structure. Every number type is a structure. This is important to know and understand, especially if you come from a language that passes some of these types by reference, such as Ruby and Objective-C.
More Differences
There are a number of other differences that set classes and structures apart in Swift. Classes support inheritance while structures don't. In the following example, we define a class Speedboat that inherits from the Boat class. The Boat class is the parent class or superclass of Speedboat.
class Speedboat: Boat {
}
var speedboat = Speedboat()
speedboat.speed = 100.0
speedboat.lifeboats = 0
speedboat.deployLifeboats()
Because Boat is the parent class of Speedboat, Speedboat inherits the properties and methods defined in the Boat class. The example illustrates this. Even though the implementation of the Speedboat class is empty, the Speedboat instance, myBoat, has speed and lifeboats properties as well as a deployLifeboats() method.
A more subtle difference that sets classes and structures apart is type checking at runtime. You can check the type of a class instance at runtime while this isn't possible for structure instances.
5. Optionals
Optionals are an integral part of the Swift programming language. Let's find out what optionals are and why they are so important. A variable must be initialized before it can be used. Take a look at the following example to understand what this means.
var str: String
str.isEmpty
If you're used to working with strings in other programming languages, then you may be surprised that the compiler throws an error. Let's see what that error tells us.
In many programming languages, variables have an initial default value. In Objective-C, for example, the string in the following code snippet is equal to nil.
NSString *newString;
What Is an Optional?
Swift uses optionals to encapsulate an important concept, a variable or constant has a value or it hasn't. It's that simple in Swift. To declare a variable or constant as optional, we append a question mark to the type of the variable or constant.
var str: String?
The variable str is no longer of type String. It is now of type optionalString. This is important to understand. The consequence is that we can no longer directly interact with the value of str. The value is safely stored in the optional and we need to ask the optional for the value it encapsulates.
Forced Unwrapping
One way to access the value of an optional is by forced unwrapping the optional. We can access the value of str by appending a ! to the variable's name.
var str: String?
str = "Test"
println(str!)
It's important that you are sure that the optional contains a value when you force unwrap it. If you force unwrap an optional that doesn't have a value, Swift throws an error and your application crashes.
Optional Binding
There is a safer way to access the value of an optional. The following example shows how we can safely access the value stored in str, which is of type String?.
var str: String?
if str != nil {
println(str!)
} else {
println("str has no value")
}
We first check if str is equal to nil before we print its contents. In this example, str doesn't have a value. This means it won't be forced unwrapped by accident.
There's a more elegant approach known as optional binding. In the following example, we assign the value stored in the optional to a temporary constant. The value of the optional str is bound to the constant strConst and made available in the if clause of the if statement. This approach also works for while statements.
var str: String?
str = "Test"
if let strConst = str {
println(strConst)
} else {
println("str has no value")
}
What Is nil?
If you're coming from a language like Objective-C, then you most certainly know what nil is. In Objective-C, nil is a pointer to an object that doesn't exist. Swift defines nil a bit differently and it's important that you understand the difference.
In Swift, nil means the absence of a value, any value. While nil is only applicable to objects in Objective-C, in Swift nil can be used for any type.
Did You Miss the Semicolon?
Have you noticed that we haven't used any semicolons in the examples of this tutorial? In Swift, there's no need to use semicolons, because the compiler is smart enough to understand when one statement ends and another one begins. If you really miss using semicolons, then it's fine to add them. Keep in mind, though, that the language guide recommends to omit semicolons.
Conclusion
Even though we've only scratched the surface in this tutorial, you now have a basic understanding of the Swift programming language. In the next tutorial, we'll explore another key component of the language, closures and functions. We'll also discuss protocols and access control.
If you have any questions or comments, you can leave them in the comments below or reach out to me on Twitter.
Apple introduced the Swift programming language during its annual developer conference in 2014, much to he surprise of the developer community. The company is serious about Swift, it isn't an experiment. The goal for Swift is to power the next generation of applications for Apple's platforms.
Prerequisites
Programming
It isn't possible to cover the basics of programming and learn Swift in one or two articles. I am therefore assuming that you already have some programming experience. Ruby, PHP, or JavaScript are good starting points for learning Swift. If you come from a web development background, then you shouldn't have problems learning the basics of Swift by reading the next two articles.
Swift
In the next two articles, I show you the power of playgrounds, a feature introduced in Xcode 6. We also cover the basics of the Swift programming language, such as variables, constants, and data types, including sets, arrays, and dictionaries.
You also learn the basics of classes and structures. In the next article, we zoom in on closures, functions, protocols, and access control. That should give you enough understanding of the language to complete the rest of this series.
Objective-C
Strictly speaking, C and Objective-C aren't required if you are interested in developing for the iOS platform. That said, most of the frameworks we will use to develop iOS applications are written in C and Objective-C. This means that I'll occasionally talk about C and Objective-C. Don't worry, though, I'll make sure you understand whatever is essential to keep you on track to reach your goal, become an iOS developer.
Xcode and Swift
Throughout this series, I will be using Xcode 7.1 and Swift 2.1. If you are using an older version of Xcode, then keep in mind that you won't be working with Swift 2.1. Swift continues to change at a rapid pace and the syntax evolves with every iteration of the language. I therefore recommend using Xcode 7.1, which includes Swift 2.1.
1. Playgrounds
In 2014, Apple introduced playgrounds as part of Xcode 6. Playgrounds are great for learning the Swift programming language. With playgrounds, you can focus on the code you're writing instead of messing with project settings, files, and folders.
Let's create a playground to start learning the basics of Swift. Fire up Xcode 7.1 and choose New > Playground... from Xcode's File menu. Playgrounds support OS X, iOS, and tvOS. Set Platform to iOS and name the playground Swift in a Nutshell.
Tell Xcode where you want to save the playground and click Create. At first glance, a playground appears to be a simple file with a .playground extension, but it's actually a folder with a handful of files. Fortunately, that's not something we need to worry about. A playground is much easier to deal with than an Xcode project with dozens of files and folders.
The user interface of a playground is clean and simple. You can see the code editor on the left and the output on the right. Xcode has already populated the playground with three lines of code. The first line should look familiar if you've read the previous tutorial.
//: Playground - noun: a place where people can play
The line starts with two forward slashes, //, indicating that this line is a comment and ignored by the compiler. Comments that span multiple lines start with /* and end with */.
/*
This is a longer
comment spanning
multiple lines.
*/
Xcode also added an import statement for the UIKit framework. UIKit is the most important framework for iOS development. It defines the building blocks iOS applications are built with. In Swift, importing a framework is as simple as using the import keyword followed by the name of the framework, UIKit.
import UIKit
The last line may remind some of you of JavaScript. We use the var keyword to declare a variable, str, and assign a value to it, "Hello, playground". This example immediately shows a key feature of Swift, type inference.
var str = "Hello, playground"
The above example is a bit misleading. You may think that Swift is a weakly typed language, but nothing could be further from the truth. The str variable is of type String. Swift is smart enough to infer the type of str by looking at the value we assign to it.
The following example is equivalent. In this example, we explicitly specify the type of the str variable. The colon following the name of the variable could be read as is of type.
var str: String = "Hello, playground"
2. Variables and Constants
Swift also defines the let keyword. This keyword is used to declare a constant. The Swift programming language encourages the use of constants whenever possible. If the value of a variable doesn't change during its lifetime, it should be a constant. As the name implies, once a constant is given a value, it cannot be changed. This is illustrated in the following example.
In the above example, we declare a constant message and assign it a value. A few lines down, we assign a new value to the message constant. Because we attempt to change the value of message, the compiler throws an error. Fortunately, the compiler makes a suggestion to fix the issue, turning the message constant into a variable.
3. Data Types
Swift defines a wide range of data types, but let's take a look at some of the most common data types you'll come across.
Booleans
Let's start with a simple type, Bool. Booleans in Swift are just as simple and easy to use as they are in other languages. The following example is probably as simple as it gets in Swift.
let myBool = true
var notTrue = false
notTrue = true
Numbers
Numbers are represented by Int, UInt, Float, or Double. There are other data types for storing number values, but these are the most common ones. These data types are similar to the ones you find in other programming languages.
Because Swift is a strongly typed language, you need to deal with type conversions from time to time. For example, it's not possible to multiply an Int and a Float. Take a look at the following example to better understand the problem.
At first, this may seem like a major shortcoming of the Swift language. The truth is that this behavior is inherent to most strongly typed languages. Fortunately, the solution is simple as you can see below.
Even though it may seem as if we are casting a to a Float, that's not what's happening. We are creating or initializing a Float using the value stored in a.
There are two ways to create a variable or constant, literal syntax and initializer syntax. The constants a and b were created using literal syntax. The str variable we discussed earlier is another example of literal syntax.
To create a Float from the value stored in a, we use initializer syntax. We create the Float by using the type's name, Float, followed by two parentheses, passing in a as a parameter.
Strings
We've already encountered some strings in this tutorial. A string is nothing more than a sequence of characters. In fact, it's possible to access the collection of characters as shown in the example below.
let city = "Brussels"
let chars = city.characters
In the above example, we use a string literal. The next example illustrates how to use the initializer of the String type. The syntax is identical to what we saw in one of the previous examples about numbers and type conversion.
let country = String("Belgium")
Collections
The Swift standard library defines three common collection types, Array, Dictionary, and Set. These collection types require little explanation if you're familiar with Objective-C or any other programming language. In some languages, dictionaries are known as hashes and arrays are known as lists. The idea, however, is the same.
let myArray = [1, 2, 3, 4, 5]
let myDictionary = ["One": 1, "Two": 2, "Three": 3]
let mySet = Set(["One", "Two", "Three", "Four", "Five"])
The array and dictionary are initialized using literal syntax. Because the Set type doesn't have a literal syntax, we use the initializer syntax to create the mySet constant.
I already mentioned that Swift is a strongly typed language and this also has consequences for collection types. The following example illustrates this. We start by creating a variable arr1 of type [Int]. This means that arr1 can only contain values of type Int.
The second and third statement confirm this. Appending an integer works fine, but appending a string results in a compiler error. The compiler attempts to convert "Two" to an Int, but is unable to do so. The result is an error.
The following example will make things even more confusing. Why isn't the compiler complaining about the array containing values of different types? The reason may surprise you. The arr2 constant is of type [AnyObject].
let arr2 = [1, 2, 3, "Four", "Five"]
Any and AnyObject
The Swift standard library defines two special types, Any and AnyObject. The Any type can represent any type while the AnyObject type can represent any class or structure. If you're confused, then that's perfectly normal. Swift was designed to be strongly typed and it seems as if Any and AnyObject undermine Swift's type safety.
The reason for introducing Any and AnyObject is primarily for compatibility reasons. I already mentioned that most of the frameworks used for Cocoa development are written in C and Objective-C. Objective-C defines the id type, which represents any object. To make sure that Swift and the Cocoa frameworks can work together, the Swift standard library introduced the Any and AnyObject types. We'll learn more about this when we start working with the Cocoa frameworks.
4. Classes and Structures
Classes
If you're familiar with object-oriented programming, then you should already be familiar with classes. Classes are pretty ordinary in Swift. Take a look at the following example in which we define a class, Boat, with two properties, speed and lifeboats, and a method, deployLifeboats().
class Boat {
var speed: Float = 0
var lifeboats: Int = 2
func deployLifeboats() {
// ...
}
}
Initializing and modifying an instance of the Boat class is straightforward as you can see below. Calling a method on an instance isn't magical either. The basics of Swift classes are easy to understand. Right?
var boat = Boat()
boat.speed = 10.5
boat.lifeboats++
boat.deployLifeboats()
Structures
Let's now create a structure that looks surprisingly similar to the Boat class and find out what sets classes and structures apart in Swift.
struct Ship {
var speed: Float = 0
var lifeboats: Int = 2
func deployLifeboats() {
// ...
}
}
The following example reveals the most important difference between Swift classes and structures.
This example illustrates that classes are passed by reference while structures are passed by value. What does that mean? We initialized a Boat instance, assigned it to boat1, and set its speed property to 11.0. We assigned boat1 to boat2. This means that boat2 has a reference to boat1. Both boat1 and boat2 point to the same Boat instance. The result is that setting the speed property of boat2 also modifies the speed property of boat1.
This isn't true for structures. We repeat the same steps using the Ship structure. The end result is different though. By assigning ship1 to ship2, the value of ship1 is copied and stored in ship2. This means ship1 and ship2 point to different objects, different instances of the Ship structure. This is a very important concept to grasp so make sure you understand this before continueing.
Consequences
You've already been introduced to the common data types defined by the Swift standard library. What I didn't mention in that discussion is that every Swift data type we discussed so far is a structure.
Every collection type in Swift, for example, is a structure. Every number type is a structure. This is important to know and understand, especially if you come from a language that passes some of these types by reference, such as Ruby and Objective-C.
More Differences
There are a number of other differences that set classes and structures apart in Swift. Classes support inheritance while structures don't. In the following example, we define a class Speedboat that inherits from the Boat class. The Boat class is the parent class or superclass of Speedboat.
class Speedboat: Boat {
}
var speedboat = Speedboat()
speedboat.speed = 100.0
speedboat.lifeboats = 0
speedboat.deployLifeboats()
Because Boat is the parent class of Speedboat, Speedboat inherits the properties and methods defined in the Boat class. The example illustrates this. Even though the implementation of the Speedboat class is empty, the Speedboat instance, myBoat, has speed and lifeboats properties as well as a deployLifeboats() method.
A more subtle difference that sets classes and structures apart is type checking at runtime. You can check the type of a class instance at runtime while this isn't possible for structure instances.
5. Optionals
Optionals are an integral part of the Swift programming language. Let's find out what optionals are and why they are so important. A variable must be initialized before it can be used. Take a look at the following example to understand what this means.
var str: String
str.isEmpty
If you're used to working with strings in other programming languages, then you may be surprised that the compiler throws an error. Let's see what that error tells us.
In many programming languages, variables have an initial default value. In Objective-C, for example, the string in the following code snippet is equal to nil.
NSString *newString;
What Is an Optional?
Swift uses optionals to encapsulate an important concept, a variable or constant has a value or it hasn't. It's that simple in Swift. To declare a variable or constant as optional, we append a question mark to the type of the variable or constant.
var str: String?
The variable str is no longer of type String. It is now of type optionalString. This is important to understand. The consequence is that we can no longer directly interact with the value of str. The value is safely stored in the optional and we need to ask the optional for the value it encapsulates.
Forced Unwrapping
One way to access the value of an optional is by forced unwrapping the optional. We can access the value of str by appending a ! to the variable's name.
var str: String?
str = "Test"
println(str!)
It's important that you are sure that the optional contains a value when you force unwrap it. If you force unwrap an optional that doesn't have a value, Swift throws an error and your application crashes.
Optional Binding
There is a safer way to access the value of an optional. The following example shows how we can safely access the value stored in str, which is of type String?.
var str: String?
if str != nil {
println(str!)
} else {
println("str has no value")
}
We first check if str is equal to nil before we print its contents. In this example, str doesn't have a value. This means it won't be forced unwrapped by accident.
There's a more elegant approach known as optional binding. In the following example, we assign the value stored in the optional to a temporary constant. The value of the optional str is bound to the constant strConst and made available in the if clause of the if statement. This approach also works for while statements.
var str: String?
str = "Test"
if let strConst = str {
println(strConst)
} else {
println("str has no value")
}
What Is nil?
If you're coming from a language like Objective-C, then you most certainly know what nil is. In Objective-C, nil is a pointer to an object that doesn't exist. Swift defines nil a bit differently and it's important that you understand the difference.
In Swift, nil means the absence of a value, any value. While nil is only applicable to objects in Objective-C, in Swift nil can be used for any type.
Did You Miss the Semicolon?
Have you noticed that we haven't used any semicolons in the examples of this tutorial? In Swift, there's no need to use semicolons, because the compiler is smart enough to understand when one statement ends and another one begins. If you really miss using semicolons, then it's fine to add them. Keep in mind, though, that the language guide recommends to omit semicolons.
Conclusion
Even though we've only scratched the surface in this tutorial, you now have a basic understanding of the Swift programming language. In the next tutorial, we'll explore another key component of the language, closures and functions. We'll also discuss protocols and access control.
If you have any questions or comments, you can leave them in the comments below or reach out to me on Twitter.
While this tutorial focuses primarily on functions and closures, we take a brief detour at the end to explore protocols and access control. We'll be working with protocols later in this series so it's important to become familiar with them early on.
A few months ago, I wrote a series on the Swift programming language in which I took a close look at functions and closures. This article summarizes what I wrote in these tutorials. If you want more information about functions and closures, I recommend reading the articles of that series:
Before we dive into the topic of functions and closures, it's time to fire up Xcode and create a new playground. Ready? Let's write some code.
1. Functions
What Is a Function?
A function is nothing more than a block of code that can be executed when it's needed. I'd like to start with an example to discuss the basic anatomy of a function in Swift. Add the following function definition to your playground.
func printHelloWorld() {
print("Hello World!")
}
A function begins with the func keyword and is followed by the name of the function, printHelloWorld in the above example. As in many other languages, the name of the function is followed by a pair of parentheses that contain the function's parameters, the function's input.
The body of the function is wrapped in a pair of curly braces. The body of the printHelloWorld() function contains one statement in which we print the string "Hello World!" in the standard output. This is what a basic function looks like in Swift. To invoke the function, we type its name followed by a pair of parentheses.
printHelloWorld()
Parameters
Let's make the above example a bit more complex by adding parameters to the function definition. By adding parameters, we provide the function with input values it can use in its body. In the following example, we define the printMessage(_:) function, which accepts one parameter, message, of type String.
A function can accept multiple parameters or input values. The parameters are wrapped by the parentheses that follow the function's name. The name of the parameter is followed by a colon and its type. As you remember, this is very similar to declaring a variable or constant. It simply says that the message parameter is of typeString.
Invoking the function is similar to what we saw earlier. The difference is that we pass in an argument.
printMessage("Hello World!")
The following example looks similar. The only difference is that the function defines two parameters, message of type String and times of type Int.
func printMessage(message: String, times: Int) {
for i in 0..<times {
print("\(i) \(message)")
}
}
While the name of the function is identical to that of the original printMessage(_:) function, the function's type is different. It's important that you understand this difference. Each function has a type, consisting of the parameter types and the return type. We'll explore return types in a moment. Functions can have the same name as long as their type is different as shown by the previous two function definitions.
The type of the first function is (String) -> () while the type of the second function is(String, Int) -> (). The name of both functions is the same. Don't worry about the -> symbol. Its meaning will become clear in a few moments when we discuss return types.
The second printMessage(_:times:) function defines two parameters, message of type String and times of type Int. This function signature illustrates one of the features Swift has adopted from Objective-C, readable function and method names.
printMessage("Hello World!", times: 3)
Return Types
The functions we've seen so far don't return anything to us when we invoke them. Let's create a function that formats a date. The function takes two arguments, a date of type NSDate and a format string of type String. Because the NSDate and NSDateFormatter classes are defined in the Foundation framework, we need to import Foundation at the top of the playground.
import Foundation
func formatDate(date: NSDate, format: String = "YY/MM/dd") -> String {
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = format
return dateFormatter.stringFromDate(date)
}
There are a few things that require some explanation. The -> symbol indicates that the function returns a value. The type of the value is defined after the -> symbol, String.
The function accepts two arguments and the second argument has a default value. This is indicated by the assignment following the type of the second argument. The default value of format is "YY/MM/dd". This means that we can invoke the function with only one argument. Xcode's autocompletion illustrates this.
If a function doesn't have a return type, the -> symbol is omitted. That's why the printHelloWorld() function doesn't have a -> symbol in its method definition.
Local and External Parameter Names
Earlier in this tutorial, we defined the printMessage(_:) function. Even though we've given the parameter a name, message, we don't use that name when we call the function. Instead, we only pass in the value for the message parameter.
The name we define in the function's definition is a local parameter name. The value of the parameter can only be referenced by this name in the body of the function. But function parameters are a bit more flexible than that.
Objective-C is known for its long method names. While this may look clunky and inelegant to outsiders, it makes methods easy to understand and, if chosen well, very descriptive. If you think you lost this benefit when switching to Swift, then you're in for a surprise.
When a function accepts several parameters, it isn't always obvious which argument corresponds to which parameter. Take a look at the following example to better understand the problem.
func power(a: Int, b: Int) -> Int {
var result = a
for _ in 1..<b {
result = result * a
}
return result
}
power(2, 3)
The power(_:b:) function raises the value of a by the exponent b. Both parameters are of type Int. While most people will intuitively pass the base value as the first argument and the exponent as the second argument, this isn't clear from the function's type, name, or signature.
To avoid confusion, we can give the parameters of a function external names. We can then use these external names when the function is called to unambiguously indicate which argument corresponds to which parameter. Take a look at the updated example below.
func power(base a: Int, exponent b: Int) -> Int {
var result = a
for _ in 1..<b {
result = result * a
}
return result
}
Note that the function's body hasn't changed, because the local names haven't been changed. However, when we invoke the updated function, the difference is clear and the result much less confusing.
power(base: 2, exponent: 3)
Even though the types of both functions are the same, (Int, Int) -> Int, the functions are different. In other words, the second function isn't a redeclaration of the first function. The syntax to invoke the second function may remind some of you of Objective-C. Not only are the arguments clearly described, the combination of function and parameter names describe the purpose of the function.
In Swift, the first parameter has, by default, no external parameter name. That's why the signature of the printMessage(_:) function includes a _ for the first parameter. If we want to define an external parameter name for the first parameter, then the method definition would look a bit different.
The examples we've seen so far are known as global functions, because they're defined at a global scope. Functions can also be nested. Nested functions can only be called from the scope in which they're defined. This means that a nested function can only be called from the function in which it is defined. The next example clarifies this.
func printMessage(message: String) {
let a = "hello world"
func printHelloWorld() {
print(a)
}
}
2. Closures
What Is a Closure?
If you've worked with blocks in C and Objective-C or closures in JavaScript, then you won't have a hard time wrapping your head around the concept of closures. We've already worked with closures in this article, because functions are closures too. Let's start with the basics and inspect the anatomy of a closure.
A closure is a block of functionality that you can pass around in your code. You can pass a closure as an argument of a function or you can store it as a property of an object. Closures have many use cases.
The name closure hints at one of the key characteristics of closures. A closure captures the variables and constants of the context in which it is defined. This is sometimes referred to as closing over those variables and constants.
Syntax
The basic syntax of a closure isn't difficult. Take a look at the following example.
let a = {(a: Int) -> Int in
return a + 1
}
The first thing you'll notice is that the entire closure is wrapped in a pair of curly braces. The parameters of the closure are wrapped in a pair of parentheses, separated from the return type by the -> symbol. The above closure accepts one argument, a, of type Int and returns an Int. The body of the closure starts after the in keyword.
Named closures, that is, global and nested functions, look a bit different. The following example illustrates these differences.
func increment(a: Int) -> Int {
return a + 1
}
The most prominent differences are the use of the func keyword and the position of the parameters and return type. A closure starts and ends with a curly brace, wrapping the parameters, return type, and body. Despite these differences, remember that every function is a closure. Not every closure is a function, though.
Closures as Parameters
Closures are powerful and the following example illustrates how useful they can be. In the example, we create an array of states. We invoke the map() function on the array to create a new array that only contains the first two letters of each state as a capitalized string.
var states = ["California", "New York", "Texas", "Alaska"]
let abbreviatedStates = states.map({ (state: String) -> String in
let index = state.startIndex.advancedBy(2)
return state.substringToIndex(index).uppercaseString
})
print(abbreviatedStates)
In the above example, the map() function is invoked on the states array, transforms its contents, and returns a new array that contains the transformed values. The example also shows the power of Swift's type inference. Because we invoke the map() function on an array of strings, Swift knows that the state argument is of type String. This means that we can omit the type as shown in the updated example below.
let abbreviations = states.map({ (state) -> String in
return state.substringToIndex(advance(state.startIndex, 2)).uppercaseString
})
There are a few more things we can omit from the above example, resulting in the following one-liner.
let abbreviations = states.map({ state in state.substringToIndex(state.startIndex.advancedBy(2)).uppercaseString })
Let me explain what's happening. The compiler can infer that we return a string from the closure that we pass to the map() function, which means there's no reason to include the return type in the closure expression definition. We can only do this if the closure's body includes a single statement, though. In that case, we can put that statement on the same line as the closure's definition, as shown in the above example. Because there's no return type in the definition and no -> symbol preceding the return type, we can omit the parentheses enclosing the closure's parameters.
Shorthand Argument Names
It doesn't stop here, though. We can make use of shorthand argument names to simplify the above closure expression even more. When using an inline closure expression, as in the above example, we can omit the list of parameters, including the in keyword that separates the parameters from the closure body.
In the closure body, we reference the arguments using shorthand argument names Swift provides us with. The first argument is referenced by $0, the second by $1, etc.
In the updated example below, I have omitted the list of parameters and the in keyword, and replaced the state argument in the closure's body with the shorthand argument name $0. The resulting statement is more concise without compromising readability.
let abbreviations = states.map({ $0.substringToIndex($0.startIndex.advancedBy(2)).uppercaseString })
Trailing Closures
The Swift programming language also defines a concept known as trailing closures. If you pass a closure as the last argument of a function, you can place that closure outside the parentheses of the function call. The following example demonstrates how this works.
let abbreviations = states.map() { $0.substringToIndex($0.startIndex.advancedBy(2)).uppercaseString }
If the only argument of the function call is the closure, then it's even possible to omit the parentheses of the function call.
let abbreviations = states.map { $0.substringToIndex($0.startIndex.advancedBy(2)).uppercaseString }
Note that this also works for closures that contain multiple statements. In fact, that is the main reason trailing closures are available in Swift. If a closure is long or complex and it's the last argument of a function, it is often better to use the trailing closure syntax.
let abbreviations = states.map { (state: String) -> String in
let toIndex = state.startIndex.advancedBy(2)
let newState = state.substringToIndex(toIndex)
return newState.uppercaseString
}
3. Protocols
Protocols are an important component of the Swift programming language. The concept isn't difficult to understand if you're familiar with protocols in Objective-C or interfaces in Java. A protocol defines a design or interface focused on a particular task. It does this by defining properties and methods necessary to perform that task.
Defining a protocol looks similar to defining a class or structure. In the following example, we define the Repairable protocol. The protocol defines two properties, time and cost, and a method repair(). The time property is readonly while the cost property is readwrite.
protocol Repairable {
var time: Float { get }
var cost: Float { get set }
func repair()
}
A class or structure can adopt a protocol by conforming to it. This means that it is required to implement the properties and methods defined by the protocol. Let's update the Boat class we implemented in the previous tutorial.
class Boat: Repairable {
var speed: Float = 0
var lifeboats: Int = 2
var time: Float = 10.0
var cost: Float = 100.0
func deployLifeboats() {
// ...
}
func repair() {
// ...
}
}
That's how easy it is to conform a type to a protocol. Even though a protocol cannot be instantiated like a class or structure, a protocol is a valid type. Take a look at the following example in which the Repairable protocol is used as the type of a function argument.
Davis Allie recently wrote a great article about protocol-oriented programming in Swift. If you're interested in learning more about protocols and their potential in Swift, then I encourage you to read Davis' article.
4. Access Control
I'd like to conclude this introduction to Swift by talking about access control. As the name implies, access control defines which code has access to which code. Access control levels apply to methods, functions, types, etc. Apple simply refers to entities. There are three access control levels, public, internal, and private.
Public: Entities marked as public are accessible by entities defined in the same module as well as other modules, such as a project, framework, or library. This access control level is ideal for exposing the interface of a framework.
Internal: This is the default access control level. In other words, if no access control level is specified, the internal access control level applies. An entity with an access level of internal is only accessible by entities defined in the same module.
Private: An entity declared as private is only accessible by entities defined in the same source file.
Take a look at the following example in which I've updated the Boat class. The class itself is marked as public, which means it's accessible from anywhere. The cost property is implicitly marked as internal, because we haven't specified an access control level. The same is true for the deployLifeboats() method.
public class Boat {
public var speed: Float = 0
public var lifeboats: Int = 2
var cost: UInt = 100
func deployLifeboats() {
// ...
}
private func scheduleMaintenance() {
}
}
The scheduleMaintenance() method is marked as private, which means that it can only be invoked by entities defined in the source file in which the Boat class is defined. It's important to understand this, because it's slightly different from what other programming languages consider a private method or property.
If we mark the Boat class as internal by removing the public keyword, the compiler will show us a warning. It tells us that we cannot mark speed and lifeboats as public as long as Boat is marked as internal. The compiler is right of course. It doesn't make sense to mark the properties of an internal class as public.
Conclusion
The Swift programming language is easy to pick up, but there's so much more to it than what we've covered in the past two tutorials. You'll learn more about Swift once we start building applications. In the next article, we take a closer look at the iOS SDK.
If you have any questions or comments, you can leave them in the comments below or reach out to me on Twitter.
A good understanding of the iOS SDK is key when developing native iOS applications. Not only will it help you choose the right tools to tackle a particular problem, it will also make sure that you don't get lost in the dozens of frameworks that are included in the SDK. In this article, we zoom in on the iOS architecture and find out what powers iOS applications under the hood.
What Is the iOS SDK?
I am pretty sure that even a few experienced iOS developers would have a hard time defining the iOS SDK in one sentence. The acronym SDK stands for Software Development Kit. The iOS SDK contains the tools and resources to develop native iOS applications, which means that the SDK enables developers to develop, install, run, and test applications in the simulator and on physical devices.
The two driving forces powering native iOS applications are Swift (or Objective-C) and the native iOS system frameworks. In the previous articles, we explored the Swift programming language. In this article, I want to explore the frameworks that power native iOS applications.
This includes high level frameworks, such as the UIKit and Map Kit frameworks, but also frameworks that are closely tied to the hardware, such as the Accelerate and Core Location frameworks.
What Is a Native iOS Application?
You now know what the iOS SDK is, but what makes an application qualify as a native iOS application? The simple answer is that an iOS application is an application that runs on an iOS device. That's only half the truth, though. What about web applications that run in Safari?
An iOS application is a Cocoa application developed for the iOS platform. Great. What is a Cocoa application? A Cocoa application is a bit harder to define. Is it the language in which the application is written? Not really. Is it the tools with which a Cocoa application is built? No. It is possible to develop a Cocoa application without the help of Xcode.
Apple defines a Cocoa application as an application that is composed of objects that ultimately inherit from NSObject, a root class declared in the Foundation framework, and that is tightly integrated with the Objective-C runtime.
In this article, I want to focus on the frameworks that are used to create native iOS applications. If you're interested in learning more about the Objective-C runtime, which is also used by Swift, I recommend taking a look at Apple's Objective-C Runtime Reference or read the Objective-C Runtime Programming Guide.
The Foundation framework provides a second root class, NSProxy. However, you will rarely, if ever, use it in any of your projects.
iOS Architecture
Another difference with web applications running in Safari is that native applications interact directly with the iOS operating system and the native system frameworks of iOS. The operating system acts as a mediator between the application and the underlying hardware. A key advantage of this mediation or abstraction is that native applications don't need to worry about future hardware changes or device specifications.
The operating system provides native applications with the necessary information about the hardware capabilities (Does the device have a camera?) and device specifications (Is the application running on an iPhone or an iPad?).
The iOS architecture can be broken down into four distinct layers:
Cocoa Touch
Media
Core Services
Core OS
This layered architecture illustrates that level of abstraction, with the higher level layers more abstracted and the lower level layers more fundamental, closely tied to the hardware. It goes without saying that the higher level layers rely on the lower level layers for some of their functionality.
Apple recommends using the higher level frameworks whenever possible, because they are often object-oriented abstractions of the lower level frameworks. In other words, the higher level layers interact indirectly with the hardware through the lower level layers, which are inherently more complex. Of course, it's still possible to fall back to the lower level frameworks if the higher level frameworks don't meet your needs.
As a reminder, a framework is a directory that contains a dynamic shared library and the resources associated with it, such as header files, images, etc. Frameworks are the access points to various system interfaces, such as the iOS address book, the device's camera roll, and the music library.
Cocoa Touch Layer
In the previous article, I wrote about Cocoa Touch and its relation to Swift and Objective-C. In this article, I would like to discuss Cocoa Touch from a more functional standpoint. How do applications rely on the Cocoa Touch layer? What is the role of Cocoa Touch in the iOS architecture?
The Cocoa Touch layer is the topmost layer of the iOS architecture. It contains some of the key frameworks native iOS applications rely on, with the most prominent being the UIKit framework.
The Cocoa Touch layer defines the basic application infrastructure and provides a number of vital technologies, such as multitasking and touch-based input.
As I mentioned, iOS applications rely heavily on the UIKit framework. Native iOS applications cannot operate if they are not linked against the UIKit and the Foundation frameworks.
The UIKit framework, or UIKit for short, is tailored to the iOS platform. There is an equivalent framework for the OS X platform, the Application Kit framework or AppKit. UIKit provides the infrastructure for graphical, event-driven iOS applications. It also takes care of other core aspects that are specific to the iOS platform, such as multitasking, push notifications, and accessibility.
The Cocoa Touch layer provides developers with a large number of high level features, such as Auto Layout, printing, gesture recognizers, and document support. In addition to UIKit, it contains the Map Kit, Event Kit, and Message UI frameworks, among others.
For a complete list of all the frameworks of the Cocoa Touch layer, I'd like to refer to Apple's iOS Technology Overview guide.
Media Layer
Graphics, audio, and video are handled by the Media layer. This layer contains a number of key technologies, such as Core Graphics, OpenGL ES and OpenAL, AV Foundation, and Core Media.
The Media layer contains a large number of frameworks including the Assets Library framework to access the photos and videos stored on the device, the Core Image framework for image manipulation through filters, and the Core Graphics framework for 2D drawing.
Take a look at Apple's iOS Technology Overview guide for a complete list of all the frameworks of the Media layer.
Core Services Layer
The Core Services layer is in charge of managing the fundamental system services that native iOS applications use. The Cocoa Touch layer depends on the Core Services layer for some of its functionality. The Core Services layer also provides a number of indispensable features, such as block objects, Grand Central Dispatch, In-App Purchase, and iCloud Storage.
One of the most welcomed additions to the Core Services layer is ARC or Automatic Reference Counting. ARC is a compiler-level feature, introduced in 2011 alongside the release of iOS 5. ARC simplifies the process of memory management in Objective-C.
Memory management is a topic we haven't covered in this series, but it's important that you understand the basics of memory management when developing Cocoa applications. Automatic Reference Counting is a great addition, but it's important that you know what ARC is doing for you.
The Foundation framework, or Foundation for short, is another essential framework for iOS and OS X applications. In the next article, we explore this framework in more detail. The Foundation framework is more than a collection of useful classes, such as NSArray, NSDictionary, and NSDate.
Foundation provides the NSObject root class, which provides a basic interface to the Objective-C runtime, and it also introduces several paradigms, such as policies for object ownership. Like Core Foundation (see below), Foundation makes it possible for the different libraries and frameworks to easily share data and code.
Another important framework of the Core Services layer, and closely tied to the Foundation framework, is the C-based Core Foundation framework, or Core Foundation for short. Like the Foundation framework, it enables the various libraries and frameworks to share data and code.
Core Foundation has a feature, known as toll-free bridging, that enables the substitution of Cocoa objects for Core Foundation objects in function parameters and vice versa.
For a complete list of all the frameworks of the Core Services layer, I'd like to refer to the iOS Technology Overview guide.
Core OS Layer
Most of the functionality provided by the three higher level layers is built on the Core OS layer and its low level features. The Core OS layer provides a handful of frameworks that your application can use directly, such as the Accelerate and Security frameworks.
The Core OS layer also encapsulates the kernel environment and low level UNIX interfaces to which your application has no access, for obvious security reasons. However, through the C-based libSystem library many low level features can be accessed directly, such as BSD sockets, POSIX threads, and DNS services.
Documentation
Your closest ally when developing native iOS applications is the documentation bundled with the iOS SDK. For the most part, the documentation is outstanding and it will help you get up to speed with a new technology or framework with little effort.
Even though the documentation is available online, most developers use the documentation browser that's included in Xcode. In Xcode 7, You can find the documentation browser by selecting Documentation and API Reference from Xcode's Window menu.
Since you'll be using the documentation extensively, you might want to learn a few shortcuts to find what you are looking for in the documentation. As I mentioned in the previous paragraph, the documentation browser provides easy access to the documentation. To quickly access the documentation, press Command + Shift + 0 in Xcode.
During development, it can quickly become cumbersome to switch back and forth between the code editor and the documentation browser every time you need to look up a symbol, such as a class, method, or structure.
There are two solutions for efficiently browsing the documentation. Whenever you place your cursor on a class or method name in Xcode's code editor, the Quick Help Inspector in the right sidebar shows a summary of the respective symbol. The summary contains several useful links that take you to the documentation browser.
Because I usually hide the right sidebar when I'm working in the code editor, I use an alternative method to show the documentation of a class or method. Whenever you press the Option key and hover over a symbol, the cursor changes to a question mark and the symbol is highlighted.
By clicking a symbol with the question mark, a new window pops up containing the same summary as the Quick Help Inspector. Clicking one of the links in the window takes you to the documentation browser. This is a fast and convenient way to switch between the code editor and the documentation browser, especially when working with two monitors.
Conclusion
You should now have a good understanding of the iOS SDK and the various layers of the iOS architecture. The two core frameworks of an iOS application, UIKit and Foundation, are the focus of the next two installments of this series.
Not only are these frameworks indispensable for every iOS application, they contain dozens of classes that you will find yourself using often when developing native iOS applications.
If you have any questions or comments, you can leave them in the comments below or reach out to me on Twitter.
Project templates are a great way to learn from other people's work. This article lists a few popular iOS templates available on Envato Market. If you are looking for inspiration or you're building an application and need help with a particular feature, then you may find your answer in some of these templates.
If you're into game development, then this template is certainly worth checking out. Scary Poo World is an endless runner game in which Poo—what's in a name—is lost in Scary World, trying to find a way out.
The game is well designed and includes many basic features you typically find in an endless runner game, such as multiple enemies, obstacles, powers, etc. The template also includes Game Center integration and support for ads. The template is compatible with Xcode 7 and ready for iOS 9. Not convinced? Give it a try. It's free on the App Store.
As the name indicates, Store Finder is an application for finding nearby stores. But the application does a lot more than that. It is packed with features and the template also includes a backend for managing the application's data.
The application fetches data from the backend and, if location services are enabled, it ranks the results based on the user's location. The template is ready for iOS 9 and also supports iPhone 6/6S (Plus).
The application includes a range custom animations to make the user experience playful and engaging. The developer invested heavily in social sharing and includes support for email, text message, Facebook, Twitter, and a few others. Head over to CodeCanyon to see the complete list of features.
Compared to ten years ago, people take a lot of photos and we have the mobile phone to thank for that. This application template includes a powerful image editor that covers most of the basics, such as cropping, rotating, applying filters, and social sharing.
The template includes a universal application, it is updated for iOS 9, and the deployment target is iOS 6. If you want to see how the application works, then check out this YouTube video.
If you're planning to develop mobile applications, then a to-do application is a great way to get your feet wet. Checklist is a well designed to-do application that includes most of the features you'd expect in a to-do application.
The application template is well supported and the minimum deployment target is iOS 5. Even though the template was created several years ago, it supports iOS 8 and has been updated to support iPhone 6 and iPhone 6 Plus. You can see the application in action on YouTube. The author has also created a video that shows how to integrate the template in an existing application.
What makes this store finder template unique is its CloudKit integration. Instead of relying on a custom backend, this application relies on iCloud through CloudKit. This means that you don't need a server to get up and running.
The template uses the location services of the device to find nearby stores, which you can then share on social media or email to a friend. The template also includes a review system and the ability to manually search for stores.
This template is great for learning how audio works on iOS. The application manages and streams a list of radio stations. It streams audio from online radio stations and pulls artwork from Last.fm. The template has support for background audio and elegantly handles playback interruptions.
The application uses SHOUTcast and Icecast for fetching radio stations and includes support for various media types.
This messaging application is built on top of Facebook's Parse platform. The template is built with Swift and messages can include both text and images. The included project also adds support for push notifications to make sure messages arrive even if the application isn't running.
Because the application relies on Parse as its backend, there's no need to set up a server or worry about uptime and scaling. If you're interested in building a messaging application or you just want to get started with Parse, then this template is worth checking out.
More?
Envato Market contains dozens of mobile application templates to get you started with your next project. These templates are great to learn or to see how fellow developers have implemented a particular feature. They're also great if you're looking for that kick of inspiration. Check out the iOS templates on Envato Market.
The Foundation framework is the bread and butter in the toolbox of an iOS developer. It provides the NSObject root class and a large number of fundamental building blocks for iOS development, from classes for numbers and strings, to arrays and dictionaries. The Foundation framework might seem a bit dull at first, but it harnesses a lot of power and is indispensable for developing iOS applications.
A Word About Core Foundation
In the previous article, I briefly mentioned Core Foundation and its relation to Foundation. Even though we won't explicitly use the Core Foundation framework in the rest of this series, it's useful to be familiar with the framework and to know how it differs from its object-oriented sibling, Foundation, which you'll use extensively.
While the Foundation framework is implemented in Objective-C, the Core Foundation framework is C-based. Despite this difference, the Core Foundation framework does implement a limited object model. This object model allows for the definition of a collection of opaque types that are often referred to as objects—despite the fact that they are, strictly speaking, not objects.
The primary goal of both frameworks is similar, enabling sharing of data and code between the various libraries and frameworks. Core Foundation also includes support for internationalization. A key component of this support is provided through the CFString opaque type, which efficiently manages an array of Unicode characters.
As I mentioned previously, toll-free bridging literally bridges the gap between both frameworks by enabling the substitution of Cocoa objects for Core Foundation objects in function parameters and vice versa.
It's important to note that Automatic Reference Counting (ARC) doesn't manage Core Foundation "objects". This means that you are responsible for managing memory when working with Core Foundation. Mike Ash wrote a great article about Automatic Reference Counting and how to use ARC with Core Foundation and toll-free bridging.
Visit Apple's Core Foundation framework reference if you want to learn more about the framework and for a complete list of the framework's opaque types.
Practice, Practice, Practice
Learning a new skill is best done through practice. Let's get started by creating a new playground in Xcode. Name the playground Foundation and set Platform to iOS. Click Next to continue. Tell Xcode where you want to save the playground and click Create.
This is what the contents of the playground should look like.
//: Playground - noun: a place where people can play
import UIKit
var str = "Hello, playground"
The playground contains a comment at the top, an import statement for the UIKit framework, and a variable declaration. On the right, you can see the output of the playground.
Since we'll be working with the Foundation framework, we need to replace the import statement for UIKit with an import statement for Foundation. Remove the comment at the top, update the import statement, and remove the variable declaration.
import Foundation
Foundation
The Foundation framework is much more than a collection of classes for working with numbers, strings, and collections (arrays, dictionaries, and sets). It also defines dozens of protocols, functions, data types, and constants.
In the rest of this article, I will primarily focus on the classes that you'll use most often when developing iOS applications. However, I will also briefly talk about three key protocols defined by the Foundation framework, NSObject, NSCoding, and NSCopying.
Protocols
Several languages, such as Perl, Python, and C++, provide support for multiple inheritance. This means that a class can descend from—be a subclass of—more than one class.
Even though Swift and Objective-C don't provide support for multiple inheritance, they do support multiple inheritance through specification in the form of protocols. We already covered protocols earlier in this series, but there is an important detail we haven't discussed yet.
Optional and Required Methods
Remember that every method of a Swift protocol is required. If a type conforming to a Swift protocol doesn't implement every property and method defined by the protocol, the compiler will throw an error. This isn't true for Objective-C protocols. In Objective-C, methods of a protocol can be marked as optional. If a protocol method is optional, the type conforming to the protocol isn't required to implement the method.
Because the vast majority of the frameworks of the iOS SDK are written in Objective-C, we will meet a number of Objective-C protocols that define optional methods. What's important to remember is that every property and method of a Swift protocol is required.
Benefits
The benefits of protocols are manifold. When a class adopts or conforms to a protocol, the class is expected to implement the methods declared by the protocol. For some of you, protocols may be reminiscent of interfaces in Java. This means that a protocol can be used to declare the interface to an object without revealing the type of the object.
Multiple inheritance has its benefits, but it most certainly has its downsides. The advantage of protocols is that unrelated types, enums, classes, and structures, can still share similar behavior through the use of protocols.
NSObject
In addition to the NSObject root class, the Foundation framework also defines the NSObject protocol. In Swift, however, classes and protocols cannot have the same name. As a result, the NSObject protocol is known as the NSObjectProtocol in Swift.
Objects conforming to the NSObjectProtocol protocol can be asked about their class and superclass, can be compared with other objects, and respond to self. This is only a small subset of the behavior added to objects conforming to the NSObjectProtocol protocol.
NSCoding
Objects conforming to the NSCoding protocol can be encoded and decoded. This is necessary for objects that need to be archived or distributed. Object archival, for example, takes place when an object or object graph is stored to disk.
NSCopying
The NSCopying protocol declares only one method, copyWithZone(_:). If a class is to support copying objects, it needs to conform to the NSCopying protocol. Copying an object is done by sending it a message of copy() or copyWithZone(_:).
Classes
NSObject
The NSObject class is the root class of the vast majority of the Objective-C class hierarchies. Why is that important if we're interested in Swift? Remember that most frameworks of the iOS SDK are powered by Objective-C. Even if you decide to develop an application in Swift, you'll still be using Objective-C under the hood.
By inheriting from the NSObject root class, objects know how to behave as Objective-C objects and how to interface with the Objective-C runtime. It shouldn't be a surprise that NSObject conforms to the NSObject/NSObjectProtocol protocol, which we discussed a few moments ago.
Let's see what we get for free if a class inherits from the NSObject class. Add the following code snippet to your playground. This should look familiar if you've read the previous articles of this series. We declare a class, Book, that inherits from NSObject. The Book class implements two instance methods, chapters() and pages().
Because Book inherits from NSObject and NSObject conforms to the NSObjectProtocol protocol, we can ask the Book class about its behavior and inheritance tree. Take a look at the following example.
We first ask the Book class about itself by invoking classForCoder() on the Book class. The classForCoder() method is a class method, which means we can invoke this method on the Book class itself. Next, we ask the Book class about its superclass or parent class, the class it directly inherits from. This returns an optional since not every class has a parent class. Unsurprisingly, the superclass of Book is NSObject.
The next line tells us that Book conforms to the NSObjectProtocol protocol, which isn't unexpected since it inherits this trait from the NSObject class. We also learn that Book doesn't conform to the NSCoding protocol.
It appears that the Book class doesn't respond to the chapters() method. This isn't that odd since chapters() is an instance method, not a class method. This is proven by the last two lines of our example in which we instantiate a Book instance and ask the instance the same question.
In the above example we use the respondsToSelector(_:) method, but you may be wondering what a selector is? What does "responding to a selector" mean? A selector is a fancy word for the name a function or method. A selector is used by the Objective-C runtime to send messages to objects. Long story short, if you read the word selector, then think function or method. The finer details are beyond the scope of this tutorial.
NSNumber
The NSNumber class is a utility class that manages any of the basic numeric data types. It is a subclass of the NSValue class, which provides an object-oriented wrapper for scalar types, pointers, structures, and object ids. The NSNumber class defines methods for retrieving the value it stores, for comparing values, and also for returning a string representation of the stored value.
Keep in mind that the value retrieved from an NSNumber instance needs to be consistent with the value that is being stored in it. The NSNumber class will attempt to dynamically convert the stored value to the requested type, but it goes without saying that there are limitations inherent to the data types that NSNumber can manage.
Let me illustrate this with an example. Add the following code snippet to your playground.
We create a new NSNumber instance by passing a Double value to init(double:). Next, we request the stored value using three different NSNumber methods. As you can see, the results don't always reflect the value stored in myNumber.
The lesson is simple, be consistent when using NSNumber by keeping track of the type that is stored in the NSNumber instance.
NSString
Instances of the NSString class manage an array of unichar characters forming a string of text. The subtle but important difference with a regular C string, which manages char characters, is that a unichar character is a multibyte character. This is similar to Swift's String type.
As its name implies, a unichar character is ideally suited for handling Unicode characters. Due to this implementation, the NSString class provides out-of-the-box support for internationalization.
I want to emphasize that the string managed by an NSString instance is immutable. This means that, once the string is created, it cannot be modified. Developers coming from other languages, such as PHP, Ruby, or JavaScript, might be confused by this behavior.
The Foundation framework also defines a mutable subclass of NSString, NSMutableString, that can be modified after initialization.
There are various ways to create string objects. The simplest way to create a string object is by calling the string() method on the NSString class. This returns an empty string object. Take a look at the class reference of NSString for a complete list of initializers.
Another common path for creating string objects is through string literals. In the next example, a string literal is assigned to stringA. At compile time, the compiler will replace the string literal with an instance of NSString.
Notice that we don't rely on Swift's type inference to determine the type of stringA. The second example, stringB, shows why that is. If we don't explicitly specify the type of stringA as NSString, Swift thinks we want to create a String instance. The example also illustrates that NSString inherits from NSObject while String doesn't. Remember that the String type in Swift is a structure and structures don't support inheritance.
The NSString class has a wide range of instance and class methods for creating and manipulating strings and you will rarely, if ever, feel the need to subclass NSString.
Let's explore NSString and its mutable subclass, NSMutableString, by adding the following snippet to your playground.
let stringA: NSString = "This is "
let stringB: NSString = NSString(string: "a mutable string.")
var mutableString = NSMutableString(string: stringA)
mutableString.appendString(stringB as String)
We start by creating two NSString instances, one using literal syntax and one using the init(string:) initializer. A mutable string is then created by passing the first string as an argument. To illustrate that mutable strings can be modified after creation, stringB is appended to the mutable string and its value printed.
NSArray and NSSet
The NSArray class manages an immutable, ordered list of objects. The Foundation framework also defines a mutable subclass of NSArray, NSMutableArray. The NSArray class behaves very much like a C or Swift array with the difference that an instance of NSArray manages objects. The NSArray class declares a wide range of methods that facilitate working with arrays, such as methods for finding and sorting objects in the array.
It's important to understand that instances of NSArray, NSSet, and NSDictionary can only store objects. This means that it's not possible to store scalar types, pointers, or structures in any of these collection classes—or their subclasses—the compiler will throw an error if you do. The solution is to wrap scalar types, pointers, and structures in an instance of NSValue or NSNumber like we saw earlier in this article.
Add the following code snippet to your playground to explore NSArray and its mutable counterpart, NSMutableArray.
let myArray = NSArray(objects: "Bread", "Butter", "Milk", "Eggs")
print(myArray.count)
print(myArray.objectAtIndex(2))
var myMutableArray = NSMutableArray(object: NSNumber(int: 265))
myMutableArray.addObject(NSNumber(int: 45))
We create an array by using the init(objects:) initializer. This method accepts a variable number of arguments. Next, we print the number of objects in the array and ask the array for the object at index 2.
Because NSMutableArray inherits from NSArray, it behaves in much the same way as NSArray. The main difference is that objects can be added and removed from the array after initialization.
Before moving on, I want to say a few words about NSSet. This class is similar to NSArray, but the key differences are that the collection of objects that a set manages is unordered and that a set cannot contain duplicates.
The advantage of NSSet is that querying its objects is faster if you only need to know if an object is contained in the set. The Foundation framework also defines NSOrderedSet. Instances of this class have the benefits of NSSet, but also keep track of the position of each object.
NSDictionary
Like arrays, dictionaries are a common concept in most programming languages. In Ruby, for example, they are referred to as hashes. The basic concept is easy, a dictionary manages a static collection of key-value pairs or entries.
As in Ruby hashes, the key of an entry doesn't need to be a string object per se. It can be any type of object that conforms to the NSCopying protocol as long as the key is unique in the dictionary. In most cases, though, it's recommended to use string objects as keys.
Like arrays, dictionaries cannot store a null value. If you want to represent a null value, then you can use NSNull. The NSNull class defines a singleton object that is used to symbolize null values in arrays, dictionaries, and sets.
The singleton pattern is an important pattern in many programming languages. It limits the instantiation of a class to one object. You will deal with singleton objects frequently when developing iOS applications.
Like NSArray, the Foundation framework defines a mutable subclass of NSDictionary, NSMutableDictionary. There are various ways to instantiate a dictionary. Take a look at the following code snippet.
let keyA: NSString = "myKey"
let keyB: NSString = "myKey"
let myDictionary = NSDictionary(object: "This is a string literal", forKey: keyA)
print(myDictionary.objectForKey(keyB))
We declare two separate NSString objects containing the same string. We then instantiate a dictionary by invoking init(object:forKey:). Next, we ask the dictionary for the object associated with the contents of keyB and print its value.
It's important to pay attention to the details. Even though we used keyA as the key of the key-value pair and keyB as the key to fetch the value or object of the key-value pair, the dictionary gave us the correct object (as an optional). The NSDictionary class is smart enough to know that we want the object associated with string "myKey". What does this mean? Even though the objects keyA and keyB are different objects, the string that they contain is the same and that is precisely what the NSDictionary class uses to reference the object.
Before we wrap up this tutorial, I'd like to show you an example of nested dictionaries and arrays and an example of NSMutableDictionary. The following code fragment shows that a dictionary can contain another dictionary—or array—and it also shows how to work with mutable dictionaries.
let myMutableDictionary = NSMutableDictionary()
myMutableDictionary.setObject(myDictionary, forKey: "myDictionary")
Conclusion
Even though we covered a lot of ground in this article, we barely scratched the surface of what the Foundation framework has to offer. It isn't necessary to know the details of every class or function defined in the Foundation framework to get started with iOS development, though. You'll learn more about the Foundation framework as you explore the iOS SDK.
In the next article, we explore the UIKit framework and I also discuss the ins and outs of an iOS application.
If you have any questions or comments, you can leave them in the comments below or reach out to me on Twitter.
UIKit is the framework that you'll user most often when developing iOS applications. It defines the core components of an iOS application, from labels and buttons to table views and navigation controllers. In this article, not only will we start our exploration of the UIKit framework, we will also explore the internals of an iOS project and the basic building blocks of iOS applications.
What Is the UIKit Framework?
While the Foundation framework defines classes, protocols, and functions for both iOS and OS X development, the UIKit framework is exclusively geared towards iOS development. It's the equivalent of the Application Kit or AppKit framework for OS X development.
Like Foundation, UIKit defines classes, protocols, functions, data types, and constants. It also adds additional functionality to various Foundation classes, such as NSObject, NSString, and NSValue through the use of Objective-C categories.
Objective-C categories are a convenient way to add extra methods to existing classes without the need for subclassing. They are similar to Swift extensions. Read this tutorial by Aaron Crabtree if you want to learn more about Objective-C categories.
Instead of exploring the key classes of UIKit, like we did for the Foundation framework, we're going to create and journey through a new iOS project, exploring the classes we encounter. By taking this approach, it will quickly become clear in what context a class is used, how each class fits into the broader scheme of an iOS application, and what role it plays.
A New Beginning
Launch Xcode and create a new project by selecting New > Project... from the File menu. In the iOS section on the left, select the Application category. From the list of project templates, choose the Single View Application template.
The Single View Application template contains the basic building blocks of an iOS application, which makes it a good place to start our journey.
Name the project FirstSteps and enter an organization name and identifier. Set Language to Swift and set Devices to iPhone. Leave the checkboxes at the bottom unchecked.
Tell Xcode where you want to save the new project and make sure to put the project under version control by checking the checkbox labeled Create Git repository on My Mac. Revisit this article for more information about version control and its benefits.
Files and Folders
We have learned quite a few new things since the last time we created an iOS project from scratch so it's a good idea to explore the various files and folders of our new project to see if they ring a bell.
In the Project Navigator, you should see two folders at the root of the project:
Products
a folder with your project's name, FirstSteps in this example
Let's take a look at the contents of each of these folders.
Products
The Products folder currently contains one item. It bears the name of the project and has an extension of .app. The Products folder contains the application—or applications—created by the project after compilation of the source code.
Have you noticed that FirstSteps.app is highlighted in red? Whenever Xcode is unable to locate a file, it highlights the file in red. Don't worry, though. Because the project hasn't been compiled yet, Xcode hasn't created the product yet.
Project Folder
Most of your time is spent in the project folder, which currently contains six files. The first two files, AppDelegate.swift and ViewController.swift, are source files. These files contain the source code of the application.
Main.storyboard contains the user interface of the application. We've already worked with storyboards earlier in this series. Notice that there's a second storyboard, LaunchScreen.storyboard. This storyboard is used by the operating system when the application is being launched. Instead of showing an empty view, the operating system uses this storyboard to dynamically create a launch image, which is shown to the user when the application is loading.
Info.plist, commonly referred to as the "info-dot-plist" file of a project, is a property list that contains various configuration settings. Most of these settings can also be modified by selecting the project in the Project Navigator, choosing the target in the Targets list, and opening the General, Capabilities, and Info tabs.
Assets.xcassets is a special type of folder for storing your project's assets, such as images.
Application Components
Now that we know what the different files and folders in our project are for, it's time to explore the different components of an iOS application. As we continue our journey, we will come across several classes that belong to UIKit. Each class that belongs to the UIKit framework starts with the class prefix UI. Remember that Foundation classes are prefixed with NS.
The Model-View-Controller Pattern
Before we start exploring the UIKit framework, I want to talk about the Model-View-Controller (MVC) pattern. The MVC pattern is one of the most widespread patterns in object-oriented programming. It promotes code reusability and has close ties with the concept of separation of responsibilities or concerns. One of the main objectives of the MVC pattern is the separation of an application's business logic from the presentation layer.
Cocoa Touch embraces the MVC pattern, which means it's important to understand what it is and how it works. In other words, by understanding the MVC pattern, it will be much easier to grasp how the different components of an iOS application work together.
In the MVC pattern, the model layer is in control of the business logic of an application. Interacting with a database, for example, is the responsibility of the model layer. The view layer presents the data that is managed by the model layer to the user. The view layer manages the user interface and user input.
The controller is the glue between the model layer and the view layer. While the model layer and the view layer don't know about each other's existence, the controller knows about both.
Because the controller knows about model and view, it's often the least reusable piece of an application. The less an object knows about its environment and the objects it interacts with, the easier it is to reuse.
UIApplication
Even though the UIApplication class is a key component of every iOS application, you won't interact with it very often and you will rarely, if ever, feel the need to subclass UIApplication.
When an application launches, a singleton of this class is created. Do you remember what a singleton object is? It means that only one object instance of the UIApplication class is created during an application's lifetime.
The UIApplication instance is the entry point for user interaction and it dispatches events to the appropriate target objects. The exact meaning of this will become clear in a few minutes when we take a look at view controllers.
In iOS applications, the UIApplication instance has a delegate object associated with it. Whenever you create an iOS project using one of the provided templates, Xcode will create an application delegate class for you. Take a look at the names of the source files in the project folder in the Project Navigator. The first file is named AppDelegate.swift.
The instance of this class is the delegate of the UIApplication singleton. Before taking a closer look at the AppDelegate class, we need to understand what the delegate pattern is.
Ole Begemann wrote an excellent article about the launch sequence of a typical iOS application. In his article, Ole talks about the various components involved and their role during the application launch sequence. I highly recommend reading this article if you want to get a better understanding of the role of the UIApplication class.
The Delegate Pattern
The delegate pattern is used extensively in Cocoa and Cocoa Touch. In a future article of this series, in which we explore the ins and outs of table views, you'll discover that table views rely heavily on the delegate (and data source) pattern.
Like the MVC pattern, delegation is common in object-oriented programming. The delegate pattern in Cocoa Touch, however, is slightly different, because it makes use of a delegate protocol to define the behavior of the delegate object.
Let's jump ahead and take a look at table views. If you've spent any amount of time with an iPhone or iPad, then the UITableView class should be familiar to you. It presents an ordered list of data to the user and it does this job very well.
How does a table view know what to do when a row is tapped? Is this behavior included in the UITableView class? Certainly not, because this behavior varies from application to application. If we were to include this behavior in the UITableView class, it would not be very reusable.
The table view outsources this responsibility to a delegate object. Put differently, it delegates this task to another object, a delegate object. Take a moment to inspect the class reference of the UITableView class. It has two properties named dataSource and delegate. The delegate is notified by the table view when the user taps a row. It is the responsibility of the delegate object to respond to that touch event.
The data source of the table view is similar. The main difference is that the table view asks the data source object for something, the data that it needs to display.
Delegate and data source objects, such as the table view's delegate and dataSource objects, are almost always custom classes. In most cases, it's up to the developer to create and implement these classes, because their implementation is specific to each application.
The Application Delegate
Now that we know what delegation is, it's time to explore the AppDelegate class Xcode created for us. At application launch, the application creates an instance of the AppDelegate class. This AppDelegate instance is then set as the delegate of the UIApplication instance the operating system created for your application. You never explicitly instantiate an application delegate object.
Open AppDelegate.swift to examine the implementation of the AppDelegate class. Ignoring the comments at the top, the first line imports the UIKit framework so we can work with its classes and protocols.
import UIKit
On the next line we see something we haven't covered yet, an attribute. Attributes in Swift start with an @ symbol and can be seen as instructions for the compiler. The @UIApplicationMain attribute tells the compiler that AppDelegate is the class that should be used as the application delegate. That is all you need to know about this attribute for now.
@UIApplicationMain
The next line should look familiar. This is the start of the declaration of the AppDelegate class. It specifies the name of the class and the class's parent class, UIResponder.
It also tells the compiler that AppDelegate conforms to the UIApplicationDelegate protocol. This isn't surprising since we already know that AppDelegate serves as the application's delegate.
class AppDelegate: UIResponder, UIApplicationDelegate {
...
}
The next line is a property declaration for the window property. Note that the property is a variable of type UIWindow?. The UIWindow class is a subclass of UIView, the base class for views on iOS.
var window: UIWindow?
The most interesting part of the interface of the AppDelegate class is the UIApplicationDelegate protocol. Take a look at the reference of the UIApplicationDelegate protocol for a complete list of the methods the protocol defines.
The protocol defines dozens of methods and I encourage you to explore a few of them to get an idea of the protocol's capabilities. The method that's most interesting to us at this point is application(_:didFinishLaunchingWithOptions:).
When the UIApplication object has finished preparing the application for launch, it notifies its delegate, the AppDelegate object, that the application is about to launch.
Why does it notify the application delegate of this event? The UIApplication instance notifies its delegate about this event so that it has an opportunity to prepare for application launch. The implementation of application(_:didFinishLaunchingWithOptions:) is pretty short as you can see below.
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
return true
}
It provides a reference to the UIApplication instance and a dictionary of options. You can ignore the dictionary of options for the time being. To make sure the application is launched by the operating system, we return true.
Storyboard
The Xcode project contains another interesting file, Main.storyboard. The storyboard defines what the user interface of your application looks like. By default, the storyboard is named Main.storyboard. Select the storyboard to open it.
The storyboard currently contains one view in the central workspace. On the right of the Project Navigator you can see a list of items, which are the objects you see in the view. The top item, View Controller Scene, contains one child item, View Controller.
The View Controller object also has a number of child items, but there is one that is of special interest to us, the object named View. Remember the discussion about the MVC pattern. You can now see the MVC pattern in action. The model is missing at the moment, but we do have a view, the View object, and a controller, the View Controller object.
When the application launches, the storyboard is used to create the application's user interface. The view controller is automatically instantiated and so is the view controller's view. The View object in the storyboard is managed by the view controller.
Wait a minute. Where can I find the class of the view controller in the storyboard? How can I change its behavior to create a unique application? Select the View Controller object on the left and open the Identity Inspector on the right.
The Identity Inspector tells you everything you need to know. At the top, in the section Custom Class, you can see the name of the view controller's class, ViewController. Have you noticed that the file we haven't talked about yet bears the same name? We'll explore this file in a few moments.
The view controller is instantiated for us, because it is the initial view controller of the storyboard. This is indicated in the storyboard by the arrow pointing to the View Controller Scene.
UIViewController
If you open ViewController.swift, you'll notice that the ViewController class is a subclass of UIViewController. Like AppDelegate, the UIViewController class is a subclass of UIResponder. View controllers, or subclasses thereof, fall in the controller category of the MVC pattern. As the name implies, they control a view, an instance of the UIView class, which belongs to the view category of the MVC pattern.
As we'll see later, a view controller manages a view and its subviews. To do this, the view controller needs to know about the view. In other words, it needs to have a reference to the view.
The view controller in the storyboard has a reference to the view. You can verify this by selecting the view controller in the storyboard and opening the Connections Inspector on the right.
In the Connections Inspector, you should see a section named Outlets. The term outlet is a fancy word for a property that you can set in the storyboard. Hover with your mouse over the outlet named view and observe how the view in the workspace is highlighted. That is the connection between the view controller and the view.
UIView
Even though your application can only have one instance of UIWindow, it can have many views. The UIView class is an important component of the UIKit framework, because many classes inherit from it—directly or indirectly.
Revisit Main.storyboard by selecting it and take a look at the Object Library at the bottom of the Inspector.
Browse the Object Library and drag a label and a button to the view in the workspace. It doesn't matter where you position them in the view as long as they are in the view controller's view.
Notice that two new objects have been added to the Objects section on the left. Both the label (UILabel) and the button (UIButton) inherit from UIView. Have you noticed that the Label and Button objects are slightly indented compared to the View object? This indicates that the Label and Button objects are subviews of the View object. A view can have one or more subviews that it manages.
As I mentioned earlier, the UIView class is an important component of UIKit. A view manages a rectangular area or frame on the screen. It manages the contents of the area, the subviews, and any interactions with the view's contents. The UIView class is a subclass of UIResponder. You'll learn much more about views over the course of this series.
Outlets
Let's take a look at an example to illustrate the relationship between the storyboard, the view it contains, and the view controller. These three components are important and I want to make sure that you understand just how they work together.
A few moments ago, you added a label and a button to the view controller's view. How does the view controller know about these objects? At the moment, they don't appear in the Connections Inspector, but we can change that by telling the view controller about them. Open ViewController.swift and add a property for the label and one for the button.
import UIKit
class ViewController: UIViewController {
@IBOutlet var myLabel: UILabel!
@IBOutlet var myButton: UIButton!
...
}
By adding the @IBOutlet attribute to the property declaration, the properties appear in the Connections Inspector in the storyboard and that's what we want.
Head back to the storyboard, select the View Controller object in the View Controller Scene, and open the Connections Inspector on the right. The new properties are now listed in the list of Outlets. However, the view controller hasn't made the connection between the new properties and the objects in the storyboard yet.
This is easy to remedy. Drag from the empty circle on the left of the myLabel outlet to the label in the workspace. This will create the connection. The view controller now knows about the label. Repeat this step for the button.
Even though we can change the text of the label in the storyboard, let's do this in the view controller to illustrate that the view controller has access to the label and button in the storyboard.
Open ViewController.swift and look for theviewDidLoad() method. Modify the viewDidLoad() method to reflect the implementation below. Comments have been omitted for clarity.
override func viewDidLoad() {
super.viewDidLoad()
myLabel.text = "This is an instance of a UILabel."
}
We can send messages to the label property by accessing the view controller's myLabel property. We can change the text of the label by setting the label's text property, using a string literal.
myLabel.text = "This is an instance of a UILabel."
The viewDidLoad() method is automatically invoked when the view controller has loaded its view. The override keyword indicates that we are overriding a method that is defined by a class higher up in the inheritance tree. The UIViewController class, the parent class of the ViewController class, implements this method.
Also note that we invoke viewDidLoad() on super. What is super? Just like self refers to the current instance, super refers to the parent class, UIViewController. In other words, we invoke the viewDidLoad() method on the superclass. This is often important when overriding a method in a subclass, because the superclass may be carrying out important tasks in its own implementation and we don't want to break anything.
Run your application in the simulator by clicking the Run button in the top left. Notice that the label's text has been updated. Don't worry about the position of the label and button. That's something we'll fix in the next tutorial.
Actions
We've explored a lot of new things in this article. I want to end this installment by talking about actions. Just like outlets, actions are nothing more than methods that you can access in the storyboard.
Let's see how this works. Open ViewController.swift and add the following method below the viewDidLoad() method.
@IBAction func changeColor(sender: UIButton) {
print(sender.classForCoder)
print(sender.superclass)
let r = CGFloat(arc4random() % 255)
let g = CGFloat(arc4random() % 255)
let b = CGFloat(arc4random() % 255)
let color = UIColor(red: (r/255.0), green: (g/255.0), blue: (b/255.0), alpha: 1.0)
view.backgroundColor = color
}
Don't be confused by the @IBAction attribute. This attribute indicates that the method is an action and, therefore, accessible in the storyboard. If we take a closer look at the changeColor(_:) action, we can see that it takes one argument of type UIButton.
As the argument name implies, the argument of the method or action is the object that sent the message to the view controller. I will explain this in more detail in just a bit.
Revisit the storyboard, select the View Controller object in the View Controller Scene, and open the Connections Inspector. A new section has appeared in the Connections Inspector, Received Actions, and the action we just added is listed in this section.
Drag from the empty circle on the left of the action to the button in the workspace. A pop up menu with a list of options should appear. The list contains all the possible events that the button can respond to. The one that interests us is Touch Up Inside. This event is triggered when a user touches the button and lifts her finger within the bounds of the button.
Run your application one more time and tap the button. The view controller's view should change color every time you tap the button. We added two print statements to the changeColor(_:) action. Let's see what the output looks like when you tap the button.
UIButton
Optional(UIControl)
The first line displays the class of the sender, an instance of UIButton. This proves that it is the button that's triggering this method on the view controller. It's sending a message of changeColor(_:) to the view controller.
The second line displays the superclass of the sender. Remember that not every class has a superclass. That's the reason we get back an optional. The output tells us that the parent class of UIButton is UIControl.
The method itself is pretty simple. We generate three random integers between 0 and 255, pass these values to init(red:green:blue:alpha:) to generate a random color, and update the background color of the view controller's view with the randomly generated color. Note that view references the view that the view controller manages.
Conclusion
In this article, we explored a few classes of the UIKit framework and we took a close look at the various components of an iOS application. We'll explore and work with the UIKit framework in more detail in the rest of this series. If you don't fully understand the various concepts and patterns, then I'm sure that you will as the series progresses.
If you have any questions or comments, you can leave them in the comments below or reach out to me on Twitter.
In the previous article, we created a simple application with nothing more than a label and a button. Despite its simplicity, the application had a few layout problems. In this tutorial, you learn how to solve those problems using Apple's layout system, Auto Layout. Let's start with a new project.
Introduction
Open Xcode and create a new project, choosing the Single View Application template. Name your application Auto Layout and set Devices to Universal. Tell Xcode where to save the project and click Create.
Remember from earlier in this series, a universal application runs on iPad and on iPhone (and on iPod Touch). This means that the user interface needs to adapt to the device it's running on. Let's explore how that works and what problems we need to solve to accomplish that.
In the project, open Main.storyboard and add five labels to the view controller's view. As you can see in the below screenshot, I positioned one label in the center of the view and one in each of its corners.
You've probably noticed that Xcode tries to help you position the labels, displaying blue, dashed guidelines when you approach the edges or the center of the view. Stick with Xcode's advice and have the labels snap into position at the edges and the center of the view.
Because we are creating a universal application, the application should look good on both iPad and iPhone. Run the application in the simulator and choose iPad Retina (or any other iPad simulator) as the destination.
Ouch. The user interface doesn't look that great on iPad. Only the top left label is positioned correctly.
Change the destination to iPhone 6 (or any other iPhone simulator) and run the application one more time.
The user interface looks even worse on iPhone. Two labels aren't even visible on iPhone. As on iPad, only the top left label is positioned correctly.
The goal of this tutorial is fixing these user interface problems with Auto Layout. Before we can apply Auto Layout, we need to know what it is and how it can help us.
What Is Auto Layout?
Auto Layout was introduced on iOS with the release of iOS 5, several years ago. Auto Layout is a layout system that is descriptive and built on constraints. This simply means that you tell the layout engine how you want the user interface to be laid out. In other words, instead of telling the layout engine that a button needs to be positioned at a specific location, you describe where it should be positioned.
Constraints are used to define or describe a layout. For example, you tell the layout engine that a button needs to be horizontally centered in its containing view. The layout engine takes a set of constraints, transforms them into equations, and sets the frames of the elements in the user interface. To make this work, you should add as many constraints to avoid any ambiguity about an element's position.
The advantage of Auto Layout is simple. Thanks to the descriptive nature of Auto Layout, the layout engine updates the user interface, regardless of the dimensions or orientation of the device your application runs on. It also makes your application future-proof. When Apple introduces a device with a new screen size, your application will automatically adjust its user interface to fit the new screen size. This isn't true if you hard-code your application's user interface.
Now that you know what Auto Layout is and how it works, it's time to explore how we can apply Auto Layout to fix the layout issues in our project.
Adding Constraints
Do you remember the blue guidelines you saw when you added the labels to the view controller's view? Those aren't the constraints you're looking for. Like I said, they are guidelines to help you position user interface elements. They are nothing more than hints Xcode gives you to stick to Apple's Human Interface Guidelines.
There are a number of ways to add constraints to a user interface element. One way is by using the Pin menu at the bottom of Interface Builder. Select the label at the top left and click the Pin menu at the bottom.
The label in the top left doesn't have any constraints yet. Let's change that by pinning the label to the top left of its parent view or superview. Using the Pin menu, we can add multiple constraints at the same time. Let's also add constraints to set the label's width and height to fixed by checking the checkboxes labeled Width and Height. This is what the Pin menu should look like. Note that the checkbox Constrain to margins is unchecked.
At the bottom of the Pin menu, the button's text now reads Add 4 Constraints. Xcode is telling us that we haven't added any constraints yet. Click the button to add the constraints we specified in the Pin menu. The label's position is now defined or described by four constraints. This is visualized in the storyboard by four, blue lines surrounding the label.
Before you continue, add constraints to the top right, bottom left, and bottom right labels. It's important that you pin each label to the nearest edge of its parent view. For example, the bottom right label needs to be pinned to the bottom edge and the right edge of the view controller's view. This is what the Pin menu should look like for the bottom right label.
With the constraints in place, run the application in the simulator. This is what you should see in the iPhone 6 simulator. That's looking much better. The center label doesn't have any constraints yet. Let's add some now.
Select the center label and add two constraints to fix the label's width and height, using the Pin menu at the bottom. Did you expect to see two blue lines? If you've correctly added the constraints, you should see red lines, not blue lines. Why is that? The red lines indicate that something's amiss. Xcode is telling us that the label doesn't have enough constraints to avoid ambiguity. The description of the label's position is currently incomplete.
We've told Xcode that the label should have a fixed width and a fixed height. What we haven't defined yet is the label's horizontal and vertical position. You can find out more about the problem by inspecting the error in the panel on the left. You should see a red arrow on the left of the View Controller Scene. Click the arrow to read the error message.
The errors are telling us that the X and Y positions are undefined. If you click the red circle next to the error, Xcode gives you the option to fix the issues by adding the missing constraints. Let's not be lazy and fix the problem ourselves.
To center the label, regardless of the dimensions and orientation of the device the application is running on, we can't use the Pin menu. Instead, we use the Align menu to the left of the Pin menu. With the label selected, open the Align menu and add two constraints to center the label in its parent view. By adding these constraints, the red lines are replaced by blue lines.
Inspecting Constraints
It's time to learn more about constraints. Constraints aren't static and they're certainly not magical. You can add, remove, and modify constraints. As an example, let's take a look at the constraints of the center label. Select the label and open the Size Inspector on the left. The Constraints section lists the constraints of to the current selection, the center label. Each constraint has an Edit button to modify the attributes of the constraint.
Click the Edit button of the constraint that read Width Equals: 42. By modifying the Constant property, you can change the label's width. Set Constant to 100 and press Enter or Return to commit the change. The size of the label in the storyboard immediately reflects the change we've made.
The Priority property of the constraint is important if multiple constraints conflict with one another. Let's illustrate this with an example. Select the center label and add a new constraint that sets the width of the label to 200. You already know how to do this. When you add the new constraint, Xcode complains that it cannot satisfy both constraints at the same time.
Select the label and open the Size Inspector to inspect the constraints. There are two constraints setting the width of the label. Click the Edit button of the constraint that says Width Equals: 100 and set Priority to High (750). The width of the label changes to 200 in the storyboard and one of the blue lines changes from solid to dashed, indicating that this constraint is overruled by a constraint with a higher priority. The dashed constraint is still active, but it's currently not being applied due to its lower priority compared to the constraint that sets the width of the label to 200.
There's another way to solve the problem. Set the priority of both constraints to Required (1000). At the same time, change = to >= for the constraint that reads Width Equals: 100. This also solves the issue. The result isn't the same, though. Both constraints are in effect, working together to define the position of the label. The constraint now defines that the label's width should be greater than or equal to 100.
Adding More Constraints
I already mentioned that there are several ways to add constraints in interface builder. Let's look at another popular technique. Open the Object Library on the right and add a text field to the view controller's view. To pin the text field to the top of the view, select the text field, press Control, and drag from the text field to the top of the view. Take a look at the below screenshot for clarification.
From the menu that pops up, select Vertical Spacing to Top Layout Guide. The top layout guide is a special guide positioned along the bottom edge of the status bar and the navigation bar. The position of the top layout guide depends on the presence or absence of a status bar and navigation bar at the top.
The text field should now be pinned to the top of the view. As expected, Xcode tells us that the text field doesn't have enough constraints to unambiguously describe its position.
Select the text field, press Control, and drag to the label on the left of the text field. From the menu, select Horizontal Spacing. Repeat this step for the label on the right of the text field. We're almost there.
To set the label's height to fixed, select the text field, press Control, and drag from the top of the text field to the bottom of the text field. Select Height from the menu that appears. This defines a constraint about the text field itself, its height.
I'm sure you agree that the basics of Auto Layout are easy to understand. It can sometimes get pretty complicated, though. What we covered so far are the basics, Auto Layout flexing its muscles. Let's finish this tutorial by looking at a very common problem that is easily solved with Auto Layout.
More Constraints
It's not uncommon that you want a subview to span the width and height of its parent view. A table view, for example, is very often the same size as its parent view. Let's see how we can handle this using Auto Layout.
Add a view from the Object Library to the view controller's view. Open the Attributes Inspector and set the view's background to blue to make sure it stands out. Run the application in an iPad simulator to see what we're starting with.
You can press Command + Left Arrow or Command + Right Arrow to rotate the device. It looks like the view maintains its width and height, but it's stuck to the top left. The goal is to have it span the width and height of its parent view. Select the blue view and add the following constraints using the Pin menu.
Before you click Add 4 Constraints, make sure that you are adding the constrains in relation to the blue view's superview. What does that mean? A constraint describes a relation between two views. You are about to apply these constraints to the blue view in relation to its nearest siblings. What we want, however, is to add constraints that define the blue view's position in relation to its containing or parent view. You specify what view the constraint defines by clicking the small triangle next to the number (which defines the constant of the constraint). Take a look at the following screenshot for clarification.
Double-check that every constraint applies to the blue view and its parent or containing view. When you're ready, add the four constraints.
Instead of blue lines, you are probably seeing orange lines with numbers. In Xcode, orange means warning. The orange lines warn you that the current position of the blue view isn't in alignment with the position of the blue view at run time. Have you noticed the orange dashed lines at the edges of the blue view's parent view? Those dashed lines symbolize the frame of the blue view if the constraints you just applied are in effect. That happens at run time.
If you don't believe me, I suggest you run the application in the iPad simulator to take a look for yourself. The blue view spans the width and height of its parent view, even if you rotate the simulator from portrait to landscape and vice versa.
The orange lines unnecessarily clutter the workspace and what you're seeing isn't what you are getting at run time. It's better to fix the issue by updating the frame of the blue view. This is simple. Select the blue view and select Update Frames from the Resolve Auto Layout Issues menu at the bottom right.
Make sure you understand what we've covered in this tutorial, because we'll be needing it in the rest of this series. In the next tutorial, we'll be discussing table views and we'll be applying some of the techniques discussed in this tutorial. To learn more about Auto Layout, browse Apple's Auto Layout Guide.
Conclusion
To say that Auto Layout is powerful is an understatement. Even though we've only scratched the surface in this tutorial, you should now have an idea what Auto Layout is and what it can do for you.
In the rest of this series, we will continue using Auto Layout. If you get stuck, make sure to revisit this tutorial or drop me a line in the comments. You can also reach out to me on Twitter.