Categories
Development

Forms & Lists

If there’s one area where SwiftUI really shines, it’s forms and lists. I have one area of the app that’s meant as, at most, a fallback option for managing some data, and putting together that management interface took, oh, an hour? It was a breeze. Admittedly, it’s not the prettiest list I’ve ever made, but like I said: fallback option.

Screenshot of a list with a title, two items showing a date and value each, and an 'add' button.
Managing data points in a data set. Unpolished? Sure. Functional? Absolutely.
Screenshot of a Settings screen showing two lists, with an 'edit' button.

I was delighted to find that the automagic ‘edit’ button function handles multiple editable lists within the same View. As this is part of the ‘Settings’ screen, one of the three core screens in the app, it has received a bit more polish.

And I’ve continued to have fun building custom versions of the Picker control, with an expansion on my previous custom picker to support inline management of the above Data Sets and the addition of another one for picking a type of graph:

Screenshot of a picker showing three types of graphs.

At the moment, I’m showing a pretty basic dataset for these, but at some point I think I may create something a bit more visually interesting. The trick being, of course, that I can’t just random-number-generate the data, because I want all three to show the same data points, and since the user can also control the color, I want it to stay consistent if you leave, change the color, and come back.

(The solution here is probably to hard-code a data set, but where’s the fun in that?)

Categories
Development

File > New > Project…

I recently started working on a new development project. Or rather, a project I’ve been thinking about for a while, but just recently started developing – the first draft of the design is from almost a year ago, now, something that I worked on as a class project. But, mostly on a whim, I signed up for SwiftUI Jam, and took it as an excuse to start actually building the thing.

Now, normally my approach to projects is very Apple – refuse to admit I’m even working on something new until it’s complete, ready to present to the world. This time, though, the vague rules of the jam meant it had to be done at least somewhat in the open, and I figured I may as well do some proper write-ups as I go. Could be interesting.

I’m starting with… not the first thing I built, but the one that was the most fun so far. I’m doing the whole app in SwiftUI, and it really shines for building forms.

Screenshot of an iOS application showing a form: Title, Color, and Data Set; Comparison? is set to false.
Screenshot of an iOS application showing a form: Title, Color, and Data Set; Comparison? is set to true. The first three questions are repeated.
Screenshot of an iOS application showing a list to choose from, with groupings such as Activity featuring items like Calories Burned and Cycling Distance.

As I said, a fairly simple form – Title, Color, and Data Set, with the option to add a second of the same three items. The Data Set picker is a custom version of a Picker, because I wanted to give the options in a grouped list rather than just alphabetical order.

I suspect I’m going to be building a second custom Picker implementation sometime soon – this time, choosing from more visual options. Should be fun to put together.

Categories
Education Portfolio Technology

Swift Student Challenge

A few days ago, Apple announced the winners of their Swift Student Challenge. I had applied and used my “taking a test” tactic, which was to hit ‘submit’ and then promptly erase the whole thing from my brain. (What’s done is done, and I feel silly worrying about something I have no control over.)

So when I got the email that “my status was updated” it was a bit of a surprise.

And when I clicked through the link (because, of course, they can’t just say in the email, you have to sign in) I was in for more of a surprise.

My submission had been accepted. I’m one of 350 students around the world whose work sufficiently impressed the judges at Apple.

Screenshot from Apple Developer website. It reads: Congratulations! Your submission has been selected for a WWDC20 Swift Student Challenge award. You'll receive an exclusive WWDC20 jacket and pin set at the mailing address you provided on your submission form. You'll also be able to download pre-release software, request lab appointments, and connect with Apple engineers over WWDC20 content on the forums. In addition, one year of individual membership in the Apple Developer Program will be assigned free of charge to eligible accounts of recipients who have reached the age of majority in their region. For details, see the WWDC20 Swift Student Challenge Terms and Conditions.
Neat!

Now, throughout the whole process of applying, I was my usual secretive self. I think two people knew that I was applying at all, much less what I was working on. Since it’s over with, though, it’s time for the unveiling.

What I made

I wanted to bring back a concept I’ve played with before: cellular automata. A few days before the competition was announced, I’d seen a video that really caught my interest.

Well hey, I thought, I’ve got some code for running cellular automata. I want to learn Swift Playgrounds. And I’ve been having fun with SwiftUI. Let’s combine those things, shall we?

The first big change was a visual history; when a cell dies, I don’t want it to just go out, I want it to fade slowly, leaving behind a trail of where the automata have spread.

The second was rewriting all the visuals in SwiftUI, which was a fun project. Animation timings took me a bit to get right, as did figuring out how to do an automated ‘update n times a second’ in Combine. The biggest issue I had, actually, was performance – I had to do some fun little tricks to get it to run smoothly. (Note the .drawingGroup() here – that made a big difference.)

And third, I didn’t want it to just be “here’s some code, look how pretty,” I wanted to actually use the Playground format to show some cool stuff. This turned out to be the most frustrating part of the whole thing – the Swift Playgrounds app doesn’t actually support creating a PlaygroundBook, and the Xcode template wasn’t supported in the then-current version of Xcode.

But the end result? Oh, I’m quite happy with it. PlaygroundBooks are cool once you get past how un-documented they are. You can, to borrow a Jupyter turn of phrase, mix code and prose in a lovely, interactive way.

Screenshot of the 'Grid' page of the playground book.  The full text is at https://github.com/grey280/SwiftLife/blob/master/Swift%20Student%20Submission.playgroundbook/Contents/Chapters/Chapter1.playgroundchapter/Pages/Grid.playgroundpage/main.swift
Don’t worry, the real version (and some videos) are below.

Doing the actual writing was pretty fun. This is a concept I’ve spent a lot of time learning about, just because it captured my interest, and I wanted to share that in a fun way.

Overall, I’m quite happy with the result. If you’d like to see more, I’ve made recordings of the ‘randomized grid’ and ‘Wolfram rule’ pages running, and the actual playground is available on GitHub.

Categories
Programming

SwiftUI’s Picker

I’m very excited about SwiftUI, and have been using what little free time I have to do some tinkering with it. I started during the beta period, which was fun in between being very frustrating; a lovely side effect was that some of the knowledge I picked up is… entirely wrong. One that caught me was the implementation details for the Picker type.
Based on the rather rough state of the SwiftUI documentation for Picker and ForEach,1 I’d assumed that combining the right binding with a .tag(_:) on the items would work:

Form {
    Picker(selection: $selectedItemID, label: Text("Choose Something") {
        ForEach(items){
            Text($0.label).tag($0.value)
        }
    }
    Text("You've selected item \(selectedItemID)!")
}

For reference, the models I’m referring to throughout are pretty simple:

struct CustomModel {
    let value: Int
    let label: String
}

Now this looks like it’s working in simple cases. However, I was trying to interact with a web API, so that items array looked something like this:

var items: CustomModel[] = [
    CustomModel(value: 7, label: "First"),
    CustomModel(value: 3, label: "Second"),
    CustomModel(value: 1, label: "Third")
]

If you tapped “Second” in the picker that SwiftUI generated, however, the text wouldn’t read “You’ve selected item 3!” like it should; it would be “You’ve selected item 1!”
A bit more tinkering revealed that, instead of pulling the value from the .tag(_:) on there, it was just using… the index in the ForEach.2
After some frustrated Googling, utterly despairing of Apple’s documentation, and a lot of StackOverflow searches, I finally figured out the solution:

Form {
    Picker(selection: $selectedItemID, label: Text("Choose Something") {
        ForEach(items, id: \.value){
            Text($0.label).tag($0.value)
        }
    }
    Text("You've selected item \(selectedItemID)!")
}

Quite frankly, I don’t have a good explanation of what’s going on here; last time I was tinkering with Pickers, the .tag(_:) provided SwiftUI with the information it needed to do the binding. (When I’ve got more time, I’d like to do another test — now that I’ve got the id keypath, do I even need the tag?)
I’d love a good explanation of what all the id keypath gets used for, and where else it might be necessary, but alas:


  1. It’s a bit unfair for me to link to No Overview Available when referring to SwiftUI; the coverage is low, but the problem isn’t so much that as the fact that ‘documentation coverage’ just doesn’t work as a metric for something like SwiftUI. The tutorials are a start, and a good sign that Apple was at least trying to rethink their approach to documentation, but they’re not nearly complete enough. 
  2. Zero-based index, of course, which seemed obvious to me, but got me a “???” response when I was complaining about this issue to a non-programmer friend.