Day 80 - 100 Days of Swift

3 minute read

Project 24 (part 1)

Day 80 is the first part of the twenty-fourth project. It is a technique project where you look at some of the ins and outs of Swift Strings. You look at the fact that they are not simply arrays of primitive chars like in many other languages. You look at some potentially useful extensions and techniques for working with Swift Strings. And you have a very quick look at using NSAttributedString to format Strings in different ways.

First, he talks about how a String in Swift is not simply an array of primitive characters. So while you can do this:

1
2
3
4
5
let name = "John"

for letter in name {
	print("Give me a \(letter)")
}

You cannot do this:

1
print(name[3])

In Swift, you would have to do this:

1
print(name[name.index(name.startIndex, offsetBy: 3)]

You could write an extension to add subscript-ability to Strings, but it gets to be pretty inefficient pretty quickly, so there are other ways of dealing with the common String problems in Swift. For instance, you should always use .isEmpty instead of checking if the count is 0:

1
2
3
4
5
// do this
if someString.isEmpty { // do stuff

// not this
if someString.count == 0 { // do stuff

Next he looks at a couple of extensions you could write using the built in functionality on String. You could write these functions that will delete a prefix or suffix, if they exist:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
extension String {
    /// remove a prefix if it exists
    func deletingPrefix(_ prefix: String) -> String {
        guard self.hasPrefix(prefix) else { return self }
        return String(self.dropFirst(prefix.count))
    }

    /// remove a suffix if it exists
    func deletingSuffix(_ suffix: String) -> String {
        guard self.hasSuffix(suffix) else { return self }
        return String(self.dropLast(suffix.count))
    }
}

print("12345".deletingPrefix("123")) // prints 45
print("12345".deletingPrefix("358")) // prints 12345
print("12345".deletingSuffix("345")) // prints 12

Or you could write an extension that capitalizes the first letter of a string, instead of the first letter of every word:

1
2
3
4
5
6
7
8
9
10
11
12
extension String {
    /// capitalize the first letter
    var capitalizedFirst: String {
        guard let firstLetter = self.first else { return self }
        return firstLetter.uppercased() + self.dropFirst()
    }
}

print("it sure looks like rain".capitalized)
// prints "It Sure Looks Like Rain"
print("it sure looks like rain".capitalizedFirst)
// prints "It sure looks like rain"

And you could write an extension that would check whether a String contains any of the strings in a given array. But, there is a simpler way to do it using contains(where:):

1
2
3
4
5
let input = "Swift is like Objective-C without the C"
let languages = ["Ruby", "Python", "Swift"]

print(languages.contains(where: input.contains))
// prints true

This will loop through each of the values in languages and check to see whether input contains that value.

Finally, you look at using NSAttributedString to give some attributes to some or all of a String:

Screenshot of strings with attributed text.

And that’s it for today. I’m hoping we get more into the attributed string thing tomorrow though, because it looks pretty cumbersome so far. There has to be easier ways of dealing with formatting at scale. Or at least some patterns people have adopted. But I guess we’ll see tomorrow.

You can find my version of this playground at the end of day 80 on Github here.