Editor’s note: See our latest post on using Carthage for adding Alamofire to your project. You don’t need to suffer through git submodules (the method described below) any longer.
It didn’t take long after the introduction of Swift to begin seeing Stackoverflow questions asking about using AFNetworking, the popular Objective-C framework for making HTTP requests on iOS. Of course it can be done, as Swift and Objective-C can coexist together in the same project, but there’s the Objective-C way of doing things, and then there is the Swift way. Enter Alamofire, brought to you by the same author as AFNetworking.
As you can guess, we’re interested in using this new framework with our Swift projects. Let’s get to it shall we. This tutorial will walk you through creating a new Xcode project using Swift to make use of the MyMemory language translator to translate simple phrases from English to Spanish. Of course we could have built an application that allowed the user to choose the source and destination languages, but we wanted to leave it as an exercise to the reader.
Before you get started, I should point out that I’m using Xcode 6.1 (6A1052d). If you are using a different version, well, as they say, YMMV. While I suggest you go through this tutorial step-by-step, you can fast forward and download the working project on Bitbucket (see the end of this post for instructions to ensure Alamofire is updated in your checkout).
Start Xcode and select File – New Project and create a Single View iOS application. For the Product Name we chose translator
, and of course make sure your language is Swift.
Before getting to Alamofire, let’s create a UI. Click on Main.storyboard
to bring it up.
Drag four labels and a text input field to the storyboard, arranged as follows:
In this example we have also added constraints to the layout. I’m by no means an expert on using Xcode constraints, but if I did it correctly the UI should look appropriate on the iPhone 5, 6, or 6 Plus. The layout should also rotate correctly.
Wire up the Text Field to the view controller as an IBOutlet. In this example I’ve named it textFieldToTranslate
. Also wire up the label where we’ll display our translated text. I’ve named it translatedTextLabel
.
Your IBOutlet
s in ViewController.swift
should look like:
[objc]
@IBOutlet weak var textFieldToTranslate: UITextField!
@IBOutlet weak var translatedTextLabel: UILabel!
[/objc]
Now, let’s add the appropriate delegate methods to the view controller so we can interact with the text field. This includes:
- Adding
UITextFieldDelegate
to theViewController
class declaration - Setting the
delegate
property of theUITextField
to the view controller - Adding the
textFieldShouldReturn
function to theViewController
class
I typically set the UITextField delegate
property in the view controller viewDidAppear
method, so let’s add that:
[objc]
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.textFieldToTranslate.delegate = self
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
[/objc]
We can compile and run our code as is, but of course it does next to nothing. Now, let’s wire up Alamofire to translate the text that is in the text field.
Using Alamofire
Alamorefire’s set up is a bit different than with Objective-C frameworks. The Alamofire Github repository currently states, Due to the current lack of proper infrastructure for Swift dependency management, using Alamofire in your project requires the following steps, followed by 7 steps to follow. We’re going to follow those here, with some additional detail provided.
Open a terminal (again, I like iTerm 2), and cd
over to your Xcode project directory. In our case we cd ~/projects/blogging/translator
, and use the git submodule feature to check the Alamofire code as a git submodule:
Now, with the Mac Finder, locate your project directory, navigate into the Alamofire folder, and drag-and-drop the Alamofire.xcodeproj
icon from the Finder window into the Xcode project.
You should now see something like this in your Xcode project:
Now, in Xcode, navigate to the target configuration window of Alamofire by clicking on the blue Alamofire project icon, and selecting the application target under the Targets heading in the sidebar. Ensure here that the Deployment Target of Alamofire is the same as the Deployment Target of the translator application. In our case, we are using a deployment target of 8.0.
Now, click on the translator project icon (the blueprint icon), select the translator target and in the tab bar at the top of that window open the Build Phases panel. Expand the Target Dependencies group, and add Alamofire
:
Finally, click on the +
button at the top left of the panel (right under the label that says General and select New Copy Files Phase.
Rename this new phase to Copy Frameworks, set the Destination to Frameworks, and add Alamofire.framework
.
And that’s all there is to it! Okay, so it’s a pain in the ass doing all that, but I find it worth the trouble. For a minute or two of drag-and-drop-and-configure we have an excellent API to begin making HTTP requests with.
Now that we have Alamofire added, let’s use it in our textFieldShouldReturn
function. Remember, textFieldShouldReturn
is going to get called when the user presses the action key on the iOS keyboard associated with our text field. First, add the statement import Alamofire
at the top of your ViewController.swift
file, like such:
[objc]
import Alamofire
[/objc]
Then, in textFieldShouldReturn
we’ll do the following:
[objc]
let textToTranslate = self.textFieldToTranslate.text
let parameters = ["q":textToTranslate,
"langpair":"en|es"]
Alamofire.request(.GET, "http://api.mymemory.translated.net/get", parameters:parameters)
.responseJSON { (_, _, JSON, _) -> Void in
let translatedText: String? = JSON?.valueForKeyPath("responseData.translatedText") as String?
[/objc]
We’re following the API at MyMemory for translating text from English to Spanish. Notice the simplicity of both the HTTP request with Alamofire as well as handling the response. .GET
is an enumeration for the HTTP method to use for the request, followed by our URL, and then a basic dictionary of URL parameters.
The MyMemory API call returns a JSON string, so we can utilize the Alamofire responseJSON
function to give us a JSON dictionary (it handles taking the JSON string returned in the body and converting it for us). Although it looks careless the method in which we are getting the translatedText
is good form. Since we declare translatedText
as String?
we are saying “This could be a String
or nil
.” Moreover, by using JSON?.valueForKeyPath()
we are saying, “JSON
could respond to valueForKeyPath
or it could be nil
“. If JSON
is nil
then it follows translatedText
will be nil
as well. If JSON
is not nil
and we find a value at the given key path responseData.translatedText
, then we have our translation available (which we’ll display in the label).
All of this code makes heavy use of chained optionals in Swift. For a refresher in Swift optionals in general, visit our post on the topic.
Once we have the translated text we update our view controller label:
[objc]
if let translated = translatedText {
self.translatedTextLabel.text = translated
} else {
self.translatedTextLabel.text = "No translation available."
}
[/objc]
Alamofire has a lot of features, and of course we’ve only scratched the surface. Take a look through the extensive documentation on Github; it’s all there, support for POST
and the remaining cast of characters, various authentication methods (eg., basic auth), uploading data, etc.
Let’s run our new application and translate Good night, friends! into Spanish.
Nice, it worked! Of course, my Spanish-speaking amigos will point out that the opening signo de exclamación is missing, but that can be corrected.
That’s it for today, I hope you enjoyed the tutorial. Again, if you’d like a working example visit the Bitbucket repository. After checking out the repository, make sure and run the following in your alamofire-translator directory:
1 2 |
git submodule init git submodule update |
Exercises for the Reader
You will no doubt notice that the application is only capable of translating from English to Spanish. MyMemory allows for any-to-any translation, why not add a popup menu to allow for choosing which language to translate from and to? And while the HTTP request is pretty quick there’s room perhaps for a progress indicator somewhere on the screen, as either a HUD or basic activity spinner.
Great article – it was most helpful.
I do have a related question that I would think would be quite common, but I cannot seem to find an answer to it anywhere. When I follow your instructions to add Alamofire as a submodule, and then change the Deployment Target in the Alamofire.xcodeproj file to match my project settings, the project file is obviously now dirty. What is the proper way to handle this from a SCM perspective? It seems creating a fork just for this is silly. How do you handle this?
Apologies in advance if this is a noob question ;(
I do see someone else asking the exact same question here http://stackoverflow.com/q/26695627, but alas no one has answered it.
Any assistance you can give would be greatly appreciated…
There is a broader tutorial here
– Basic: http://www.raywenderlich.com/85080/beginning-alamofire-tutorial
– Intermediate: http://www.raywenderlich.com/87595/intermediate-alamofire-tutorial
Thanks for the feedback!