iOS Swift – Building a Times Tables App – Part 1

Previously, we built an Android times tables practice app in Kotlin, as well as a backend-only web times tables app in Python. Today we’re going to port this app to Swift so it can work on iOS for an iPhone as well. Let’s get started!

At the time of writing, this was done in Xcode 12.5.1 and Swift 5.4.2. All the code for this app can be found on my github account:

https://github.com/jamesmcclay/swift_times_tables

Create a project in Xcode

We’re going to create an iOS app in Xcode, so make sure you select “iOS” in the Xcode new project window:

Xcode New Project Window

There are, in fact, many different ways to write an app in Xcode/iOS/swift. As a matter of complete personal preference, I like doing everything “programmatically”. In iOS development you have two choices: use Interface Builder or programmatically. Interface Builder uses the story board to create UI objects/elements, while programmatic creates the same elements from swift code without using Interface Builder. I happen to prefer the latter.

The only thing that is really difficult to create from code is a UIViewController, so I typically add those from the storyboard. Since Apple gives us the first UIViewController, we’ll jump right into creating the UI elements.

Create the UI objects

We’ll first create global variables to hold our UI elements so we can access them from anywhere in the class, like this:

let mainLabel:UILabel
let subLabel:UILabel
let tableInput:UITextField
let multiplierInput:UITextField
let normalMode: UISwitch
let normalLabel: UILabel
let randomMode: UISwitch
let randomLabel: UILabel
let startButton: UIButton
var modes: [UISwitch] = []

I’ll explain what each one does:

  • mainLabel: a title-like piece of text to show the name of the app.
  • subLabel: some text that tells the user to enter a table or leave it blank to practice all tables.
  • tableInput lets the user select a specific table to practice.
  • multiplierInput lets the user specify how far up they want to practice. The default is to practice to 12, but this input allows it to be configured.
  • normalMode: a switch for “normal mode” which practices in sequence.
  • normalLabel: a label attached to the switch saying “normal mode”.
  • randomMode: a switch for “random mode” which practices randomly.
  • randomLabel: a label attached to the switch saying “random mode”.
  • startButton: the button to begin practicing.
  • modes: an array to hold the two switches, more on that in the next post.

Now that we have these created, we’ll add a couple of functions that allow us to create objects to put in these variables, without ever touching Interface Builder. They look like this:

convenience init() {
    self.init()
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

I won’t go into how these work, as it’s a bit distracting from the app building. Suffice to say they let us create UI objects programmatically.

Our objects can be created in the required init? function before the line with super.init is run. The way I typically create objects is using closures, which is just a function without a name. You can assign whatever the closure returns to a variable. So I just create a bunch of closures that create the objects and assign them to the global variables. This next bit is long, but it’s just a bunch of boilerplate creating these elements/objects the way that I wanted them. The required init? function now looks like this:

required init?(coder aDecoder: NSCoder) {
    mainLabel = {
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.text = "James McClay's Times Tables!"
        label.numberOfLines = 2
        label.textAlignment = .center
        label.font = UIFont.preferredFont(forTextStyle: .largeTitle)
        label.adjustsFontForContentSizeCategory = true
        return label
    }()
    subLabel = {
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.text = "Enter a table to practice,\n or blank for all:"
        label.numberOfLines = 2
        label.textAlignment = .center
        label.font = UIFont.preferredFont(forTextStyle: .title2)
        label.adjustsFontForContentSizeCategory = true
        return label
    }()
    tableInput = {
        let input = UITextField()
        input.translatesAutoresizingMaskIntoConstraints = false
        input.placeholder = "All Tables"
        input.borderStyle = .bezel
        input.keyboardType = .numberPad
        return input
    }()
    multiplierInput = {
        let input = UITextField()
        input.translatesAutoresizingMaskIntoConstraints = false
        input.placeholder = "Max Multiplier (12)"
        input.borderStyle = .bezel
        input.keyboardType = .numberPad
        return input
    }()
    normalMode = {
        let mode = UISwitch()
        mode.translatesAutoresizingMaskIntoConstraints = false
        mode.tag = 0
        return mode
    }()
    normalLabel = {
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.text = "Normal Mode"
        label.font = UIFont.preferredFont(forTextStyle: .body)
        label.adjustsFontForContentSizeCategory = true
        return label
    }()
    randomMode = {
        let mode = UISwitch()
        mode.translatesAutoresizingMaskIntoConstraints = false
        mode.tag = 1
        return mode
    }()
    randomLabel = {
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.text = "Random Mode"
        label.font = UIFont.preferredFont(forTextStyle: .body)
        label.adjustsFontForContentSizeCategory = true
        return label
    }()
    startButton = {
        let button = UIButton(type: .system) as UIButton
        button.translatesAutoresizingMaskIntoConstraints = false
        button.titleLabel?.font = UIFont.preferredFont(forTextStyle: .title2)
        button.titleLabel?.adjustsFontForContentSizeCategory = true
        button.setTitle("Start!", for: .normal)
        return button
    }()
    super.init(coder: aDecoder)
    modes = [normalMode, randomMode]
}

modes = [normalMode, randomMode] is put after super.init because that’s where self is created. I’ll use that array to make sure only “normal” or “random” mode can be selected, both.

Now that we have all those elements created, let’s lay them out on the view.

Using autolayout to put objects on the view

All of the elements created above have translatesAutoresizingMaskIntoConstraints set to false, which means that Autolayout is turned on. Autolayout basically allows a swift developer to put UI elements on the view and have their position dynamically calculated based on the view size and their relative position to other elements.

The way I like to do this is to write a function to hold the code for each logical area, and call each function from viewDidLoad. So my viewDidLoad looks like this:

override func viewDidLoad() {
    super.viewDidLoad()
    self.navigationController!.navigationBar.isHidden = true
    setupLabels()
    setupInputs()
    setupModes()
    setupStartButton()
}

First we’ll set up the “labels”, the main one and the sub one. My setupLabels function looks like this:

func setupLabels() {
    view.addSubview(mainLabel)
    view.addSubview(subLabel)

    mainLabel.topAnchor.constraint(
        equalTo: view.safeAreaLayoutGuide.topAnchor,
        constant: view.frame.height * 0.1
    ).isActive = true
    mainLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    mainLabel.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.8).isActive = true

    subLabel.topAnchor.constraint(
        equalTo: mainLabel.bottomAnchor,
        constant: view.frame.height * 0.04
    ).isActive = true
    subLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    subLabel.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.7).isActive = true
}

I really hate how complicated this looks, because it’s not complicated. The autolayout code here is doing just a few basic things:

  • Add the UI element to the view as a subview (it puts the element on the screen).
  • Anchor its y-axis, usually by putting a constraint on the topAnchor. I usually give a constant with that one as well to provide some dynamically-created spacing, with view.frame.height * 0.1.
  • Anchor its x-axis, a lot of times it can just be constrained to the view.centerAnchor.
  • Anchor the width, usually to a percentage of the main view.

Once those constraints are in place, the element will properly show on the screen. That’s really all that’s happening here. If you have any questions, please comment or contact me!

Now let’s create setupInputs:

func setupInputs() {
    view.addSubview(tableInput)
    view.addSubview(multiplierInput)

    tableInput.topAnchor.constraint(
        equalTo: subLabel.bottomAnchor,
        constant: view.frame.height * 0.04
    ).isActive = true
    tableInput.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    tableInput.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.4).isActive = true

    multiplierInput.topAnchor.constraint(
        equalTo: tableInput.bottomAnchor,
        constant: view.frame.height * 0.02
    ).isActive = true
    multiplierInput.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    multiplierInput.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.4).isActive = true
}

You might have noticed this looks very much like setupLabels. That’s because autolayout requires a great deal of boilerplate but necessary code. I haven’t found a good way to reduce the plates on my boiler for this kind of code, so I end up with a fair amount of it when laying things out programmatically.

Now let’s create setupModes:

func setupModes() {
    view.addSubview(normalMode)
    view.addSubview(normalLabel)
    view.addSubview(randomMode)
    view.addSubview(randomLabel)
    
    normalMode.topAnchor.constraint(
        equalTo: multiplierInput.bottomAnchor,
        constant: view.frame.height * 0.04
    ).isActive = true
    normalMode.leadingAnchor.constraint(equalTo: tableInput.leadingAnchor).isActive = true
    normalMode.addTarget(self, action: #selector(modeTapped), for: .touchUpInside)
    
    normalLabel.leadingAnchor.constraint(
        equalTo: normalMode.trailingAnchor,
        constant: view.frame.width * 0.01
    ).isActive = true
    normalLabel.centerYAnchor.constraint(equalTo: normalMode.centerYAnchor).isActive = true
    normalLabel.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.3).isActive = true
    
    randomMode.topAnchor.constraint(
        equalTo: normalMode.bottomAnchor,
        constant: view.frame.height * 0.02
    ).isActive = true
    randomMode.leadingAnchor.constraint(equalTo: tableInput.leadingAnchor).isActive = true
    randomMode.addTarget(self, action: #selector(modeTapped), for: .touchUpInside)
    
    randomLabel.leadingAnchor.constraint(
        equalTo: randomMode.trailingAnchor,
        constant: view.frame.width * 0.01
    ).isActive = true
    randomLabel.centerYAnchor.constraint(equalTo: randomMode.centerYAnchor).isActive = true
    randomLabel.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.3).isActive = true
}

Once again, very similar to the previous ones with one difference. We’re attaching a label to the right edge of each switch. So normalMode has a corresponding normalLabel to explain to the user what the switch is for. The normalLabel.leadingAnchor is constrained to the normalMode.trailingAnchor with some spacing given to constant.

Finally, we’ll set up the start button with setupStartButton:

func setupStartButton() {
    view.addSubview(startButton)

    startButton.topAnchor.constraint(
        equalTo: randomMode.bottomAnchor,
        constant: view.frame.height * 0.04
    ).isActive = true
    startButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    startButton.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.3).isActive = true
}

Try it out!

Now that we have all the UI elements created and laid out and constrained, they should fall into place! On the simulator it’s looking good:

The app running on Xcode iPhone Simulator

In the next post, we’ll add some logic so our elements actually do things.

See you next time!

How To Publish An Android App On The Google Play Store

In a previous post, we created a simple app for practicing times tables. Then we added Google AdMob to it to display a basic ad banner at the bottom of the app. Today, we’re going to get the app published and available on the Google Play Store.

Create a developer account

Becoming an official developer with Google costs a one-time $25. It all starts here:

https://play.google.com/console

If you already have a google account, just follow the prompts to make your account a developer account.

Developer account creation page

Once your account is a developer account, you’ll need to upload a document that proves your identity.

Identity verification page

Verification usually takes a day or two to complete.

Create an app

Now we’re ready to create our first app on the store.

Play Store Console App Creation

The app creation process takes some time, and if you’re really serious about it, some planning. I won’t show all the screenshots, that would get a little long. The times tables app is very simple so we can move through it pretty quick.

Step 1 – basic details

We’ll need to give it a name, default language, whether it’s a game, and whether it’s paid or free. Be careful on that last one, once it’s set you can’t change it later.

Step 3 – App setup

App setup process

Google wants to know a fair amount about the app before it’s published. Some of it is for their own internal policies or data collection, others are to comply with various laws in the countries the app can be available in.

  • App access – whether your whole app is available immediately or if there is a paywall.
  • Ads – whether your app contains ads or not.
  • Content rating – a questionnaire about the content of your app.
  • Target audience – the age your app might be targeted to.
  • News apps – whether or not your app contains news.
  • COVID-19 – whether or not your app is for tracing COVID-19.
  • Data safety – you must disclose what kind of data your app collects. You also need to provide a link to a privacy policy for your app, so you’ll need to create both the policy and the page if you haven’t already.
  • Select an app category and provide contact details – a few questions about what categories your app falls under.
  • Set up your store listing – see below

Step 4 – Set up store listing

The store listing setup area will collect a bunch of information that is used to build your app’s Play Store page.

Store listing setup page

We need to upload the app icon, along with a feature graphic. A feature graphic is important if the app ever becomes popular and Google wants to feature it on the app store:

Then it’s time for screenshots:

Once we have all that stuff input and uploaded, we should be good on the store listing section. We should now be able to complete the final section to release the app on the Play Store.

Release the app on the Play Store

Now that we’ve done all the work to get the app ready, the “Publish your app on Google Play” section at the very bottom on the app’s main dashboard should be available. You’ll need to skip all the sections about testing and pre-releasing. It looks like this:

First check all countries in “Select countries and regions”, unless you have a reason not to select them all. Then click on the “Create a new release” button. On this page we’re actually going to upload a copy of the app code.

In Android Studio, you can create a bundle from Build –> Generate Signed Bundle:

Creating a Signed Bundle in Android Studio

If this is your first time creating a signed bundle, you’ll need to create a key store. Just fill in the information, it’s part of the X.509 certificate standard so it asks you for a bunch of identifying information:

Make a note of the build file destination, and create the bundle. Then upload the “.aab” file in on this page. After entering some quick details on the release at the bottom, we’re good to go.

We are now finally ready to roll it out to the world! On the Review Release page, we can click “Start rollout to Production”, which means we have completed all preparation steps!

Final release review page

Clicking the rollout button will send the app to Google, where it will be reviewed by human beings to ensure the app is safe/secure/compliant and otherwise OK to release to the world. If all goes well, the app should be available on the store within 3 days, sometimes taking up to 7, according to Google.

Congratulations!

Monetize Your App – Google AdMob

In the last couple of posts, we wrote a simple times tables flash card app. Let’s add some advertisements to it so we can make some money if anybody decides to actually use it.

Enter Google AdMob, one of the simplest and easiest ways to monetize an app.

The base code that we’ll be adding to is here on my Gihub account:

https://github.com/jamesmcclay/android_kotlin_times_tables

Let’s apply and get some ads popping up in our app!

Start the process

The application process starts here:

https://admob.google.com/home/

Clicking on “Get Started” will do what it promises.

If you’re already logged in with a Google Account, this part is easy. Your account will be created and you’ll be taken to the main AdMob page:

Google AdMob Dashboard

Click on “Add Your First App” to start adding an app.

Add your app

This part is pretty quick too. Just follow the prompts, answer the questions and create your app.

Now that we’ve created an app, we’ll need to add an ad to it. Once we’re done creating the app it leads us to the main page for the app. Clicking on “Add Ad Unit” will take us through the process to create an ad.

Create an ad unit

Ad units are just an ad within the app. There’s several different types to choose from. Some are simpler and less intrusive like the banner, and others take up the whole page and completely interrupt the flow of the app. Choose wisely. In this case, we’ll pick the simplest one, the banner.

Once the ad unit is created, we’ll get some identifiers we can use in our code to display the ad and connect it to our account to get paid.

Add the SDK

Now it’s time to write some code. We’re mostly going to be using the code given to us by Google, but since it’s in code we have a lot of control over how/when/if the ad is displayed. We’re following the quick start instructions on the Google documentation found here:

https://developers.google.com/admob/android/quick-start

We need to add some stuff to the build.gradle file located in the root directory (not the app-level one):

buildscript {
    repositories {
        google()
        mavenCentral()
    }
}

allprojects {
    repositories {
        google()
        mavenCentral()
    }
}

I also ran into an issue where I had to change a line in settings.gradle to be this:

repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)

The key was changing “FAIL_ON_PROJECT_REPOS” to “PREFER_SETTINGS”. After that, syncing gradle worked.

Now we need to add the dependency to the app-level build.gradle file (the other one) like this:

dependencies {
  implementation 'com.google.android.gms:play-services-ads:20.4.0'

  // For apps targeting Android 12, add WorkManager dependency.
  constraints {
    implementation('androidx.work:work-runtime:2.7.0') {
        because '''androidx.work:work-runtime:2.1.0 pulled from play-services-ads
                   has a bug using PendingIntent without FLAG_IMMUTABLE or
                   FLAG_MUTABLE and will fail in apps targeting S+.'''
    }
  }
}

Then we need to add the follow to AndroidManifest.xml. Make sure you put in the Application ID for your app that’s in the Google AdMob dashboard. It’s not the Ad ID that you created, the app ID. I got confused, so I thought I’d specifically call it out:

<manifest>
    <application>
        <meta-data
            android:name="com.google.android.gms.ads.APPLICATION_ID"
            android:value="ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy"/>
    </application>
</manifest>

With that, the SDK is added to the project. Next step is to initialize it.

Initialize the SDK

To initialize, we need to add the import at the top of the TableActivity.kt file (we’re going to put this on the flash card screen) and run the initializer inside onCreate. We’ll also add a global variable called mAdView to connect to adView (which we’ll create next):

import com.google.android.gms.ads.MobileAds

class TableActivity : AppCompatActivity() {

    lateinit var mAdView : AdView

    override fun onCreate(savedInstanceState: Bundle?) {

        MobileAds.initialize(this) {}

        mAdView = binding.adView
        val adRequest = AdRequest.Builder().build()
        mAdView.loadAd(adRequest)

Now all we need to do is add an AdView to the layout file so there’s an actual spot for ads. In the activity_table.xml file, we’ll stick this at the bottom, it came right from the Google documentation:

<com.google.android.gms.ads.AdView
    xmlns:ads="http://schemas.android.com/apk/res-auto"
    android:id="@+id/adView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:layout_alignParentBottom="true"
    ads:adSize="BANNER"
    ads:adUnitId="ca-app-pub-3940256099942544/6300978111">
</com.google.android.gms.ads.AdView>

You’ll notice there’s a real adUnitId in there, that’s on purpose. That’s actually the Google AdMob official test ID, we’re supposed to use that for testing. You can get your account suspended if you use your actual AdMob production ad ID.

And that should do it! When we fire up the app, we should see a test banner at the bottom of the flash card screen

Happy coding!

Android Kotlin – Building a Times Tables App – Part 2

In a previous post, we built the first part of a times tables flash card app in Android Studio. So far, we have the main page of the app where a user can either select a specific table by entering a number, or leave it blank to practice all tables. In addition, we set up a radio group with two buttons, one for “Normal Mode” and the other for “Random Mode”.

Today, we’ll be implementing the page of the app that actually shows the user their table’s questions and answers. Let’s get right into it by creating a new activity.

When I wrote this, I was using Android Studio Arctic Fox | 2020.3.1 Patch 2.

The full code for this project is on my Github account:

https://github.com/jamesmcclay/android_kotlin_times_tables

Create a new activity

To create one, just go to File –> New –> Activity –> Empty Activity. I’m going to call my activity “TableActivity”:

New Android Activity Screen in Android Studio Arctic Fox

Now that we have a fresh activity, we can create the layout elements.

Creating layout elements

We can go ahead and just delete any auto-populated content in the layout. The first thing we’ll want to create is a toolbar, so that we can put a back button on it. My initial RelativeLayout looks like this:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:minHeight="?attr/actionBarSize"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:titleTextColor="@android:color/white"
        android:background="?attr/colorPrimary">
    </androidx.appcompat.widget.Toolbar>

</RelativeLayout>

This is some boilerplate that creates a toolbar with an ID of toolbard so we can grab it from our Kotlin code later.

As for the view itself – my idea for the layout of this page was to have just three elements. A TextView to hold the question, a TextView to hold the answer, and a Button to allow the user to show the answer when they’re ready. Between the RelativeLayout tags, I’ll write the XML for the elements:

<TextView
    android:id="@+id/textview_question"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:layout_centerVertical="true"
    android:text=""
    android:textAlignment="center"
    android:textSize="32sp" />

<TextView
    android:id="@+id/textview_answer"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@+id/textview_question"
    android:layout_centerHorizontal="true"
    android:layout_marginTop="50dp"
    android:text=""
    android:textAlignment="center"
    android:textSize="32sp" />

<Button
    android:id="@+id/button_show"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@id/textview_answer"
    android:layout_centerHorizontal="true"
    android:layout_marginTop="60dp"
    android:text="Show answer"
    android:width="150dp"/>

Nothing special here, just some text and a button on the screen. That’s all we need for a basic flashcard app.

TableActivity.kt

The main logic of the app is going in this file. Not that it’s anything complicated, but there’s a few calculations that need to be made.

Before we do any of that, some global variables need to be defined so we can store some (state) information there. At the top of the file right after the class declaration, we’ll put these in:

class TableActivity : AppCompatActivity() {

    var mode:String = "" //Normal or Random mode
    var tableMode = "normal" //A single table or all tables
    var table:Int = 0 //The number of the current table
    var multiplier = 1 //The number to multiply by the table
    var answerShowing = false //The state of whether answer is showing

    lateinit var appBarConfiguration: AppBarConfiguration //The Toolbar

The lateinit keyword just means that instead of giving the variable a value now, we promise to give it a value before we use it, or the app will crash. In this case, we’re going to do the toolbar code in onCreate, so I think we’re ok.

In addition, as was instructed to me by the Android documentation, we need to add this (overridden) function to our class to make the back button work:

override fun onSupportNavigateUp(): Boolean {
    onBackPressed()
    return true
}

onCreate function

Now let’s put some stuff in onCreate. First is the binding to the layout so we can access all the elements, it’s pretty quick:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    val binding = ActivityTableBinding.inflate(layoutInflater)
    setContentView(binding.root)

Next is the toolbar code – I honestly struggled quite a bit with this part and ended up finding the solution on StackOverflow and can’t remember what page, sorry 🙁 But this magic incantation seemed to work:

val toolbar = binding.toolbar
setSupportActionBar(toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.title = "Practice!"

Then we put the layout elements (text fields and button) in some variables:

val question = binding.textviewQuestion
val answer = binding.textviewAnswer
val button = binding.buttonShow

Now let’s set the mode and table global variables to values sent from the previous activity. You’ll remember if the user didn’t put any value into the EditText for the table, we set the value to 0 so it would be a number. Let’s get the values now:

mode = intent.getStringExtra("mode").toString()
table = intent.getStringExtra("table").toString().toInt()

if (table == 0) {
    tableMode = "all"
    table = 2
}

The above is a bit confusing so let me explain – if the user selected a specific table, it will be a number and we can just work with that. But if it’s 0, they want to do all tables. We still need to use the table integer and increment it up as the user works through the tables. We need a way to know that we are in “all tables mode”, which is why I created the global variable tableMode. So if table is 0, we’ll set tableMode to all, and table we’ll set to 2. Why set to 2? Nobody wants to do tables 0 and 1, they’re too easy. We’ll start at 2.

We also need to run nextQuestion once on startup so the first question will show. All subsequent question will show when the user taps the button:

nextQuestion(question, answer, button)

The last chore in onCreate is to create an onClickListener for the showButton. This button is actually responsible for two things – if the answer isn’t showing and it’s clicked, it needs to show the answer. If the answer is showing, it should go to the next question. Hence the need for an answerShowing global variable. Here’s the listener:

button.setOnClickListener {
    if (answerShowing == false) {
        showAnswer(question, answer, button)
    }else {
        nextQuestion(question, answer, button)
    }
}

We’ll send the question, answer, and button layout items through as arguments so they can be updated by either the showAnswer or nextQuestion functions, whichever runs.

Done with onCreate. Let’s implement nextQuestion and showAnswer.

nextQuestion function

This function got a little more complicated than I would have liked, but it works. I’ll try to break it down so it’s clear what’s happening:

fun nextQuestion(question:TextView, answer:TextView, button: Button) {
    if (mode == "random") {
        multiplier = (2..12).random()
        if (tableMode == "all") {
            table = (2..9).random()
        }
    }else{
        multiplier += 1
        if (multiplier == 13) {
            multiplier = 2
            if (tableMode == "all") {
                table += 1
            }
        }
    }
    question.text = "$table X $multiplier = "
    answerShowing = false
    answer.text = ""
    button.text = "Show Answer"
}

This function starts with a check to see if random mode is on or not. If it’s random, we set the multiplier to something random between 2 and 12 (I assume people want to learn their tables up to 12). Then we check to see if we’re doing a specific table, or all of them. If it’s a specific table, we can use the existing fixed value of table. If we’re doing all tables, we’ll get a random table since this is random mode.

If the check for random is false, we’re incrementing the multiplier sequentially, so we increase it by 1. If multiplier is now 13, set it back to 2 (most people don’t learn tables past 12). In addition, when the multiplier is 13, increment the table by 1 so the user can move on to the next one.

That should do it for the logic. The lines after that are setting the text of the question, setting answerShowing to false (since it’s showing a new question now), then removing the answer text, and finally changing the button text to “Show Answer”.

showAnswer function

This function is much simpler – as the name suggests, it’s just showing the answer.

fun showAnswer(question:TextView, answer:TextView, button: Button) {
    val theAnswer = table * multiplier
    answer.text = "$theAnswer"
    answerShowing = true
    button.text = "Next"
}

Done with code!

Try it out

Everything is looking good!

Hope you liked this one. Let me know if you have any questions.

Android Kotlin – Building a Times Tables App – Part 1

Google’s Android Studio is a pretty awesome tool for building Android apps, but after building a times tables app in python and HTML, I’ll say doing an Android version was a bit more complicated. But with a little bit of knowledge about how the basics of Android Studio works along with some knowledge of Kotlin, you can have a basic app up and running in very little time. Today I’m building an app that is basically flash cards for times tables, with a couple different modes. I’ve split this up into two posts since there’s a fair amount of code.

Part 2 of this post is here.

When I wrote this, I was using Android Studio Arctic Fox | 2020.3.1 Patch 2.

The full code for this project is on my Github account:

https://github.com/jamesmcclay/android_kotlin_times_tables

Create a new project

We start by creating a new project, with an empty activity.

New project screen in Android Studio

Give your project a name, and make sure to set the language as Kotlin. Click finish, and you have a brand new project!

Write the layout code

Android Studio takes you to the MainActivity.kt file off the bat, but we’re going to jump into the layout file and create the interface elements. At the top of the screen, you should see a tab that says activity_main.xml, that’s where we can create the first page elements of app.

Opening up activity_main.xml, you’ll need to click on “split” near the top right so you can see the code as well as a rending of it on a mock phone. There’s a bunch of code already in there but you can delete all that.

First I’m going to create a RelativeLayout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

</RelativeLayout>

If you just type “Re”, RelativeLayout will probably autopopulate and you can press enter to get it and a bunch of pre-written code for you. No need to type all that stuff.

Text items

Inside the RelativeLayout (between the opening and closing <RelativeLayout> tags), I’ll create some text. These will just be banners introducing the app and instructing the user to enter a table to practice. This can be done with the element TextView:

    <TextView
        android:id="@+id/textview_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="100dp"
        android:text="James McClay's\nTimes Tables!"
        android:textAlignment="center"
        android:textSize="32sp" />

    <TextView
        android:id="@+id/textview_select"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textview_title"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="30dp"
        android:text="Practice all tables\n Or enter a table to practice:"
        android:textAlignment="center"
        android:textSize="24sp" />

I thought about commenting all these to explain what they’re doing, but it seems like they’re all pretty self-explanatory. It’s basically just putting some static text on the layout of the app, centering it, setting the font size, etc.

Next we’ll create a text entry field where the user can either leave it blank to practice all times tables or enter a specific one. This is done with the element EditText:

    <EditText
        android:id="@+id/edittext_timestable"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textview_select"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="30dp"
        android:hint="All tables"
        android:inputType="number"
        android:textAlignment="center"
        android:textSize="24sp" />

All elements have been given an "@+id", and using layout_below we can tell elements to go below another one.

Button and radio group

Next we’ll need a start button to send the user to the view that shows times tables questions. A button can be created with Button:

    <Button
        android:id="@+id/button_start"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/edittext_timestable"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="40dp"
        android:text="Start!" />

Finally, we’ll create a RadioGroup to hold two radio button buttons. I thought having a normal, sequential mode as well as a random mode would be beneficial. The RadioGroup means that only one RadioButton can be selected in the group. Also, RadioButtons have a special property called onClick, where you can specify what function to run when one of the buttons is clicked and selected.

    <RadioGroup xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/button_start"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="20dp"
        >

    <RadioButton
        android:id="@+id/radio_normal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="onRadioButtonClicked"
        android:text="Normal Mode"
        />

    <RadioButton
        android:id="@+id/radio_random"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="onRadioButtonClicked"
        android:text="Random Mode" />
    </RadioGroup>

Remember, all of that stuff went in-between the RelativeLayout tags. Ok, now we’re ready for the Kotlin code.

onCreate function

You will probably need to add a snippet of code to your app’s build.gradle file so you can “bind” your Kotlin code to the layout file. Be careful – there are two of these files. You want the one that is inside “app” directory, not the one that’s in the root directory. In build.gradle, in the android block, paste this snippet and sync gradle:

buildFeatures {
    viewBinding = true
}

Next let’s write our code in the onCreate function that’s given to us by Android Studio:

class MainActivity : AppCompatActivity() {

    var mode: String = "normal" //represents what radio button user selected

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val binding = ActivityMainBinding.inflate(layoutInflater) //bind to layout file
        setContentView(binding.root)

        val button = binding.buttonStart //get the start button
        button.setOnClickListener {
            val theIntent = Intent(this, TableActivity::class.java)
            var table = binding.edittextTimestable.text.toString() // get what table the user entered
            if (table == "") {
                table = "0" //if the user entered nothing, meaning all tables, set to 0 so toInt() won't fail.
            }
            theIntent.putExtra("mode", mode) // send mode to next screen
            theIntent.putExtra("table", table) // send table to next screen
            startActivity(theIntent)
        }
    }
}

I’ve created a global variable (I believe the Kotlin word is “property”) called mode to hold what radio button the user selected. The Intent stuff is just standard boilerplate code to send the user to the next screen. The next screen’s activity will be called TableActivity, which this bit Intent(this, TableActivity::class.java) has TableActivity in it.

You’ll notice we’ve attached mode and table to the intent so the next screen’s code can access it. You can see where table is retrieved and set, but you might be wondering how mode is set. We’ll do that next.

onRadioButtonClicked function

I took this code directly from the Android Studio documentation, and substituted my radio button id’s and mode property. We specified the onRadioButtonClicked function in the Radio Button XML code earlier.

fun onRadioButtonClicked(view: View) {
    if (view is RadioButton) {
        // Is the button now checked?
        val checked = view.isChecked

        // Check which radio button was clicked
        when (view.getId()) {
            R.id.radio_normal ->
                if (checked) {
                    this.mode = "normal"
                }
            R.id.radio_random ->
                if (checked) {
                    this.mode = "random"
                }
        }
    }
}

This basically just runs some logic to see which button is clicked, and then set the value of mode.

Try it out!

The app looks pretty good so far!

On the next post – I’ll build the screen where the user can actually practice times tables. Happy coding!

Check out part 2!

Python Flask Web App – Times Tables Quiz

Have you ever built a web app? Me neither! That’s why I’m going to build this app so we can both learn a thing or two. The components I will use are:

  • Python Flask Web Framework
  • HTML
  • No CSS!
  • No Bootstrap!
  • No React!
  • No Javascript!
  • No SQL!

So basically just python, Flask and HTML. I will also impose these limitations to make things simple and interesting:

  • No external HTML files – all HTML written within python files!
  • No http server in front of the Flask development http server – no NGINX, no Apache, no nothing! Just the Flask development http server.

This app will violate so many best practices, I can’t count. You have been warned.

You can find the entire code in one file on my Github account:

https://github.com/jamesmcclay/python_flask_times_tables

Install Flask

Make sure you install Flask, this is what we’re going to use for the main logic of the app. You might have to type “python3” or “python”, depending on what kind of system you have and how python is installed.

python3 -m pip install flask

Good to go!

Create the first page

I use vim, because using PyCharm or VisualStudio Code would probably be a lot more productive.

At the top of our file, I’ll do some imports to pull Flask in:

from flask import Flask
from flask import request

Then we’ll create the application object, and put it in a variable called app. I don’t actually know what this does other than fire up Flask. We’ll use the app object at the bottom of the file to actually start the http server and Flask app:

app = Flask(__name__)

I’m going to show the html in a separate block here so you can see it in html highlighting. Then I’ll show it embedded in the python code. It’s hard to look at in the python code because it’s all highlighted as a string.

My html code creates a form, asking the user to submit their requested times table (2*X table, 3*X table, etc). The selected table (it’s just a number) will be stored in the query string that is sent back to a different URL at /next.

<html>
<form action ="/next" method="get">
<label for="times_table">What times table do you want?</label><br>
<input type="text" id="times_table" name="times_table"><br> <!-- the variable "times_table" stores the requested table -->
<input type="submit" value="Submit">
</form>
</html>

Now here’s that html embedded into python code, in a multi-line string:

@app.route('/') #Flask provides this. This function will respond to requests to '/'
def index():
    #Three quotes makes a multi-line string
    form = '''
    <html>
    <form action ="/next" method="get">
    <label for="times_table">What times table do you want?</label><br>
    <input type="text" id="times_table" name="times_table"><br>
    <input type="submit" value="Submit">
    </form>
    </html>
    '''
    return form

Flask gives me a ‘decorator’, a type of python magic that allows you to add special functionality to an otherwise normal function. In this case @app.route('/') gives this function the ability to respond to http requests using return. Whatever return sends back will in fact be sent to the user’s browser. In this case, it’s sending back the html form.

At the bottom of the file, we add the command to run the app (it will listen on all network adapters, beware):

app.run(host='0.0.0.0', port=80)

The program should be runnable at this point, let’s give it a shot! This command runs the Flask development http server. I had to put the -E option on sudo to allow python to access all my modules.

sudo -E python3 times_tables_website.py 

Opening up a browser, we can just go to the loopback adapter at 127.0.0.1 and see the app! I zoomed in a bit:

Entering 6 and hitting submit, I will get a 404 because /next hasn’t been implemented yet, but you can see the query string has sent the data we want:

Implementing /next

Here is the html form I’m going to send from the /next route. It will also be embedded in my python string, so I’m showing it once here in html highlighting. I’m using a trick in order to store data in the form I send to the user. I send a couple of hidden <input> labels to store times_table and multiplier. When the user sends the form, my function will be able to extract those and know what question to ask the user next.

<html>
<form method="get">
{judgement} <!-- Not HTML!! Will use python to insert label showing answer correct/not -->
<input type="hidden" id="times_table" name="times_table" value="{times_table}"> <!--store times_table variable hidden-->
<input type="hidden" id="multiplier" name="multiplier" value="{multiplier}"> <!--store multiplier variable hidden-->
<label for="answer">What is {times_table} x {multiplier}</label><br> <!-- python string interpolation again-->
<input type="text" id="answer" name="answer"><br> <!-- answer variable stored here-->
<input type="submit" value="Submit">
</form>
</html>

Next we will implement the /next route. Web developers call these routes, they are relative to the top level of your site which is always /. In this code, we’ll use request.args to get data from the request that was sent. Remember the form put a times_table variable in the query string? We’ll need to get that to know what table the user requested. The way to grab one is with request.args.get('variable_in_query_string'). We’ll also grab the multiplier, but on the first page multiplier won’t exist in the query string because the user hasn’t started yet. Which means the multiplier should start at 1. So if multiplier is None, I set it to 1. Otherwise, grab it, turn it into an int, and do a check to see if the user’s answer is correct. The judgement label will dynamically change based on the answer, and be inserted before being sent back to the user.

@app.route('/next') #Answers requests to the "/next" route
def next_row():
    times_table = request.args.get('times_table') #"request" was brought in from a flask import, lets us get query string variables
    times_table = int(times_table) #turn "times_table" into a number so it can be multiplied
    multiplier = request.args.get('multiplier') #get the multiplier
    answer = request.args.get('answer') #get what user answered. I use int() later because this is None on first page
    if multiplier == None:
        multiplier = 1
        judgement = ''
    else:
        multiplier = int(multiplier) #turn multiplier into a number
        if int(answer) == (times_table * multiplier): #check if answer is correct. I use int() here because this is not None
            judgement = '<label>You got it right!</label><br><br>' #judgement inserted into html (interpolated) later
        else:
            judgement = '<label> You need to practice!!!!!</label><br><br>'
        multiplier +=1 #increment multiplier for the next question

    #This is string interpolation as of python 3.6, using "f" before initial string quote
    form = f''' 
    <html>
    <form method="get">
    {judgement}
    <input type="hidden" id="times_table" name="times_table" value="{times_table}">
    <input type="hidden" id="multiplier" name="multiplier" value="{multiplier}">
    <label for="answer">What is {times_table} x {multiplier}</label><br>
    <input type="text" id="answer" name="answer"><br>
    <input type="submit" value="Submit">
    </form>
    </html>
    '''

    return form

Let’s try and see if it works!

It works! Hope you enjoyed this one. I sure learned quite a bit.

As an Indie App Developer, Marketing Terrifies Me

I’ve been working on an app for over 2 years now, and I feel like I’ve done a fair amount of research about how to market an app. Enough to know that I really don’t know how to do it. My chances of launching an app that anyone will download, much less pay for (through in-app purchases, my chosen monetization method), is slim. If you’ve done any research about common ways that apps fail, probably the most common is that the marketing didn’t connect with users, or there wasn’t any marketing done at all.

If you just build it, they definitely won’t come

It seems like there’s a fair amount of indie app developers with no marketing plan at all. No matter how great an idea, no matter how well an app solves a problem, if nobody knows about it they won’t be downloading your app. I think every developer would like to think their app is going to be the next Instagram – it’s so awesome that it simply markets itself.

The truth is, no app markets itself. And the version of Instagram in your head where it was so cool and awesome that no one had to do any marketing is simply an illusion. If you look into how Instagram was created, they had to do a lot of hard work and big changes to get anyone to be interested in it.

For my app, I know if I don’t have at least some kind of plan to market it, I’ll fall into that group of apps that good or bad, never get discovered.

App store optimization – does it do anything?

I understand App Store Optimization (ASO) to be the technique of trying to get your app to come up in search results when users search on the App Store. There are ways that ASO can be quickly applied, for example choosing the correct wording for the title of your app, as well as writing a good description with good screenshots.

But the more effective ASO techniques require hard work, diligence, and time. The app store wants to see, for example, that your app has lots of good reviews, that your app is updated often, and has a lot of downloads before it really starts showing your app in search results.

This presents us a chicken-and-egg scenario. How do you get good reviews and downloads if the App Store wants you to already have good reviews and downloads? I’m thinking that the answer is that ASO is not a good marketing technique by itself. There’s no special words or key phrases you can put in your app’s description that’s going to magically attract users to it. That may have been true early on in the history of the App Store when there weren’t so many apps and app developers. But now there’s lots of competition, and you really have to stand out from the crowd.

How to stand out?

If app marketing takes time and hard work, how do really successful apps launch themselves to popularity within a few days or weeks of launch? That kind of rocket-propelled launch doesn’t happen by accident. It’s almost always part of a carefully planned marketing campaign, using a number of techniques to draw attention to the app’s existence.

I think it’s safe to say that this marketing business is no easy task all by my lonesome, especially when most of my time is spent, you know, building the app. I need some help.

My plan

My plan has two parts:

  1. Do my own social media marketing
  2. Try to get someone with some influence to help

That’s about it. The other person on my team, my wife, has a Youtube channel (https://www.youtube.com/channel/UCfms-4LkhJ3oR2Y4GbUy1xw, if you’re interested) an Instagram account, and a Facebook page, and we’re going to market the app there.

For my part, I plan to spend a few months to do some groundwork trying reaching out to some influencers that might be interested in promoting my app, and see what they want in return.

We’ll see what happens! Wish me luck!

No Need To Be Afraid – iOS Apps Are Just Loops

I’m pretty sure that most beginning programmers are intimidated by the term “loop”. After all, a loop in real life could mean a number of different things that bear little similarity to the concept of loop in computer programming. I was recently talking with an aspiring iOS developer that was struggling with how a button is linked to Swift code in iOS.

As we continued the discussion, I realized that what was clear to me from experience writing code wasn’t clear to the person I was talking to. What is happening in the background when you load an app? Well, quite a bit, actually. And it isn’t really stated clearly off that bat when you jump into Xcode and iOS development. Sure, it’s probably in the Apple documentation somewhere, but it’s not spelled out for you.

The main event loop

You’ve probably been told that computer code is just a bunch of instructions that tells the computer what to do. The computer executes your commands to a tee. By that logic, the computer should run your commands until it has no more commands to execute, and stop. Right?

Well, yes. But remember Apple did some stuff in the background that you can’t see. So if you just write a couple of print statements in viewDidLoad (the first function to run in your app) in your app’s only UIViewController (the thing that shows the app’s view on the phone’s screen), what exactly is your app doing when you run it? How is it still running and showing something on the screen after the code you wrote has been executed?

The answer is that your app, at it’s most basic function, is a loop. By loop I mean it goes in a circle, doing the same things over and over. Specifically, it does two things in this loop. It checks for an “event” – a good example is whether or not the user tapped a button. The second thing is it reacts to an event if one happened. A good example would be to play a sound in reaction to a button being tapped. If no event happened, it checks again. And again and again, in a loop. That’s what your app is. In my head, it looks a little something like this:

Apple does in fact have official documentation on this subject, it’s really old and in their archive but doesn’t seem to have been replaced by anything new. So as of this writing at the end of 2021, Apple’s explanation of the iOS app main event loop is here, I thought it would be worth mentioning:

https://developer.apple.com/library/archive/documentation/General/Conceptual/Devpedia-CocoaApp/MainEventLoop.html

Your app’s job: react to events

Back to computers executing commands one by one – yes that is how they work. A computer program that works in this fashion is loosely called a “script”, but there’s no hard definition of what that actually means. The important thing to remember about the difference between your app and other types of computer programs is that it’s waiting for input from the user, who is (hopefully) the owner of the phone your app is running on. Your app’s job is to react to input from your user.

So how does the iPhone know what code to run when an event happens? It knows because you tell it. You attach a function to a button, which is just a bundle of code. That function will run when the button is pressed. The cool part is iOS does all the heavy lifting for your once you make the connection. You don’t need to know about how messages are carried in the event loop or what’s going on behind the curtains, just connect your button and code and away you go! It almost feels like you’re cheating somehow.

Happy coding!

Swift Classes vs. Structs – Why You Shouldn’t Care About The Difference

Like all iOS developers at some point early in their app-building journey, you may be wondering what the difference is, when to use one over the other, and why you should care. If you’re at this point, especially if you’re new to programming, I’d highly recommend not caring. That view might make the Internet mad, but after learning the major differences and reading the Apple documentation, I would still make that recommendation. If you’re an experienced developer, you’ve already made your decision and not only done the research, you understood what you were reading. But for the rest of us non-super geniuses, classes and structs can be a pretty abstract concept that’s hard to wrap your head around. In the end, I think you can build a basic app using either one, and until your app’s performance is hindered by the improper use of one or the other, why not just focus on more pressing matters?

They both do the same thing

This isn’t entirely true, and under the hood they’re fundamentally different, but if you’re at a point where you need to create a custom object – just pick one and move on. The first time I found I was really forced to create my own object was when I needed to read and write JSON. The hippest coolest way to deal with JSON these days in Swift is to use the Codable protocol. The only issue is both structs and classes can do the codable thing:

struct JamesStruct: Codable {
    var key:String = "value"
}

class JamesClass: Codable {
    var key:String = "value"
}

So which one to use, then? The StackOverflow example I found somewhere and mercilessly copy/pasted used a struct, so I just went with that without really understanding why. Is that so wrong? I mean come on, we’ve all done it. Even the most advanced, highly-paid, successful and super genius developers out there have quickly scraped StackOverflow because they were on a deadline. Anyone who says otherwise is likely selling something.

You need context to really understand the difference

I always need some sort of context to really understand how something works. Sure I could conjure up some pie-in-the sky example for you to illustrate the differences between these two, but there’s a zillion blogs out there already that have done that for you. Not to mention if you’re looking for pie in the proverbial sky, the official Apple guidance on the topic is here:

https://developer.apple.com/documentation/swift/choosing_between_structures_and_classes

I could say that classes are a reference type and structs are a value type, that structs are “lightweight” and classes are “heavier”, or that only classes can inherit. But it probably doesn’t mean much to you unless it specifically affects YOUR app and YOUR use case somehow.

If you’re debating which one to use in your app, or wondering if you used them correctly, why not just play around a bit? See what happens when you substitute one for the other. That’s where you’ll really learn.

If you need a hard recommendation, Apple says default to structs

If you checked out the official Apple guidance, you might have noticed they said to use structs (as of this writing, end of 2021) unless you have a specific reason to use classes. Which brings me to the image at the start of my post – I was surprised to learn that many of the basic data types in Swift like Strings and Int’s are, in fact, structs. If Apple is using them in that capacity I think it’s safe to say your custom object is mostly likely a good candidate for a struct.

Happy coding!

Swift Classes – You Don’t Really Need To Understand Them.

Of course, that’s not actually true. If you want to become an expert Swift programmer, you absolutely need to understand classes. However, I believe you don’t really need to know that much about classes to get going with them. In fact, the first time you use them you probably won’t even really be aware of it other than there’s a “class” keyword in your code at the top.

Tutorials might have confused you.

At least, I was confused. Most of the explanations I read/watched about classes went something like this:

“A class lets you create a custom object. For example, say you wanted to create an Animal class, you’d do it like this:”

class Animal {
 let greeting = "I am an animal"
}

“Now you can create multiple Animal instances from the original design you created in Animal, like this:”

let animal1 = Animal()
let animal2 = Animal()
let animal3 = Animal()

“Now create a subclass, that lets you use all of the stuff Animal had, and customize further for this subclass. Our subclass will be Dog:”

class Dog: Animal {
 let species = "I am specifically a dog"
}

“And now you can create as many Dogs as you want, an army of them in fact, all with the powers of both Animal and Dog:”

let myDog1 = Dog()
let myDog2 = Dog()
let myDog3 = Dog()

print("\(myDog1.greeting). \(myDog1.species)")
print("\(myDog2.greeting). \(myDog2.species)")
print("\(myDog3.greeting). \(myDog3.species)")

And the tutorial would go on to explain properties, methods, etc. That’s super cool, and those are indeed the magical powers of classes and object oriented programming. When I first saw this kind of explanation, the concept totally made sense in my head. I was totally on board with the logic.

But how to use them?

But then I went to try and write an app of my own, and found I had no idea why anyone would ever use classes in actual code. Sure it’s all fun with animals, dogs and cats, but I was way more concerned about how I would get my app to show an image or a button, for starters. That’s the level I was at. But there was the class keyword staring at me when I created a new project in Xcode, without ever writing a single line of code on my own. It appears in the freebie stuff Xcode gives you when you create a fresh storyboard-based project:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
}

Why is class there? And it’s not just a class, it’s a subclass. To be honest, understanding why isn’t really necessary to get your app to fire up for the first time, or to get an image on the screen, or put some basic logic behind a button.

I’ve realized that to create a basic app, you don’t need to worry about creating classes from scratch, or much less create subclasses of your custom classes to use abstract object oriented constructs such as polymorphism or multiple inheritance. The most immediately applicable use of a class is right there in that first bit of code that Xcode populates for you.

There’s a swift class right front of you

If you think about what the Apple developers might have been thinking when they were cooking up Xcode, they can’t possibly know what your app is going to do. At some point, they have to hand some control of the screen to your app. The way they accomplished this was to create UIViewController, which does a bunch of stuff you can’t see to create a blank screen on the phone, ready to be customized for some interesting and unique things your app will do. If you don’t customize UIViewController, all your app will ever be is a blank screen. By creating a subclass of UIViewController (Apple assumes you want to call this ViewController), you can now write your own custom stuff to show beautiful things on the screen. You don’t really realize it, but you’re using inheritance.

The subclassing in this line lets you customize the view:

class ViewController: UIViewController

But where does the handoff take place? When does Apple hand off the view to your app? As it turns out, viewDidLoad() is a function that Apple already wrote. Like the name suggests, it loads up the view. But if you don’t customize it, it’ll just be a blank view of nothing. That’s why you need to “override” viewDidLoad to customize it, so you can start running your own code. That’s what’s happening here:

override func viewDidLoad()

But there’s one last thing to do in your now-overridden viewDidLoad function. Since you overrode it, the original Apple code to load up the blank view won’t run. So you have to run it with:

super.viewDidLoad()

At this point, you’re finally ready to write your own custom code for your app.

As you keep coding, you’ll realize that subclassing Apple-created classes like this is really helpful when you want to do all sorts of things, and the inheritance concept will make a very real-world kind of sense.

I really think that’s a more realistic approach than an Animal/Dog/Cat example of classes, which makes sense after you’ve had a lot of experience.

I hope that helps! Happy coding!