WWDC22 SALE: Save 50% on all my Swift books and bundles! >>

SOLVED: Day 18: Project 1 Wrap Up: Extra Challenge

Forums > 100 Days of SwiftUI

It has been very exciting to get started with SwiftUI, make an actual app and run it in the simulator! I think I did OK and I solved the three challenges without much trouble.

However, I'm completely lost with the extra challenge, that is storing the currency formatter inside a property. Any hints on how I should approach this? Or is there a certain topic I should revisit to get closer to the answer?

2      

SPOILERS Ahead!

This is a four part answer. Each part should take you closer to a solution. Read one at a time and see if you can solve on your own. Or return for more hints.

Part I

You should be quite comfortable with basic properties such as Strings and Integers, yes?

let answerToTheUltimateQuestion = 42  // integer property
var lastName = "Dolphins"  // string property

You're assigning a value to a name. This way, in your code whenever you need a user's last name you use the variable "lastName" rather than hand typing it each time. There's a danger that 99 times you will type "Dolphins", but late one night you will type "D⚬lphins" instead.

So @twostraw's lesson seems to be: Review your code and Remove redundancies. Remove the parts of your code that are pure duplicates and are used elsewhere. Here's the example:

// See the redundant code?
Text(checkAmount, format: .currency(code: Locale.current.currencyCode ?? "USD"))
// and
Text(totalPerPerson, format: .currency(code: Locale.current.currencyCode ?? "USD"))

He asks the question Can you make a new property to store the currency formatter?

The goal then is to create a property, let's call it dollarFormatter, so you can re-use it everywhere in your Tip calculator where you want to format a Double value to look like currency.

// Goal:
Text(checkAmount, format: dollarFormat))
// and
Text(totalPerPerson, format: dollarFormat))

So you might ask yourself, "Self? What is format? Is it a String? Is it an Integer?" How do you as a Day 18 coder find out this answer? This is an IMPORTANT skill for you to have!

3      

Part II

Move your mouse over the .currency key word in the original code and hold down the option key. The cursor changes to a question mark. ❓

Click the .currency keyword and open the Developer Documentation.

This is another skill for you to develop. Learn how to read these signatures!

static func currency<Value>(code: String) -> FloatingPointFormatStyle<Value>.Currency where Value : BinaryFloatingPoint

This tells you that currency is a function that modifies some value, where the value is a BinaryFloatingPoint. How does it modify the value? It needs a code (a string) to tell it how to modify the value. The documentation also tells you the function returns a type. (Note: the type is not something simple, like a string!)

The type is complex and named FloatingPointFormatStyle<Value>.Currency In fact this is a Struct. See the documentation for more detail! The other hint @twostraws gives is that <Value> is a placeholder for any type of value. However, in your solution, you really want a Double.

@twostraws gives you this hint. So with this you can at least stub out your new property.

// Creating a new property with a special type. For this app, we want it to work with Doubles.
var dollarFormat : FloatingPointFormatStyle<Double>.Currency {
   // Magic spell here
   // not sure what goes here, but we KNOW we need to return a FloatingPointFormatStyle.
   return FloatingPointFormatStyle<Double>.Currency( === something goes here === )
}

Getting close!

3      

Part III

Notice that in the original solution, the format code in Text requires a parameter named code?

// the currency func has a required parameter named code. 
// Dig into the documentation and see this is a String.
format: .currency(code: Locale.current.currencyCode ?? "USD"))

You could just hard code the string "USD". But generally this is a bad practice. You should really let your users decide what currency they use, and they will log their preference in their device. So @twostraws shows how to grab the user's preference.

Locale.current.currencyCode But this returns an optional (after all, your user maybe didn't actually record a preference.) So use the nil coalescing operator to default to "USD".

Fine, this is one more step you can put into your new reusable computed property.

// Creating a new property
var dollarFormat : FloatingPointFormatStyle<Double>.Currency {
   let currencyCode = Local.current.currencyCode ?? "USD"
   // more magic here.
   return FloatingPointFormatStyle<Double>.Currency( === something goes here === )
}

3      

Part IV. Final Step.

You've used Apple's documentation to research the pieces. You broke a bigger problem into several smaller steps. And you're almost done. What part is missing?

Your goal is to return a format style initialized to be some sort of currency. How do you initialize that Currency struct?

var dollarFormat : FloatingPointFormatStyle<Double>.Currency {
   let currencyCode = Local.current.currencyCode ?? "USD"
   // How do you initialize the Currency struct?
   return FloatingPointFormatStyle<Double>.Currency( === something goes here === )  // HOW do you initialize this?
}

Again, you need to dive into the documentation. Get comfortable with this! Make this skill a GOAL.

Let your mouse hover over the word Currency in your code and hold down the option key. When your cursor turns into a ❓click the word and open the documentation.

You'll see more information about this struct, scroll down until you find the initializers. Do you see any that use currency codes? Yes?

Voila! You can now finish your new computed property.

var dollarFormat : FloatingPointFormatStyle<Double>.Currency {
   let currencyCode = Local.current.currencyCode ?? "USD"  // Get user's preference, or use default
   return FloatingPointFormatStyle<Double>.Currency( code: currencyCode )
}

Now you have a reusable property you can use in your solution. Try it!

// Day 18. Extra credit challenge
// Make a new property to store the currency formatter.
// for: @hyperDolphins
// by:  @Obelix
// Copy-paste into Playground
import SwiftUI
import PlaygroundSupport
var dollarFormatter : FloatingPointFormatStyle<Double>.Currency {
    let currencyCode = Locale.current.currencyCode ?? "USD"
    return FloatingPointFormatStyle<Double>.Currency(code: currencyCode)
}

struct dollarView : View {
    var checkAmount = 7132.42  // note! using a Double. Will this work with an Integer?
    var body: some View {
        Section {
            // Which version is more declarative?
            Text(checkAmount, format: dollarFormatter)
            // verify against previous version...
            Text(checkAmount, format: .currency(code: Locale.current.currencyCode ?? "USD"))
        }
    }
}

// Show SwiftUI views in Playground
PlaygroundPage.current.setLiveView( dollarView() )

// expected results:   $7,132.42
// Try with different currencies!

4      

Hi @hyperdolphins

In the extra challenge you were given this FloatingPointFormatStyle<Double>.Currency as a hint this is type. So you could do

let localCurrency: FloatingPointFormatStyle<Double>.Currency = 

then when you put the dot your will get.currency(code: String) and you then can replace the String with Locale.current.currencyCode ?? "USD" so end up with

let localCurrency: FloatingPointFormatStyle<Double>.Currency = .currency(code: Locale.current.currencyCode ?? "USD")

Then use that any where require localized currency

Text(grandTotal, format: localCurrency)

2      

Thanks for the replies to both of you! It seems I was already on the right track yesterday but messed up something in the syntax. I managed to write a crude but working version after Obelix's second hint.

And @Obelix yes, I did study the quick help and developer docs, actually I have been checking the official Swift documentation regularly for some time now. :) But as a beginner I often find it hard to understand. It's highly technical and English is not my native language so many of the terms are something I need to look up. And it has been very hard to find an up-to-date dictionary for programming and computer science, between English and my language. Paul's Swift glossary sometimes helps, though.

And thanks for revealing how to handle and display SwiftUI stuff in the Playground! Earlier today I was wondering if it's possible.

Anyway, I'll play around with this for a while and then I'm off to tackle Challenge 1.

1      

Thanks to you both!

   

Save 50% in my Black Friday sale.

SAVE 50% To celebrate WWDC22, all our books and bundles are half price, so you can take your Swift knowledge further without spending big! Get the Swift Power Pack to build your iOS career faster, get the Swift Platform Pack to builds apps for macOS, watchOS, and beyond, or get the Swift Plus Pack to learn advanced design patterns, testing skills, and more.

Save 50% on all our books and bundles!

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.