Swift

Introducing... Tarrific!

One of the best things about being an independent app developer is that if you have an idea for an app that would make your life better or easier, there’s nothing stopping you from developing it, and then getting to share it with others. My newest app, Tarrific, falls squarely in that category. I love to cook, and often use a kitchen scale. The tare (or zero) button on the scale is a great way to add new ingredients to a bowl, and weigh them as you go. But, when you forget to zero out a scale first, or the scale decides to time out and turn off while you are working, you’re stuck. How much do the contents weigh? Who knows. Another common situation I found myself in was having my ingredients in a bowl, but wanting to divide them in half, or quarters, etc. Without knowing the exact weight of the contents, or remembering to zero out my scale before I added something and hoping it doesn’t turn off before I’m done, it was really hard to be exact.

Icon-40@3x
From this idea, Tarrific was created. Tarrific lets you store the weights of all of your bowls, measuring cups, dishes — anything you’d like. So, there’s a little bit of setup to do - just grab your most used bowls, weigh them, and save them in the app. Then, when you are in the middle of a big cooking project, just put the bowl and its contents on the scale, and use Tarrific to do something very simple — subtraction! If you pick a saved container, and then enter in the total weight, you’ll be given the weight of the contents. Not so fancy, really, but it can be real lifesaver when you are in the middle of a recipe, and just need to remember how many cups of flour you’ve added to the bowl (it’s about 120g a cup for most flours).

Once you know the weight of the contents, you can do something even more fun — division! Just tell Tarrific how many portions you’d like the contents divided into, and it will tell you what weight you should see on the scale as your remove each part. So, dividing the contents in half is now easy. Pick your container, enter the total weight into Tarrific, and then specify that you want two portions. You’ll then be shown the exact value the scale should display once you have removed half of the contents. I’ve found this invaluable for everything from creating evenly sized mini meatloaves to getting exactly 12 perfectly portioned muffins.

Another fun thing about the development process has been having it tested by my mom. She had been keeping a written list of the weights of her most often used bowls, just so she could subtract the weight out later. She already used an iPod touch for a kitchen timer app, so was able to start using Tarrific as well. This has been the first app of mine that she she had a real reason to use, and it has been a fun process to get her feedback on everything from the icon design to “what does that button do??”.

I’ve learned a lot through this particular app development process, and hope to share some of the new tools and techniques that I tried out on the blog over the next few weeks. For an app that is essentially something very simple (subtraction and division), I really tried to concentration on the design, keeping it simple, streamlined, and useful in the kitchen.

Preview of the tech-y details for the curious: It uses Core Data (my first app trying that out), 100% Swift, fastlane for some of the testing (brand new to me - so cool, but I’m still learning), XCode-based UI animation and unit tests (my first time trying those new tools out), cocoapods (not too many), PaintCode and Sketch for graphics (of course!), and all of the UI done in code, not in IB. That last one was a tricky choice, as an app this simple probably could have been done in IB without too much work. But, I’ve gotten used to SnapKit for Autolayout, and really like the power it gives me to tweak UI values and see all of my constraints in one place. Doing AutoLayout right makes it so much easier to support different size classes and screen sizes, including split screen on new iPads.

If you love to cook, and use a kitchen scale, I hope you’ll give Tarrific a try. It’s free in the App Store. If you really like it and find that you want to add more than four containers, there is a one-time $1 upgrade to unlock unlimited containers. I’d love to hear from you if you try it and want any new features added. Happy cooking!

A Swifty New Year

Do you listen to Under the Radar, the new(ish) podcast from David Smith and Macro Arment? I have been enjoying it, having missed the shorter format of David Smith’s original podcast, Developing Perspective. It directly relates to topics of interest to indie developers, and the shorter format focuses the conversation a bit.

Because of their ergonomics episode, I finally took the plunge and bought a standing desk. I’ll talk more about that in a separate post, but it has been a really positive experience.

I was surprised by their take on Swift, though. Both developers were emphatically in the “no-Swift-for-me” camp for now. This post is my take on moving to Swift, and what I see as the benefits and drawbacks to doing so at this time.

For the new year, give Swift a try. The barrier to entry is low. Every developer has XCode, and its Swift support just keeps getting better. I can understand the reluctance during the Swift 1.0 days. I didn’t play with it then much, either. I found Playgrounds slow, and the compiler crash-prone. Everyone who was talking about Swift seemed to have jumped right into the deep end of complexity with discussions of functional programming and obscure language features.

But, things have improved. Apple has put together a lovely tutorial where they walk you through a nontrivial iOS app using Swift (no temperature converters here!) Start there and just see how you like it. Many of the tutorials on raywenderlich.com have been re-written in Swift. Take one you’ve done before (or a book you’ve purchased in the past), and try it out in Swift.

One approach I haven’t been as successful with is writing some new functionality in an existing Objective-C app in Swift. It can be done, but I find switching between the two to be less efficient. Plus, although the way Swift interacts with the existing Cocoa APIs is improving, it will still feel more clunky than just calling things from Objective-C.

Also, don’t start reading all of the hardcore Swift blogs right away. They bring up cool points, but are too specific and detailed to be useful at first. I found them confusing and overwhelming. However, now four months in to writing Swift almost every day, I have found myself revisiting some of the older posts, and better understanding the concepts they were trying to explore. The WWDC 2015 Swift videos are also nice to watch once you have a bit of practical Swift under your belt.

It will feel frustrating at first - Swift code will take you probably twice as long to write as equivalent Objective-C, and you’ll still be looking things up and fighting compiler errors. Once you have working Swift, it will probably just be Objective-C style, but written in Swift. THIS IS FINE. You spent years building up your Objective-C skills - they are not going to be as easy to discard for a newer, shinier language.

But, when it comes time to create something new, consider Swift. You will end up writing significantly less code overall. As you become comfortable with optionals, value types, and the class/protocol model, you will slowly start to change your style and write more “Swift”-ly. Only then start following Swift blogs. You should also keep an eye on the future of the language that is unfolding on Github. No point in getting attached to a language feature that is destined to disappear (I’m looking at you, c-style for loops…) Give the Xcode migrator less to do by starting to follow future conventions today.

I wrote two apps for AppleTV entirely in Swift. The first went pretty slowly. It felt like I was not only learning a new programming language, but the Cocoa APIs as well. Concepts that seemed so clear when reading the Swift docs seemed more complicated in practice. However, the next Swift app I wrote for AppleTV was essentially written in three days. I now have a hard time bringing myself back to Objective-C. I had written in Objective-C since 1992, and have been surprised by how quickly and completely I want to just stay in Swift.

And then, once you’re ready for it, definitely check out Erica Sadun’s new book, The Swift Developer’s Cookbook. This book is Hard Core, but in a totally amazing way. If you want to start writing code that is not warmed-over Objective-C, and takes advantage of some of the truly cool language features of Swift, this is the book for you. I’m working through it slowly, but find that I am learning something new in every chapter. It is to be savored and digested gradually (ha! because it’s a cookbook! didn’t even to mean to make that pun…).

Here’s to a 2016 is filled with great apps written in Swift!



Shrinking Swift Arrays

I’m really moving ahead with a new project (for tvOS!) and writing it entirely in Swift. On basically the second day of coding, I was really missing some NSArray/NSMutableArray functions from Swift Arrays, and after way more StackOverflow/Google time than it should have taken, here’s a version of removeObject that seems to compile:


Note also that the indexOfObject method on NSArray is replaced by the native indexOf method, so no need really to reimplement that.

Enjoy!

Code Spelunking - DGRunkeeperSwitch

This post is the first of what I hope will be many that takes a piece of software that has been released publicly (usually on github) and looks at the code to learn more about it. I always learn a lot by reading other people’s code, and thought it would be fun to take various controls, apps, etc. and break them apart and point out what I find interesting about them.

The first control I’m choosing is the DGRunkeeperSwitch by Danil Gontovnik. I learned about it from a maniacdev email this morning, and I was immediately drawn in by the smooth animation and clean lines of the control. I use Runkeeper (less regularly than I used to due to the Apple Watch), but hadn’t noticed the control until I went looking for it. It is mainly used on screens other than the “Start” tab, which is where I spend most of my time. But, I don’t love the look of the standard segmented control and switch on iOS, so the more stylish look of this control is appealing.

First thing to consider when looking at this control is that it is written using Swift 2.0, so fire up the code in the latest XCode beta. It comes with a small sample app, which is a nice touch (and typical for most controls shared on github, I’ve found).

DGRunKeeperSwitch is a subclass of UIControl.

Swift notes
  • Liberal use of tuples for assignment. Increases compactness of the code.
  • Reasonable defaults for configurable aspects of the control, using defaults for variables on the control
  • Uses the deinit method to remove itself as an observer. So nice to have a well-defined place to do this!

General coding notes
  • Changes the underlying layer class of a few views in two different ways. The first, expected, way is by returning a custom class from the class-level layerClass() method. When your own class wants to change its layer, this works. If you want to change the layer class for a standard view, such as UIView, then you can use the Objective-C runtime method object_setClass to change the underlying class object. This new class object updates the cornerRadius of the view based on the height of the bounds. This is done in one list as a Swift didSet on the frame property of the CALayer. (I would almost count that as a clever Swift trick, since something like this is so much simpler to do in Swift than Objective-c). Also, can you really call it the Objective-C runtime when writing in Swift? I suppose just “runtime” is more appropriate now.
  • The clever thing about this control is watching the color of the text labels change as you swipe the selected “bubble” from one item to the other. This is done by having two copies of each label, stacked on top of each other. They are in contrasting colors to their background. There is a background view between these two sets of labels, which contains the selection highlight. A mask is then applied to the view containing the “selected” labels (the top set of labels), such that the selected title views under the current selection background are visible, and the ones outside the bounds of the selection view are masked out.
  • Both tap and pan gestures are supported. UIView dynamics are used for a nice springy animation when switching between choices. Snapping behavior kicks in if you pan only partway.
  • layoutSubviews() handles positioning the selected rectangle above the selected item (essentially either on the right or left side of the control). If the labels are too long to fit in the specified size of the control, the label spills over its background, which doesn’t look great. Truncating the labels to fit would be better than letting them flow over the bounds of the control. This could be done by just pinning the size of each label to the maximum allowed size.
  • The frame of the selection view and the frame of the mask view are tied together using KVO on the frame property of the selection background view. I’m not sure this is worth it, as you could easily set both frames at the same time, instead of decoupling this. Overall, it is less code to just assign the mask in the two places where it changes, although I can understand the desire to tie the two values together with KVO so that you don’t have to worry how many times the selection view is changed - it will always update the mask when its frame changes. Definitely a design choice, and one that I think could go either way.

Side Trip

I was getting an unexpected error message when running the sample app, that was due to the UIViewControllerBasedStatusBarAppearance key being specified in the Info.plist file. This key had been set to NO to allow the view controller to set the color of the text in the status bar explicitly, using the call UIApplication.sharedApplication().statusBarStyle = .LightContent. Without the entry in the plist file, it doesn’t appear that this call actually changes the status bar color. The warning may just be an artifact of a beta release, but it bothered me. The way to fix this was to remove the key from the Info.plist file, and have the root view controller manage its own status bar style. However, the root view controller is actually a UINavigationController, and it does not, by default, defer to its top view controller for its status bar style, even though that would seem to be the obvious way to handle things. You can fix this in an extension to UINavigationController, which either overrides preferredStatusBarStyle() to return the custom status bar style, or in a more general way, override childViewControllerForStatusBarStyle() to return the topViewController, which then implements prefferedStatusBarStyle() itself. This seems like the more general option, and puts the responsibility to set the status bar color in the hands of the view controller that is presenting the rest of the UI, where presumably we are attempting to match an existing UI to the status bar color. One last Swift gush - it is so easy just to add a quick extension to a system class such as UINavigationController.

I didn’t think I would explore the world of status bar style overrides and system class extensions, but you never know what you’ll learn when you dive into a new piece of code!

Possibilities

It would be interesting to see this control support @IBDesignable/@IBInspectable so that it could be configured in IB. It also could be extended to support more than two choices, making it an alternative to UISegmentedControl in addition to UISwitch.

Conclusion

Overall, a lovely little control with clearly written code that takes advantage of some nice Swift language features to implement things in a clean, streamlined way.
© 2010-2016 Little Potato Software   Follow littlepotatosw on Twitter        Site Map     Privacy Policy     Contact Me