Build an Ethereum/Bitcoin price tracking app in Swift (Part 1)
Ethereum, Bitcoin, and cryptocurrencies at large have been exploding in value lately. Even if you’re not invested in cryptocurrencies yourself now is a great time to learn how to program apps that leverage them.
Today we will be building a very simple Ethereum/Bitcoin price tracker in Swift 4 using Xcode 9. To get started download the base project here then open “CryptoTracker.xcodeproj”.
Try running the app (⌘+R) in the iOS Simulator and you’ll notice the text “$0.00” with “Ethereum Price” under it. If you select “Main.storyboard” from the projects pane on the left-hand side you’ll see we have a horizontally and vertically aligned stack view with the two labels. Select the “$0.00” label and reveal the connections inspector (⌘+⌥+6) and you’ll see it has a @IBOutlet
connection to “ViewController.swift” with the name etherValueLabel
. We will edit this label with the real value of the currency later.
Getting Connected
Our price tracker wouldn’t be very good without up to date information on prices. The best way to get this information is through the use of an API, and CryptoCompare has a great one that supports numerous types of currencies.
For now, we want to use it to make an API call to get back Ethereum’s price in USD so we can display that in our app. Open up “ViewController.swift” from the projects pane and add the following below the etherValueLabel
@IBOutlet
at the top of the file:
let apiURL = URL(string: "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD")
This is the API URL
we will be connecting to in order to fetch the data we now read to write a GET request in order to retrieve the latest price information from this URL
. Add the following function below the didReceiveMemoryWarning
function:
Our function takes in a URL
and has a completion block which returns an optional value. We will send this information back later when we complete our request or send back nil
if there is an error.
On the first line, we perform a basic dataTask
request that takes in the URL, this is done using Apple’s URLSession API. It returns data from the call, a response(which returns information about the call that was made), and an optional error in the event of failure.
We also do request.resume()
at the end which actually starts the call. Up to this point though we are not doing anything with the information returned from the call, so replace the TODO
with the following:
This confirms that the data we got back isn’t nil
and that there weren’t any errors. In the else case we send back nil
since no data was found and try to print the error, for safety we unwrap it using ?
to get back a description of the error and if no description is found we just print an empty String
. The error should never be nil
in this case but using optionals is a good habit to get into for writing safe code.
Now we have the data safely unwrapped and made sure there aren’t any errors, now its time to fetch the USD value from the JSON response we got back from the server. To do so add the following underneath the guard block we just added:
In order to read the JSON data in Swift, we use the JSONSerialization class from Apple, which takes JSON data and converts it into a dictionary which can be read in Swift. This must be done using a Swift try-catch block, which is why we need to add do at the beginning and catch to handle an error in the case that we aren’t able to get back the JSON data.
Once we have the dictionary we can start reading values, inside the JSON dictionary is the key “USD” which contains the US price of Ethereum as a number so we cast that value to NSNumber
.
If for whatever reason we can’t get back the value we pass nil
to the completion block again and return. If we do get the value back safely though we pass it to the completion block.
Next, we’ll write a small helper function that takes the value number and formats it to a US currency string. Add the following underneath the makeValueGetRequest
function we just wrote:
NumberFormatter is a class from Apple that takes numbers and represents them in various text formats. By setting the locale
to en_us
and the numberStyle
to .currency
we can use the NumberFormatter
to represent the value in US dollars.
Now we need to unwrap the value passed into the formatAsCurrencyString
function to ensure it’s not nil
and format it using the NumberFormatter
instance we just created.
We unwrap the value using a guard and use the NumberFormatter
string function which takes a NSNumber
and converts it to a String
following the formatter’s rules (which here was that we print a currency style String
using US values). At the end, we return the formattedCurrencyAmount
String
which we can use to print that value on the screen.
Great! Now we can get a numerical value back from the API and we can format that value into US dollars. All that we have to do now is make the request and populate the on-screen etherValueLabel
with the value.
Recall that in the beginning, we added the following line to store the URL
for the CryptoCompare API:
let apiURL = URL(string: "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD")
Now we want to use that URL
to make a GET request for the data. Before we can use that URL
though we first have to unwrap its value. By default, URL
objects initialized with a String
are optional since the URL
could potentially return nil
if the String
resolves to an invalid web address.
To do so add the following under super.viewDidLoad()
in your viewDidLoad
function:
A quick, simple guard statement ensures apiURL
on the left-hand side is safely unwrapped and ready to be used to fetch that data.
Recall that earlier we created the makeValueGETRequest
function which takes in a URL
and has a completion block that returns the value of Ethereum as a number.
We can pass in the now unwrapped apiURL
then we can use that formatAsCurrencyString
function to convert that value to a String
in US dollar currency format. Finally, we can display that String
on the etherValueLabel
so the user’s of our app can see it.
We call the makeValueGETRequest
function we created earlier with our now unwrapped apiURL
and get back value
in NSNumber
format which represents the cost of 1 ETH in US dollars.
For the next part, we have to use a DispatchQueue, a class provided by Apple to deal with multithreading. The makeValueGETRequest
performs the GET request in the background so that it won’t interrupt the main thread, which is used by iOS to update the UI on the screen. By doing this work in the background we can avoid interrupting any interface changes with our GET request.
To get back to the main thread using DispatchQueue we use DispatchQueue.main.async
a method that creates a block where we can update the UI on the main thread after coming back from a background operation.
Once inside we assign the etherValueLabel.text
with our value for 1 ETH in US dollars. The ??
after the formatAsCurrencyString
is known as nil coalescing which means since formatAsCurrencyString
returns an optional String
(either the US dollars value or nil
in the case of a failure), the ??
acts as an OR clause essentially which in the case of failure will simply print the String
“Failed” to the user.
Whenever you’re dealing with API’s it’s always good to handle failure gracefully, there are many ways to do so and the nil coalescing operator is certainly a handy tool to keep in mind.
Try running the app (⌘+R) and you should now see the value of 1 ETH!
Whats Next?
You can download the final version of this project with some added comments here.
Update: part 2 is out now! Go check it out to learn how to build a more robust price tracker with Bitcoin, Ethereum, Litecoin, Monero, Ripple, and NEO support!