Non-Selectable Rows in a SwiftUI Picker

With SwiftUI, it’s quite easy to create forms to collect user input. Consider the following.

struct ContentView: View {
    @State var numberOfCookies: Int?
    
    var body: some View {
        NavigationView {
            Form {
                Picker("How many cookies?", selection: $numberOfCookies) {
                    ForEach(1..<10) { number in
                        Text("\(number)")
                            .tag(number as Int?)
                    }
                }
            }
            .navigationTitle("Order")
        }
    }
}

Being in a Form in a NavigationView means our Picker above will navigate to a list on tap by default. We thus get a view that looks like this.

If they tap on the row, they’re shown this list of options.

The Picker will take each view generated in the ForEach and show it as an option.

This is super simple! However, what if we wanted to show some kind of header alongside our various options? Or perhaps we wanted to section the options? Or maybe we’re displaying options from a third-party API that includes such headers or section names in the returned data? To figure that out, let’s first understand how the SwiftUI picker works.

How Picker Works

The above code seems fairly straightforward. I defined a Picker in a hierarchy. It had a title that is displayed in the form. The selection was set as a binding to a local state variable. The trailing closure was my picker content, where I used a ForEach to generate each option.

However, as simple as that might be, you might be asking: What is with the tag?

Each view that is used in the Picker needs to be tagged with the value it represents. In our case, it’s just a number. So I am tagging each generated view so that it corresponds with a valid value.

But why didn’t I just say “.tag(number)“? It’s because it wouldn’t match the type the Picker is looking for, namely the optional Int of the state variable. If I had done that, the Picker would still show each of my numeric options, but none of them would be selectable. Tapping on one wouldn’t change the data source.

This leads to an interesting observation: Any view in the Picker that doesn’t have a tag matching the bound type is thus non-selectable.

Making Picker Headers

With this knowledge in mind, let’s go back to our example. Let’s say we wanted to show that we have a discount if the customer buys more than 4 cookies. How can we do it?

We change our picker like this.

Picker("How many cookies?", selection: $numberOfCookies) {
    Text("Normal Price")
        .font(.headline)
    
    ForEach(1..<5) { number in
        Text("\(number)")
            .tag(number as Int?)
    }
    
    Label("Discount", systemImage: "tag")
        .font(.headline)
    
    ForEach(5..<10) { number in
        Text("\(number)")
            .tag(number as Int?)
    }
}

We now have other views in our picker that are not tagged as options, thus becoming visible yet non-selectable display items. In the above code, we first display “Normal Price” before showing options for quantities up to 4. We then show a more complex view, a Label, before showing the other quantities.

Our view now looks like this.

And just like that, we have support for displaying non-selectable content within our picker.

Using a Binding in SwiftUI – Simple Example

In my original post on Bindings in SwiftUI, I had mentioned when we might want to use a binding:

You would use a binding to create a two-way connection between a property that stores data, and a view that displays and changes the data.

I showed an example of how we could bind one of our local @State properties to a Toggle. The Toggle could update the state of our property through it.

We can use other system controls, such as TextField or Picker, to also update our local variables. But what if we want to have another one of our views update a variable owned by another? Let’s solve a simple example and, in doing so, we’ll see when we will make use of @Binding.

I have a simple view that displays my name. I am storing it locally as a variable.

struct NameDisplayView: View {
    var name: String = "unknown"
    
    var body: some View {
        Text("Your name is \(name)")
    }
}

It simply takes the text there and outputs "Your name is unknown". It works, but I want to be able to update that name so I can have it show me and not assume I have no name.

Well, we know how we can bind to something from our original post. So let’s make a view where we can change some text.

struct NameChangeView: View {
    @State var text: String
    
    var body: some View {
        TextField("Type Here", text: $text)
    }
}

So far, this is a simple example. If we loaded up NameChangeView, we could tap into the TextField and, as we type, text would be updated. Why? Because we have it bound to the text property on TextField, which is of type Binding<String>. So as the TextField updates the text, our view can get the latest values.

But let’s say we want to present this view as a sheet, let the user update the text, and then send it back to our original view. Can we do it? Yes!

What do we need to change so that our NameChangeView can pass changes back from itself to another view? All we have to do is change @State to @Binding. With that change, we now have two way communication via that variable.

Let’s add a little styling and a way to dismiss the view. That gives us our final form:

struct NameChangeView: View {
    @Environment(\.presentationMode) var presentationMode
    @Binding var text: String
    
    var body: some View {
        TextField("Type Here", text: $text, onCommit: { self.presentationMode.wrappedValue.dismiss() })
        .textFieldStyle(RoundedBorderTextFieldStyle())
        .padding()
    }
}

Now, how can we use this in our original view?

We’ll add a button to trigger a sheet. This happens by binding a local Bool to the .sheet(isPresented:) modifier. Lastly, we add our NameChangeView as what is being presented modally as a sheet. We pass our local name variable as a binding to that view, so it becomes $name.

struct NameDisplayView: View {
    @State var name: String = "unknown"
    @State var showNameChange = false
    
    var body: some View {
        VStack {
            Text("Your name is \(name)")
            Divider()
            Button("Change") {
                self.showNameChange = true
            }
        }
        .sheet(isPresented: $showNameChange) {
            NameChangeView(text: self.$name)
        }
    }
}

Now, we can tap on “Change”, which will present our text field. We can tap on it, change our name, hit “Return”, and be taken back to our original view but with our name in place.

Bindings might seem like a new concept to iOS developers, but they open up a lot of possibilities in Swift. Explore various ways that you can use bindings to communicate between views. You’ll find them very useful, especially in cases of user input as we saw in our example.

You can find the example code in this Github Gist.

Bindings in SwiftUI

Property wrappers were one of the recent additions to Swift. SwiftUI makes use of several very useful property wrappers. One of them is @Binding. The @Binding property wrapper is really just a convenience for the Binding<T> type.

But before we go into using bindings, what are bindings?

Per Apple’s documentation, a binding connects a property to a source of truth stored elsewhere, instead of storing data directly. You would use a binding to create a two-way connection between a property that stores data, and a view that displays and changes the data.

In SwiftUI, you’ll find this to be a fairly common pattern, especially with built in input fields.

Binding Example

Let’s say we want a view with a switch for the user to interact with. How do we build it?

struct BindingExample: View {
    @State var switchIsOn = false

    var body: some View {
        Form {
            Toggle(isOn: $switchIsOn) {
                Text("Switch 1")
            }
        }
    }
}

First, we need a mutable variable to hold the state of our switch. In this case, we have a Bool, named switchIsOn. We have to use the @State wrapper so it can be modified in our view.

Next, when we build our Toggle, we need to provide a binding to a property that will hold the state of the toggle. When we pass in the variable, we use the dollar sign to denote that we’re binding to it. So our view holds the current state of switchIsOn, while the Toggle has a binding internally. When the state of the Toggle flips, it is propagated through $switchIsOn back into our view.

Creating a manual binding

If we again look at Apple’s description of a binding, we see that it involves a two-way connection. The binding needs to know the value to get, and where to set the new value when it is changed.

With that knowledge, we can look at how Binding workings. Let’s look at our example again. This time, we’re going to make a binding ourselves.

struct BindingExample: View {
    @State var switchIsOn = false 

    var body: some View {
        Form {  
            Toggle(isOn: Binding(get: {
                self.switchIsOn
            }, set: { newValue in
                self.switchIsOn = newValue
            }) ) {
                Text("Also Switch 1")
            }
        }
    }
}

Binding has an initializer that takes a couple of arguments. One, with the get label, is a closure explaining where the binding gets its value. In our example, this is our switchIsOn variable. The other, set, is given the new value for the binding. This gives us the opportunity to do something with it now that it has changed. In our case, we’re setting switchIsOn to the new value.

In its most basic form, Binding opens up a lot of interesting possibilities. In later posts, I’ll talk about when we might want to create a binding between our views, as well as some interesting problems a manual binding can solve.

Property Wrappers in Swift

With Swift 5.1 and Xcode 11, many new features came to Swift. A lot of these were built in to help enable SwiftUI in Apple’s latest OS releases. While diving into SwiftUI is a great way to understand those features, there are some that we don’t need to go into SwiftUI to understand. One of these is property wrappers.

I like to explain property wrappers by a literal definition of the phrase: They wrap properties in functionality. While there are some built into various Apple frameworks (ie SwiftUI), it’s easy to create your own, and they can give you a lot of neat functionality.

How to create a property wrapper

To define a property wrapper, you need to have a custom type (I typically use structs) that you mark as a property wrapper with the @propertyWrapper keyword.

@propertyWrapper
struct Wrapper { 

}

By adding that attribute, my type now must conform to its requirements. To do so, I need to add a non-static property named wrappedValue. The type of this property will depend on the kind of wrapper you are building. Let’s look at some practical examples and see what we can build.

Easily decoding an ISO 8601 Date

Since Swift 3, we’ve had the very convenient Encodable and Decodable protocols. The type alias Codable is how we typically see it. Having our models conform to Codable allows us to easily encode and decode our models to and from JSON for API communication.

The Date type conforms to Codable. But how does it encode/decode by default?

struct DateTest: Codable {
    var date: Date = Date()
}

let dateTest = DateTest()
let data = try JSONEncoder().encode(dateTest)
let json = try JSONSerialization.jsonObject(with: data, options: [])

print(json)
// {
//    date = "608081487.019236";
// }

Okay. At least Date can encode automatically. I can live with that. But it looks like it’s turning a date into a number. What if we want to work with different standard, such as an ISO 8601 Date?

What is an ISO 8601 Date? It a popular date format presented as a string where a date like 10:43 pm on April 4, 2020 would appear like this:
2020-04-08T22:43:30+00:00

So can Date decode this by default? Let’s find out!

let isodateJSON = """
{
    "date": "2012-07-14T01:00:00+01:00"
}
"""

let isoDecodeTest = try JSONDecoder().decode(DateTest.self, from: isodateJSON.data(using: .utf8)!)

So using a multi-line statement in Swift, I’m going to try and decode an instance of our DateTest struct with this JSON object. Will this work? If you saw how Date encoded itself, then you won’t be surprised by the response we get from trying to decode this JSON.

ERROR: typeMismatch(Swift.Double, 
    Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "date", intValue: nil)], 
    debugDescription: "Expected to decode Double but found a string/data instead.", 
    underlyingError: nil))

While we have a valid date format, Date is expecting a Double. What can we do?

We could create a custom JSONDecoder when decoding our type. But if we want to support ISO 8601 dates across various models, then we have to create custom decoders for all of them. That could end up being a lot of manual decoding work. OR… we could create a property wrapper to automatically decode the string coming from our JSON into a valid Date.

We start by creating our property wrapper. Ultimately, we want to provide a Date. So that will be our wrapped type.

@propertyWrapper
struct ISO8601Date {
    var wrappedValue: Date
}

This satisfies the basic requirements of @propertyWrapper. Now we have to add our own functionality. In our case, here is where we will build our custom encoding and decoding capabilities.

We start by declaring ISO8601Date itself as conforming to Codable. This will let us wrap properties in a Codable-conforming model and not cause any errors about a model needing to manually provide such conformance.

Next, we create our custom Codable conformance within our ISO8601Date struct.

init(from decoder: Decoder) throws {
    let value = try decoder.singleValueContainer()
    let stringValue = try value.decode(String.self)
    if let date = ISO8601DateFormatter().date(from: stringValue) {
        wrappedValue = date
    } else {
        throw DecodingError.typeMismatch(Date.self, DecodingError.Context(codingPath: [], 
                        debugDescription: "Failed to decode ISO Date. Invalid string format."))
    }
}

func encode(to encoder: Encoder) throws {
    var container = encoder.singleValueContainer()
    
    let string = ISO8601DateFormatter().string(from: wrappedValue)
    try container.encode(string)
}

Our initializer will try and decode a string. If this string can be used to decode a date in the ISO 8601 standard format, it will do so. Otherwise, it will throw an error. Meanwhile, our custom encode function takes the stored date and encodes it into a string using the ISO8601DateFormatter.

Lastly, we add a simple init to allow the user to set a default value with our property wrapper.

init(wrappedValue: Date) {
    self.wrappedValue = wrappedValue
}

Put all of this together and what do we get? If we look at our original DateTest model, we can now prepend the @ISO8601Date attribute to our date property and it will encode to and decode from an ISO 8601 string automatically.

struct DateTest: Codable {
    @ISO8601Date var date: Date = Date()
}

Using UserDefaults for property storage

You may be using UserDefaults in your app to store simple properties. Perhaps it’s a Bool saying if a user has enabled or disabled some feature. Or perhaps you’re storing a String of the last logged in user. You may have built convenience properties to read and write these values. In doing so, you may have ended up with a pattern like this:

class SettingManager {
    static var userViewedWhatsNew: Bool {
        get {
            UserDefaults.standard.bool(forKey: "userViewedWhatsNew")
        }
        set {
            UserDefaults.standard.set(newValue, forKey: "userViewedWhatsNew")
        }
    }
    
    static var lastLoggedInUser: String? {
        get {
            UserDefaults.standard.string(forKey: "lastLoggedInUser")
        }
        set {
            UserDefaults.standard.set(newValue, forKey: "lastLoggedInUser")
        }
    }
}

There’s nothing wrong with the above code (except maybe hard-coded key values). But as you add support for more and more properties, things get to be real tedious. So if we were to abstract this out, what pattern do we see?

For each property, we are both (a) getting the value from UserDefaults and (b) setting the value to UserDefaults using the same (c) key. With this pattern in mind, let’s approach our property wrapper.

@propertyWrapper
struct UserDefault<StoredType> {
    public let key: String

    var wrappedValue: StoredType {
        get {
            UserDefaults.standard.object(forKey: key) as! StoredType
        }
        set {
            UserDefaults.standard.set(newValue, forKey: key)
        }
    }
}

Instead of using wrappedValue to store a value we initialize, like in our first example, we have a computed getter and setter. It is performing our reading and writing with UserDefaults. The key used for those transactions? We provide it in our property wrapper.

What data type does this work with? You’ll see that we are using a generic type (StoredType). It will inherit the type from whatever you end up wrapping.

But wait! What if you wrap an optional type, like String?. Won’t the getter crash if there is no object for key? Nope! Because it’s coming back as an optional, or Optional.none case (if you look at how Optionals work in Swift), which is a valid value for something of type String?. But if we did try to read a String that wasn’t there, then it would crash.

So how about we add a default value?

@propertyWrapper
struct UserDefault<StoredType> {
    public let key: String
    public let defaultValue: StoredType

    var wrappedValue: StoredType {
        get {
            UserDefaults.standard.object(forKey: key) as? StoredType ?? defaultValue
        }
        set {
            UserDefaults.standard.set(newValue, forKey: key)
        }
    }
}

Now we will attempt to return a value of type StoredType from UserDefaults but, in the event no such object exists, we will return our defaultValue.

How can we use this in our SettingManager above?

class SettingManager {
    @UserDefault(key: "userViewedWhatsNew", defaultValue: false) 
    static var userViewedWhatsNew: Bool    

    @UserDefault(key: "lastLoggedInUser", defaultValue: nil) 
    static var lastLoggedInUser: String?
}

If we were to add support for a new property stored in UserDefaults, it is super simple.

Now, notice how we are setting the key and defaultValue properties when declaring our property wrapper. This is making use of the synthesized initializer on our struct. You could make your own init function and use it when declaring the property wrapper.

Summary

Property wrappers are super helpful. They can help you take repeated code and patterns away from your properties and move them into a reusable component. As we’ve seen here, you can make various Codable edge cases easy to solve. They can also help you with code you find yourself repeating in things like a set, didSet, or other such case.

Like other Swift features, property wrappers are just another tool that are worth having in your developer tool box. I hope this post helped demystify them a little bit and make them more approachable for you.

You can find the code for this post in this Github Gist.

Swift Protocols Aren’t Scary

For people new to Swift, or coding in general, there are some keywords that might seem daunting. Optionals. Generics. Sometimes you can explain these in a simple way. Other times, exposure to them might scare learners.

Protocols might seem like a big concept for some. If you look at how many protocols exist in various frameworks, you might think, “Wow, that’s a lot to learn! When will I use all of these?”

For instance, the Int type conforms to 11 different protocols. Do you need to know them all?

What is a protocol?

A protocol is essentially a blueprint. It defines functionality. This can be requiring the existing of certain properties or functions. Something that conforms to a protocol is required to provide the required elements.

For instance, I could declare a protocol that requires the conforming object, whether a class, struct, or enum, to have a name property.

protocol Nameable {
    var name: String { get set }
}

If I have a struct representing, say, an instrument, I can have it conform to that protocol, which will require the presence of a name property.

struct Guitar: Nameable {
    var type: String
    
    var name: String // Required because of protocol
}

Protocol conformance can be declared when you create your type, or it can be done in an extension. However, extensions cannot contain stored properties, so you can only add support for required functions in extensions.

protocol DataSource {
    func numberOfItems(in section: Int) -> Int
    func dataToShow(at indexPath: IndexPath) -> Data
}

class DataManager {
    // Your class stuff here
}

extension DataManager: DataSource {
    func numberOfItems(in section: Int) -> Int {
        // Return the number of items in each section
    }
    
    func dataToShow(at indexPath: IndexPath) -> Data {
        // Return some data to show for each row/section
    }
}

When would I use one?

You would use a protocol when you want to require functionality for a type. When would you use this?

With the exception of very basic iOS applications, you are likely to come across a protocol and not even realize it. Consider the following example:

class MyTableViewController: UIViewController {
    
    var tableView: UITableView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        tableView.dataSource = self
        tableView.delegate = self
    }
}

Here, we have a view controller that we’ve created. It has a table view in it. To have a working table view, we need to have a data source and delegate. In simple examples, you would see what we have here: the class itself conforms as a datasource and delegate.

To do that, we’d have to have our class conform to 2 different protocols. One tells the requirements for the data source, the other tells the requirements to be a delegate.

extension MyTableViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // Return number of rows in each section
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        // Return the table view cell for each part of the table view
    }
    
    
}

extension MyTableViewController: UITableViewDelegate {
    // Add support for the delegate methods you want to support
}

So here, we’ve told our class to conform to two protocols so that it can satisfy the requirements of the table view.

They’re just blueprints

When we look at the above example of the UITableView, when it’s looking for something to be a data source, it’s wanting something that conforms to UITableViewDataSource. It’s basically saying, “If you conform to these blueprints, you, too, can be a data source!”

Don’t look at the presence of ALL protocols available to use as daunting. Remember: it’s just saying there are dozens of blueprint options out there. But they’re only used for specific reasons. UITableView wants its data source to conform to a certain protocol. UIScrollView’s delegate has certain requirements.

And what about what you might make? Would you ever want to make a protocol? Sure. If you ever want to require your types have certain properties or functions, you would create your own protocol. You’d basically be drafting your own blueprints in Swift.

That’s all protocols are. Blueprints. They’re not scary at all.

Swift Coding Puzzles #2 – Balanced Brackets

This is part of a series of coding puzzles inspired by the #CodingPuzzle tag/puzzles originally curated and shared by Ali Spittel. This is my approach to solving those puzzles in Swift. If you have any comments or answers you want to share, post them below! I’d love to read them.


Puzzle #2

Given strings of brackets, determine whether each sequence of brackets is balanced.

When would you come across a situation like this? Well, if you ever write a source editor, you might come across something like this. As most programming languages use brackets to denote context, functions, and other divisions, we’ve probably all come across a situation where we forgot to close something off.

For the sake of this exercise, let’s define what brackets mean. In this case, it’ll be three sets of characters: ( ) , [ ] , and { } . The first character we’ll call the “open bracket” and the latter the “close bracket”.

So, what makes a balanced sequence?

  1. A matched pair of brackets.
  2. Any nested brackets must also be matched pairs.

An example of some balanced sequences include: () , [(){}] , {([()])}

An example of some imbalanced sequences include: (() , [([)]] , {([)]}

If any of those become unpaired, then the entire sequence is considered imbalanced. If you’ve ever created a class in Swift and forgot to close a brace when defining functions, you’ll know what that is.

By the above definitions, we can thus determine that in a balanced sequence:

  1. It has an even number of brackets
  2. An open bracket will never meet a close bracket of a different type
  3. A closed bracket will never appear before its corresponding open bracket

That said, here’s how I approached the problem.

First, I defined what each of the brackets were.

let brackets: [Character: Character] = [
    "[":"]",
    "(":")",
    "{":"}"
]
var openBrackets: [Character] { return Array(brackets.keys) as! [Character] }
var closeBrackets: [Character] { return Array(brackets.values) as! [Character] }

Using a dictionary, I’ll be able to easily look up the close bracket for a given open bracket.

Next, let’s look at my function to solve this.

func isBalanced(_ string: String) -> Bool {
    if string.count % 2 != 0 { return false }
    var stack: [Character] = []
    for character in string {
        if closeBrackets.contains(character) {
            if stack.isEmpty {
                return false
            } else {
                let indexOfLastCharacter = stack.endIndex - 1
                let lastCharacterOnStack = stack[indexOfLastCharacter]
                if character == brackets[lastCharacterOnStack] {
                    stack.removeLast()
                } else {
                    return false
                }
            }
        }
        if openBrackets.contains(character) {
            stack.append(character)
        }
    }
    
    return stack.isEmpty
}

First, if the string has an odd number of characters, we automatically fail it. This is in line with point number 1 above.

I then declare a variable to temporarily hold brackets. This stack will be used in the following loop.

Next, we go through each character of the string. Our first check is whether the character is a close bracket or not. If it is, and our stack is empty, it means we’re encountering a close bracket before its open bracket counterpart. We thus return false. If the stack isn’t empty, we check if the last character on the stack is an open counterpart of this close bracket. If it is, we remove the open bracket from the stack. Otherwise, we return false.

If it’s not a close bracket, we’re likely looking at an open bracket. Those automatically get added to the stack.

This loop functions for all characters in the string. Afterwards, our return is whether or not the stack is empty. If it’s not empty, it meant we had more open brackets than closed brackets, and while the earlier catches may not have produced a return, it technically is an unbalanced bracket set.

Here are a few sample calls to this function and their outputs.

isBalanced("()") // True
isBalanced("[]") // True
isBalanced("][") // False
isBalanced("[][") // False
isBalanced("()()") // True
isBalanced("[(){}]") // True
isBalanced("{{[()()][]}}") // True
isBalanced("[]()({)}") // False
isBalanced("(((") // False

I had initially hoped to tackle this with recursion, but I found the above solution to be easier to follow and much easier to manage.

Did you have a different solution? Is there something I could improve with my Swift code? I’d love to hear from you!

Swift Coding Puzzles #1 – Simple Pig Latin

I’ve been following Ali Spittel‘s #CodingPuzzle challenges. While I’ve read most of them, I haven’t actually done them.  But each of them would be a fun little exercise. So, I figured I’d go back and tackle each of them in Swift.

Before I start, a note: There are always multiple ways to tackle coding challenges. This is just my approach to it. If there are better/more optimal ways of doing it, please comment and share your solutions! I’d love to see them. This is as much a way for me to share what I’ve done as it is for me to learn from how others see problems and want to solve them.

That said, here is the first puzzle:

Puzzle #1 – Simple Pig Latin

“Move the first letter of each word to the end of it, then add “ay” to the end of the word. Leave punctuation marks untouched.”

If this was just taking a sentence without punctuation, this would be a lot easier. You could split the array, modify the words, and rebuild the sentence. But keeping punctuation untouched adds a bit of a challenge.

Being me, I also wanted to make sure that this would handle if someone inadvertently misses a space after some punctuation. (No, this likely doesn’t handle apostrophes properly, so contractions will probably not be correct; but I’m no native Pig Latin speaker to know.) So I may have put a little too much thought into this.

First, I wanted to make a function that modifies a word into its proper Pig Latin form.

/// Takes a word and makes it Pig Latinized
func pigLatin(word: String) -> String {
    var newWord = word
    let startIndex = newWord.startIndex
    let firstCharacter = newWord[startIndex]
    newWord.append(firstCharacter)
    newWord.append("ay")
    newWord.remove(at: startIndex)
    return newWord
}

With this function, I can now pass in parts of a sentence as needed. With that done, now I just need to get the words to pass in.

I could have split the array based on space, but that wouldn’t necessarily preserve punctuation. So I instead opted to go through the string character-by-character and parsing words that are found.

func simplePigLatin(_ text: String) -> String {
    let characterSet = CharacterSet.whitespacesAndNewlines.union(.punctuationCharacters)
    var piggyText = ""
    var temporaryWord = ""
    for (index, character) in text.enumerated() {
        let scalar = character.unicodeScalars.first!
        if characterSet.contains(scalar) || index == text.count - 1 {
            if temporaryWord.count > 0 {
                let pigLatinWord = pigLatin(word: temporaryWord)
                piggyText.append(pigLatinWord)
                temporaryWord = ""
            }
            
            // Append any punctuation or white space
            if characterSet.contains(scalar) {
                piggyText.append(character)
            }
        } else {
            // Append letter to temporary word
            temporaryWord.append(character)
        }
    }
    
    return piggyText
}

I go through each character and, if it’s a letter, I add it to a temporary word. If I hit a non-letter (punctuation or whitespace) or the end of the string, I take that temporary word, modify it for authentic Pig Latin, and append it to the return string.

With all of that, here are some sample outputs:

let word = simplePigLatin("I wish I could speak in Pig Latin; I really do!")
print(word) // Iay ishway Iay ouldcay peaksay niay igPay atinLay; Iay eallyray oday!

let contractions = simplePigLatin("I've got day-to-day issues.")
print(contractions) // Iay'evay otgay ayday-otay-ayday ssuesiay.

let badSpacing = simplePigLatin("I forgot,this is not where commas,go")
print(badSpacing) // Iay orgotfay,histay siay otnay hereway ommascay,ogay

So that’s how you can do Pig Latin in Swift. No, it’s not perfect. There are other cases that aren’t dealt with, such as how to handle words starting with vowels or ‘qu’. But I’m no linguist.

Managing Time for Side Projects

I’m quickly coming up on my two year anniversary at my day job. I’ve learned quite a lot in my professional experience as an iOS developer. But one unfortunate side effect of doing something that I love during the day: it’s hard to find the time and motivation needed to work on my app projects, even when the desire is there.

Max’s tweet was originally about trying to work too much. But I felt inspired to address some of the issues as to why I feel I don’t work enough, whether or not that’s true.

The Problem(s)

Here are a few of the issues I’ve found myself facing:

  • Too Many Ideas – My mind seems to come up with new side projects at least once a month. Of course, there’s no way for me to complete (or even start) many of these. But this has been happening for a while. I still have a file in Evernote with about 6 years of app and service ideas. I want to work on one, but I sometimes get distracted with my list and lose focus on what is achievable.
  • Wrong Project Scope – For the ideas that I am able to actually work on, I find myself dreaming up massive plans. ‘Maybe I’ll completely rewrite X!‘ ‘I could do Y like this, but if I do it like this, it’ll be future proof and everything!‘ What was going to be a simple project that I could enjoy working on becomes a large project that might as well take my full time.
  • Too Little Time – I know what you’re going to say. “Isn’t that the whole point of this post?” Well, yes. But it’s worth mentioning. It’s hard to work on side projects when you spend time playing games or watching TV.  If you’ve set aside time for yourself, you are in control of what happens with that time. And that doesn’t always mean those desired projects get a share of it.Nor does that take into account responsibilities you might have if you’re a husband or father and the time you need to spend with your family.

The Solutions(?)

Before I had my current job, I did a lot of my development work on the side. Sometimes I even found some time during the lulls of the day to get a little bit of work done. But now, I have to try other things.

A few things I’ve ultimately realized:

  • I have to make up my mind. Some work I’ve done on my projects lately has stalled because I can’t make up my mind on what to do. In one example, I’m considering using Realm as a data store. I use Realm at work. It’s something I’m fairly comfortable with. But then I think that I could use this time to try working with Core Data again. Or maybe I’ll just stick to using SQLite directly but use a new library. Soon, I’m stuck in this cycle of each direction being one to consider, but I end up doing nothing but considering choices and don’t end up going any one way. So I’ve started telling myself, as my own boss on these projects, that I have to make a choice, stick with it, and move on.
  • I don’t have to be perfect. Similar to the last point, these projects exist for me and me alone. While I am particular about the quality of my own work, I am not going to be pushing these through any kind of code review. So I can let some things slide. If anything, it gives me things I can address with future releases. But ultimately, I don’t need to perfect something before I release it. So long as it works, I can be content.
  • I have to know what I’m doing. I’ve been a fan of Asana for several years. While it was great for my day jobs, I started using it over a year ago for my side projects.  It doesn’t need to be as complicated as my day job (with Epics, Work Requests, and Iteration planning), but I do need to have some idea for what I want my deliverables to be. Setting that for my various projects, including reasonable feature sets for various stages of release, is helping me to make progress.
  • I need a long term plan. I decided earlier this year to go overboard and plan out my 2018 project goals. I’ve got quarterly release goals (mostly Alpha and Beta releases), planned App Store releases, and a general idea of what I would like to accomplish this year. All of it is set up to be achievable but not overwhelming. So no, I’m not launching 6 new apps this year. Yes, I’m hoping to have at least 1 app update and 1 new app on the App Store by December. ((I said it was achievable. I didn’t say it was impressive.))

Overall, I’m not getting as much done with my side app projects as I’d like. But as I am a developer during the day, that takes a lot of my developer energy. And lastly, I have to balance my interest in side projects with my family, which has my ultimate priority. Thankfully, it’s kept me from being a workaholic. ((As much as I love to work.))

In my case, I just have to accept the reality: I can’t do what I once could. But that’s okay. ((I started this blog post shortly after Max’s initial tweet, and that was 4 days ago. Shows you how my time is allocated.))

iOS today view widgets and margins

One of the toughest things I’ve had to deal with while working on an app has been the today view widget. The widget I’ve been working on is very simple: 2 buttons and a label. Yet, there were a couple of issues I kept running into.

  1. When loading the widget, my buttons will appear and layout. With a button tap, the two buttons change size to what is constrained in the Storyboard. This only happens when the widget is loaded and with the first tap. Subsequent taps don’t affect it again.
  2. The widget, as much as I tried, would not appear as it did in the storyboard. Things weren’t centered properly.

The first item I still haven’t solved. The issue that ended up solving the second item is what I thought was affecting the button layout. Essentially, here is what I had: left button is x points from the left edge of the view, is y points from the right button, and has a width equal to the right button. The right button is the same except it has a constraint to the right edge of the view instead of the left. I had hoped that this would lead to a dynamic button size that would change on various devices and widths. Unfortunately, the small issue with the resizing buttons kept bothering me. If someone can figure this out, let me know.

The second issue was actually fairly easy to figure out. If you look at any of your current widgets, you probably notice two different layouts: ones that are full width, and ones that start indented.

I thought that Apple wanted all widgets indented, but there are even some of Apple’s own widgets that are full width. While it wouldn’t solve the first issue I was having (and gave up on), it did impact why the storyboard, set to the width of the device, wasn’t looking like what my widget was showing.

To solve this, make use of the NCWidgetProviding protocol. There is a method called widgetMarginInsetsForProposedMarginInsets  that you can use to either accept the default margin or set it to a custom value.

- (UIEdgeInsets)widgetMarginInsetsForProposedMarginInsets:(UIEdgeInsets)defaultMarginInsets
{
    return UIEdgeInsetsZero;
}

By removing the insets, I suddenly had a widget that not only was centered but also was taking up the space in the view as it was in the Storyboard.

If you want to see what I was working on, check out Countr on the App Store.

Countr, my first app on the App Store

It’s been many months since I last talked about app development. I’m a bit disappointed with myself, personally, and how much I haven’t shared. It’s been a fun experience as I’ve dived into Objective-C, Xcode, and learning how to develop things on my own. Since then, iOS 8 was previewed (and since launched), Swift was introduced as a new programming language, and more APIs and development tool updates have happened across the Apple ecosystem.

Well, I’ll be writing more thoughts about the development process soon. But first, I wanted to talk about the first app I’ve developed through to launch. That is Countr, a simple app to quickly take a count. I had wanted an app to help me take a count when I’m at certain meetings or assemblies. I feel this app does this excellently.

While the app was released in late August, I only just now announced it. Moving to Arizona took up a lot of time. Go figure.

Countr not only helped me learn the development process, but I got a nice overview of the app release process. I’m very grateful for the update to iTunesConnect, which has made it a much more attractive experience when checking on the status of my app.

In upcoming posts, I’ll talk about developing Countr, developing for iOS in general, and some other things that I thought were pretty cool.

I want to thank the few friends that helped beta test Countr before release. I got a lot of good feedback and, while it is a simple app, the others that I’m working on are not as simple. I made sure to use the same process with Countr that I would expect with a larger, complex application. It’s been insightful, and I’m ready to release more apps later this year.

Countr is available for free on the App Store.