DEV Community

Monty Harper
Monty Harper

Posted on

5 Lessons Gleaned and Memed from Making My 2nd iOS App

Huzzah! I just turned in my second major assignment in the Udacity iOS Developer nanodegree program. I had to create a meme-making app called Mememe. I didn't try to live-blog it, but I did take notes, and the app is fun to play with, so here we go... five lessons gleaned and memed!

  1. Avoid Rabbit Holes
  2. Sometimes the Obvious Hack is the Right (or Wrong) Answer
  3. Sometimes an Inelegant Solution Is All You Need
  4. Be a Detective (Print Statements Are Your Friend)
  5. When You Hit a Wall, Find a Door

Lesson One - Avoid Rabbit Holes

Alice falling down the rabbit hole with the caption

My first task was to set up two text fields with specific formatting for the text. After learning how to set the stroke value to give the text a solid color (It hast to be negative - Who knew?) plus how to specify centered text, all caps, font and point size, here's the question I posed in my notes:

"Why are some text attributes applied using an NSAttributedString array for the defaultTextAttributes property while others, like alignment and capitalization, can only be applied separately using their own properties?"

It's a good question, and I spent too much time researching it before I concluded that the answer is, "Don't worry about it!"

I've gained a little more perspective, looking back. For one thing, this is UIKit stuff, and apparently SwiftUI is the hot new thing, so I'll likely be learning how to do all this again in SwiftUI. Plus unless I end up writing apps where text formatting is a big deal, I don't need to delve into those details.

I tend to want to understand every little thing as I go, but progress is also important. As I gain experience I'll make better judgements about when to spend the time and when to move along. I can always come back and pick up more details if/when I actually need them.

Lesson Two - Do Not Rename Your Xcode Project!!

Or...

Rube Goldburg complicated contraption with caption

The video instructions suggested I start an app called "Experiment" just to mess around with learning the skills I would need to make the Mememe app. It was never clear to me when to start the actual app, so by the time we got to that, I practically had the whole thing done in my "Experiment" project.

So I did the "obvious hack" and re-named my folder (sorry -> directory), "Mememe 1.0." Well, guess what? Xcode DID NOT TAKE KINDLY TO THAT! Just renaming the app broke it badly; it would no longer compile.

You're probably thinking I captioned my meme wrong by now - it should say "Sometimes the Obvious Hack Is the WRONG Answer."

Bare with me. I spent a huge amount of time trying to fix this mistake by chasing down error messages and changing text in the various files. I kept thinking, one more fix and it'll run. But it never did. Somewhere deep in the bowels of the project, some needle was monkeying up the whole haystack. (Metaphor salad, anyone?)

I started to gird myself for a long and futile online search to figure out how to fix this mess when a simple solution occurred to me - a new hack to fix the old hack. I opened a new project with the name I wanted. Then I copied the text from each of the files in the old project and pasted it into corresponding files in the new project. That got me up and running in moments. See? Sometimes the obvious hack is the right answer.

Lesson Three - Sometimes An Inelegant Solution Is All You Need

Or...

Man driving an odd tiny red car, the top of which is a glass bubble, with the caption

One of the requirements of this project was that we move the lower text field up out of the way when the keyboard shows on screen. The solution they gave was to retrieve the height of the keyboard and move the entire view up by that amount.

I thought applying this to one specific text field and moving the screen up based on just the keyboard height while ignoring the text field placement seemed clunky. It's a solution that only works based on the particulars of this layout.

So I got fancy and wrote a function to calculate what size nudge it would take to park any given text field exactly on top of the keyboard. I could not get my numbers to work out correctly.

I dove right down that rabbit hole. I learned a lot about relative coordinate systems within different views, but I never could get my calculations to work. I suspect it had to do with the view's auto-formatting moving things around.

I was tempted to attempt an auto-constraint solution, using the keyboard template, which seems like a much more elegant idea, if it would work. But... constraints are my nemesis!

In the end I went back to what the lesson told me to do in the first place. (I also added in a boolean variable to track whether the view was up or down so I wouldn't inadvertently move it up twice.)

It seems like a cobbled together solution to me, but it works. I'll think twice next time I'm tempted to make the code pretty, especially if it doesn't really affect the user's experience or the app's functionality or readability. If it works, it works!

Lesson Four - Be a Detective

Or...

Photo of my unkempt self looking like Shaggy with the caption

Yeah, that's me during COVID.

This project taught me out of necessity how to hunt down villains using strategically placed print statements to provide essential clues. Printed lines aren't visible from within the app, but Xcode displays anything that gets printed when the app is running on a simulator or connected iPhone.

Print statements can tell you when a particular piece of code runs as well as what values the variables hold at a given point. They can tell you whether an if statement executes or a function is called.

I used this method to solve several mysteries, including The Case of the Double Jumper (alluded to parenthetically above) and The Case of the Mutating Text Field:

I had placed code in my "ViewDidLoad" function to set placeholder values for my text fields. Those shouldn't have changed, but now and then, under mysterious circumstances, the placeholder text would suddenly match the current text in the fields.

The only place in my code where those values were ever set was in "ViewDidLoad," which I knew in my heart was only called once at startup seeing as how this was a single-view app. So what was happening - impossible!

Imagine my surprise when a print statement revealed that the ViewDidLoad function was in fact called multiple times! A quick check with ChatGPT provided the explanation: the view had to be re-drawn whenever the device switched between portrait and landscape modes. Seems obvious to me now! But it weren't for that well-placed print statement I still wouldn't have a clue.

Lesson 5 - You Will Not Be Stuck Forever

Or...

Alice reveals a hidden door behind a curtain. Caption reads

This lesson applies to all the problems I ran into. But my biggest frustration came at the end. I had everything working great, except when I turned the phone to landscape mode, my toolbar disappeared.

The app is required to work as expected in landscape and portrait mode. So this needed to get fixed!

I spent hours. There seemed to be no information online about this problem. Chat GPT was giving me nonsense suggestions that led nowhere. I suspected my nemesis, the dastardly constraints! So I poured over them to no avail. Last night I went to bed thinking I'd never ever ever figure it out.

This morning I read through the project's rubric out of desperation. I needed to be doing something - it's all about showing up, right? So I figured I could at least make sure my app was meeting all the other requirements (yes). And there it was! Right in the friggin project requirements!! The image view content mode needed to be set to "aspect fit." I had it on "aspect fill." Duh, right?

However, making that fix left empty space around the image in landscape view. I quickly devised a creative solution and spent the morning enabling the user to apply two different crop frames - one for portrait mode and one for landscape.

Then I finally turned that sucker in!

There's always a solution. Keys to finding it include: be persistent, get rest, approach with fresh eyes, ask questions, and do what you CAN do. The solution will eventually present itself!

That's It

Well, not really. I learned a lot more making this app. But these five things are plenty enough to write about. To recap:

  1. Don't go down un-necessary rabbit holes; come back for the details when you actually need them.
  2. Sometimes the obvious hack is what you need; sometimes it's very much not. That sounds unhelpful. How about: Got a simple solution that seems too good to be true? Don't discount it, but do think twice. Or maybe just: NEVER EVER EVER rename an Xcode project!
  3. Sometimes an inelegant solution is all you need. Before you put in the effort to beautify it, ask yourself, will this make the app work better? Will it be easier to follow? Will it make the user experience better? If there's no reason to fix it, let it be.
  4. Become a detective! Use print statements to figure out what's going on inside your code.
  5. When you hit a wall, find a door. Take a break, do what you can do, put in the time, and you'll get there.

I hope these serve you well. I know they will me, if I manage to keep them in mind. The memes should help. If you're interested in checking out the app for yourself, it's here on GitHub: Monty's Mememe 1.1

Top comments (4)

Collapse
 
danielrendox profile image
Daniel Rendox • Edited

It was very interesting and fun to read about the lessons you learned. That's because I encountered all of these problems too (I still encounter them)!

I'm the one who prefers a project-based approach either. I usually follow tutorials in my own way. That's a nice way of learning because it motivates you and forces you to use the gained knowledge in practice.

However, this approach is what makes us face up to lots of problems that we need to solve on our own.

Not long ago, I was working on a codelab and the result wasn't similar to the one provided there. The theme corols of the app were different. I spent a lot of time googling and trying to find out why. And guess what? I come back to the tutorial and see the explanation of this "phenomenon" in the next phrase that I hadn't read for some reason.

So don't be afraid to get off the beaten track and solve problems in your way. But don't get too far.

And one more thing. I'm an Android developer. I'm not familiar with Xcode, but I think your IDE should provide a function that allows renaming your project. The IDE will automatically change all the files needed as it can do for renaming variables, classes, etc. This is called refactoring. Renaming your project is still not a good idea though.

Collapse
 
montyharper profile image
Monty Harper

Hi Daniel, thanks for the feedback! I too have gone on little side adventures only to find the problem mentioned later in the tutorial, or even earlier on a page I had forgotten. I'm afraid I didn't learn my own lessons too well in the next project; I spent more time than I probably should have diving into rabbit holes, but you're also right that it's a great way to learn. It's difficult finding that sweet spot between too much self exploration and not enough. I can't believe I didn't think to google "how to change the name of an Xcode project" - just did, and... well a quick glance at the results tells me it's a somewhat complicated multi-step process. So I feel a bit vindicated, but I will definitely dive into this again when I can. Thanks for the encouragement there. It's something I should know how to do, for sure!

Collapse
 
jmfayard profile image
Jean-Michel πŸ•΅πŸ»β€β™‚οΈ Fayard

5 things that are apply to way more than iPhone programming by the way :)
Transferable skills for the win

Collapse
 
montyharper profile image
Monty Harper

Thanks for that, Jean-Michel! Very validating. I know I can't offer expertise on Swift or iOS yet, so I'm trying to write about my experience in a way that might be helpful to a wider audience of learners.