Swift Findings: 001

Today I found two cool/interesting/surprising things about Swift.

First, a closure can be used as a conditional expression in a control flow statement and can also be executed at the same time:

We would probably not want to do this because the caller could pass in any closure, but its just cool to know that we can do this if we wanted to.

 

Second, I learned about two interesting pattern matching styles in switch statements:

Not sure when why if one should do this but its cool to know we can! Check out this related Twitter thread: https://twitter.com/garricn/status/916444820951916545

 

Advertisements

Using Codable with Array

I was converting one of my projects to Swift 4 and ran into an issue where I didn’t understand how to use the new Codable protocol to encode and decode an array of my model object. Here’s a little post explaining what I found out:

Repo: https://github.com/garricn/ggn-blog/tree/master/posts

Raw: https://raw.githubusercontent.com/garricn/ggn-blog/master/posts/060517-codable.swift

There’s also a playground in the repo.

Private Property Mix-Match in Swift Extension

Imagine you have a type (enum, struct, class, it doesn’t matter) like so:

struct SomeType {}

Then you add an extension to it with an internal var foo and a private var bar where foo just returns bar and bar returns the string “foo”:

 

Now, when we call SomeType().foo, we get “foo”, right? Right.

SomeType().foo prints “foo”

Then you add another extension to it with another internal var baz and another private var bar where similarly baz returns bar and bar returns the string “baz”:

 

Now, when we call SomeType().baz, we should get “baz”, right? Wrong.

SomeType().baz prints “foo”.

Weird right? What’s going on here?

Let’s try something else. Let’s remove bar from Extension II and see what happens:

 

Interestingly, we get the following error:

'bar' is inaccessible due to 'private' protection level

This is really weird because on the one hand, Extension II’s bar prints “foo”, but when it doesnt have a bar, the compiler throws an error. Weird, right? Why is that? What’s going on here?. This same behavior is present with instance and static properties and methods on enums (static only), structs, and classes.

This also works where the initial bar is in the original type definition and not in an extension:

Thing().foo and Thing.baz both print “foo”

Is this a bug? If not, why is this the correct behavior? Please let me know @garricn

Interestingly too, if you try this in the IBM Swift Sandbox, it crashes!

UPDATE (about 10 minutes later 🙂 Its a known bug!

Unix is so Rad!

After running SwiftFormat on a directory, SwiftFormat told me that it had formatted 279 out of 280 files. “What was that one file?”, I asked. So Nathan and I figured out how to do this using Unix commands.

We used find . -name "*.swift" > ~/Desktop/all.txt to find all swift files in current directory and output those lines to a file.

We then used git status | grep -E 'swift$' > ~/Desktop/gst.txt to output the result of git status to a file. Running git status after running swift format . shows all swift files changed.

We then used the TextEdit GUI to remove the ./ from the find output and modified: from the git status output.

We then used sort all.txt > allsorted.txt and sort gst.txt > gstsorted.txt to sort the files in alphabetical order.

Finally, we used diff -y allsorted.txt gstsorted.txt to give us a side by side comparison of the two files.

The result? We figured out exactly which file was not changed by SwiftFormat. After touching the file, we were able to format it by running swiftformat [file name].

Unix is so cool!

UPDATE: Cristian gave us a head start on how to do it with one line and Nathan figured it out:

diff <(find iFarmers -name “*.swift” | sort) <(git status -s | tr -d \” | cut -c 4- | sort)

 

Line of the Day #001

Line number 5 was super fun to get to.

It does the following:

  1. Gets newValue from set and uses the nil coalescing operator to either:
    1. Return the unwrapped value if newValue is not nil, or
    2. Return an empty string: ""
  2. Then – using the ternary operator – it checks whether the returned value isEmpty (i.e., is an empty string) :
    1. If it is empty, it sets constant to 0.0
    2. Otherwise, it sets constant to 4.0

To get to that line we started with what you can see in the commented out code starting on line 9. Pretty fun stuff 🙂

 

 

Making a Simple Swift Observable

I’ve been practicing reactive programming recently mostly with SwiftBond and I’ve been enjoying it. I’ve mostly just worked with simple observing and binding. So, I thought how – if at all – could I do simple observing in Swift without using a reactive library, key-value observing, or NSNoticationCenter.

I was able to do it using closures, except that I’m running into an issue where I’m forced to make some properties immutable when I would rather not. Take a look at the project and let me know if you can help me with it. Ideally, I would like to be able to make my viewModel property of my ViewController as well as the alertOutput property of my viewModel constants. The issue is that the observe(onNext:) method of my viewModel is mutating. So, how could I do self.onNext = onNext in some other way? How could I make that method non-mutating? What could I do so that I could keep those two properties immutable?

Check out the project on GitHub. Take a look at the code and let me know if you can help.