Project 5 – Completion and Challenges

by | March 4, 2019

Project 5 – Completion and Challenges

Jeff Summers

March 4, 2019

This is a continuation of yesterday’s post where I talked about Project 5 in the 100 Days of Swift challenge. If you haven’t read that entry, this one may not make as much sense. Of course if you have read yesterday’s entry I cannot guarantee that this one will make sense either but I’m hopeful that at least some of the concepts are understandable.

As I mentioned yesterday, Project 5 is now beginning to include more advanced concepts in the assignments. Hopefully when I look back at this post at the end of the 100 Days of Swift challenge I will laugh at that statement and wonder why I ever thought this was an advanced concept using closures and their associated capture lists. Right now, I am one step removed from lying in the corner in the fetal position whimpering for mercy. But as my old gym teacher used to say, “Get up that rope before I tie it around your scrawny neck!” (He was a master at positive reinforcement and compassion.)

The project itself was not too bad and I am starting to anticipate some of what is needed within the classes and functions before Paul Hudson actually starts describing the code. That’s the positive side of things. I will admit, as we were working through the submitAction portion of the promptForAnswer function where we were using closures with weak capturing, I started getting that eye twitch that I got when it was almost my turn to climb the rope in gym class. I am still holding out hope that Paul is right and that through repetition some of this will finally sink in and remain in my brain for longer than it takes to heat a Pop Tart in the toaster.

Through blind obedience and trust that the closure would work, I followed along and wrote the code. I did make a few mistakes and was kind of proud of myself for actually finding what I did wrong (with some help from Xcode of course). In the end I had a working word anagram game.

When I arrived at the Wrap Up at the end of the project I was feeling a little confident that this one would go better than my challenges with Project 4. With a slight bit of apprehension, I looked over the first challenge.

Challenge 1 was to disallow answers from the user that were shorter than 3 characters. Looking at that I immediately knew that I would need to make changes to the isReal() function we created to determine if the user had typed in a real word. This was even before Paul gave the hint which acted to reaffirm that just maybe I was starting to get it. Since Swift 4 can give us the length of a string using the .count suffix, this one was pretty straight forward:

if word.count < 3 { showAlert(title: "Word too short", message: "Words must be at least 3 characters long.") return false

Basically this code will look at the user-entered word (named unimaginatively “word”) and see if the length is less than three. If it is then it displays an alert box with the appropriate message. The “return false” line will make sure the too short word is not included in the answer. It should be noted here that I am tipping my hand with the “showAlert” function as that is Challenge 2.

For Challenge 2 we were to refactor (rewrite in layman’s terms) the rather wordy if...then...else statements where we check if the user entered a word already used, a word made up of the characters in the word they were given (is it really an anagram) and is it a real word. In each test if it fails it will call a new function called showAlert() to display an alert box giving the user feedback.

The function requires two parameters. First is the title to be displayed in the alert box. The second is the actual message to be displayed in the alert box. As you can see from the code example above, if the user entered a word too short the alert box would appear with the title “Word too short” followed by a message, “Words must be at least 3 characters long.” Pretty simple really. The function code is:

func showAlert(title: String, message: String) {
let ac = UIAlertController(title: title, message: message, preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default))
present(ac, animated: true)

}

In this code “ac” is the constant that calls an Alert Controller. We pass it the title and the message that came from the call and the “.alert” in preferredStyle says we want an alert box. The ac.addAction tells it we want a button with the word “OK” in it styled in the default style. We then present the Alert box and we are done.

The final challenge, Challenge 3 asked that we create a left bar button at the top of the screen allowing the user to request a new word. This too was fairly straight forward since we had created buttons in the navigation area of view controllers in several past projects so my confidence was fairly good I could do this.

This took adding one line in the viewDidLoad() function for when a view controller is loaded. The code for that was:

navigationItem.leftBarButtonItem = UIBarButtonItem(title: "New Game", style: .plain, target: self, action: #selector(startGame))

In this code we create a button using navigationItem telling it we want it on the left. That item is a button with the text label of “New Game”. When the button is tapped, we make a call to our startGame function which gives the user a word and resets the used word array and refreshes the screen.

All in all, the challenges went pretty well and my confidence went a tick higher (as long as I didn’t think too hard on the closure and capture list portion which is still shrouded in a thick brain fog.

Paul gave us one bonus challenge in Project 5, one I am still pondering. Not because I couldn’t do it but because I didn’t do it in a way that Paul was hinting at and I am not sure where he was going. This bonus challenge stated that the game had a bug in it. If a user entered a three-letter word capitalized the system would take it. If a user, then entered the same three-letter word this time not capitalized the system would take it too.

I validated the error did exist (not that I don’t trust Paul but given my history with test data you can’t be too careful). The obvious answer to me was to always make sure that answers were stored at lowercase then any subsequent check if a word was used would account for case differences. This did require me to modify the code with the (shudder) closure in it, but you have to face your fears. Besides, the change I was making would not cause a disturbance in the closure force. The code becomes:

let submitAction = UIAlertAction(title: "Submit", style: .default) { [weak self, weak ac] _ in
guard let answer = ac?.textFields?[0].text else { return }
self?.submit(answer.lowercased())
}

Since all I was doing was modifying the submit, I felt confident. Instead of passing that function the answer as typed, I used “answer.lowercased()” which always provides the answer in lower case. This mandates that all words in the usedWords array are in lower case therefore will not allow case changes to trick the system.

That code does what Paul was asking so I think technically I solved the problem. Where I was still a little stumped was that he sent us looking at the line: “usedWords.insert(answer, at: 0)”. Oh my heck! It just dawned on me that we are inserting into the usedWords array using answer and not lowerAnswer which we are using everywhere else! Ug! Sometimes it is the simplest things.

So, I guess I was on the right path. I just chose to make the string lowercase before sending it whereas Paul was suggesting doing it at the time you insert it into the array. This boys and girls is why it is important to write about your experiences, you never know what may trigger your mind into looking at a problem or a solution.

This is definitely going into my troubleshooting repertoire. When I have a problem that is kicking my butt and I am not making headway, write it down along with the steps or instructions given. Or if writing is not your thing, try and explain it to someone else. You may just have the epiphany you need to solve it. If not, perhaps others can help you find the problem or solution. I can’t believe I missed that.

Share this Article

Posted by Jeff Summers

Author, technologist, and baseball aficionado specializing in information technology and developing new and creative ways to interact with the world around us. My goal is to extend the boundaries of what is possible and find ways to make the world a better place while having fun.

0 Comments

Submit a Comment

Your email address will not be published. Required fields are marked *

Stay Connected

Search

More Articles

Pace Layered Architecture Categorization

Change is inevitable. Today’s computing environments are constantly in flux from internal and external forces that put demands on the systems and necessitate changes to maintain its value stream. Technology currency is a constant struggle that organizations must...

TBM, Another Holy Grail?

Technology Business Management or TBM as a term was coined around 2012 although many of the concepts making up this framework have been around for almost as long as there has been IT. In its simplest form, TBM represents the integration of business, technology, and...

Visionary or Dreamer?

Thinking back over your life you’ve met and worked with countless personality types. You have been a part of teams that struggled to complete simple tasks and the work felt meaningless. Perhaps your goal in these times was to just trudge through the mud hoping the...

Archives