@CloudStorage property wrapper

I wrote a Swift library to help with prototyping (haven’t used it yet in production apps).

CloudStorage is property wrapper that will save values in iCloud key-value storage. These values are persisted across app restarts and will sync between different devices that are signed into the same iCloud account. This property wrapper is similar to AppStorage and SceneStorage, two new types Apple introduced with iOS 14.

The basic API is the same as for AppStorage; add @CloudStorage("someName") in front of a property, to save the value to iCloud key-value storage.

Usage

Make sure you enable the “key-value storage” service in the iCloud capability. See Apple’s documenation.


@CloudStorage("readyForAction") var readyForAction: Bool = false
@CloudStorage("numberOfItems") var numberOfItems: Int = 0
@CloudStorage("orientation") var orientation: String?

See also the example app in the repository.

For what should this be used?

The same caveats apply as with key-value storage itself:

Key-value storage is for discrete values such as preferences, settings, and simple app state.
Use iCloud key-value storage for small amounts of data: stocks or weather information, locations, bookmarks, a recent documents list, settings and preferences, and simple game state. Every app submitted to the App Store or Mac App Store should take advantage of key-value storage.

From Apple’s documentation on choosing the proper iCloud Storage API.

In general, key-value storage is not meant as a general purpose syncing service. If you need any advanced capabilities to prevent data loss, consider using CloudKit instead.

Check out the CloudStorage repository.

Easy Storyboard segues in Swift

When working with a storyboard and segues, the usual method of performing a segue can be a bit cumbersome.

To deal with this, we’ve created a tiny helper called SegueManager that allows you to pass a closure to a performSegue call.

Current situation

Say you have a simple storyboard containing two view controllers: a master and a detail controller, with a segue between them:

Storyboard with Segue

Usually at the point where you’re performing the segue, the information that needs to be passed to the destination segue is also available. However we can’t directly pass it to performSegueWithIdentifier, but instead need to store it.

This is the code needed to store a string for later, and then perform the segue:


private var textForDetail: String?

@IBAction func openDetailAction(sender: UIButton) {

  // Save text for later
  textForDetail = "This is the detail screen!"

  // Kick off segue
  self.performSegueWithIdentifier("showDetail", sender: self)
}

The thing we want to pass to the detail view controller can be as simple as a single string, like it is here. But it can also be a complete view model, specific to the detail view controller.

This is the code needed to pass the stored string along to the destination view controller:


override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
  // Segue is underway, update destination ViewController with value set earlier
  if let vc = segue.destinationViewController as? DetailViewController {
    vc.displayText = textForDetail;
  }
}

Note that if you have want to add a second segue, to a different view controller, you need to add code in three different places;

  1. You need an extra private var for the view model of the second controller.
  2. You need to add an extra if let check to the prepareForSegue code where the private var is passed to the destination view controller.
  3. At the place where you want to perform the segue, you have to also store the second view model in the private var.

Using SegueManager

With SegueManager you can immediatly pass a closure that sets the view model. This nicely scales when using multiple segues.

You first have to create a SegueManager in the master view controller:


var segueManager: SegueManager!

required init(coder aDecoder: NSCoder) {
  super.init(coder: aDecoder)

  // Create a segue manager based on the current view controller
  segueManager = SegueManager(viewController: self)
}

Also, you still need to override prepareForSegue, but it only needs one line of code that never needs to be changed:


override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
  self.segueManager.prepareForSegue(segue);
}

And finally, when you want to perform a segue, you can call performSegue on the SegueManager:


segueManager.performSegue("showDetail") { segue in
  let vc = segue.destinationViewController as DetailViewController
  vc.displayText = "This is the detail screen!"
}

And that’s it! Now, when you want to add a second segue, you only need to add a second call to performSegue, no other code needs to be changed.

Conclusion

Since the SegueManager is so little code, it’s available as a single gist that you can simply copy-and-paste into your project.

I’m curious, currently CocoaPods isn’t available for Swift, but once it is, would you like a tiny library like this to be available as a pod? Or would you be happy with just the gist as it is now?

2015-03-20: Now that CocoaPods has support for Swift, I’ve turned SegueManager into a cocoapod. OS X support has also been added.

AwesomePrelude presentation (video)

Last monday (February 8, 2010) Sebastiaan Visser and I presented our ongoing work on the AwesomePrelude at the Dutch Haskell User Group meeting.

In a previous post “Deeply embedded DSLs in Haskell”, I introduced the AwesomePrelude. While the ideas behind that post haven’t changed, the implementation of the AwesomePrelude is radically different now.

The AwesomePrelude is reimplementation of the Haskell prelude in which all data types have been replaced with type classes. Embedded Domain Specific Languages (DSLs) can implement these type classes to get access to the functions defined in terms of the type classes. For example: by implementing the BoolC type class, a DSL gets to use the (&&), (||) and not functions.

Here’s a recording of our presentation:

The slides are online, and the code is available on github.
The reactive javascript example Sebastiaan mentions in the talk doesn’t use the AwesomePrelude per se, but is based on the same ideas.

Waking on LAN

Computers are really nice machines, they have amazing processing power and can be used for all sorts of noble purposes, such as storing your movie collection family photos.

Unfortunately, they also have the downside of generating heat and noise, so that’s why I keep one of mine at a friend’s house (also because he has a very fast internet connection). Strangely though, it seems he also isn’t to fond of all that heat and noise and turns the machine off when he thinks I’m not using it. So that’s why I needed a way to send a Wake on LAN signal, known as a magic packet, to remotely start the machine.

Yesterday I wrote a small Haskell program called wol (available on Hackage) to send the “magic packet” to his router. We had to flash his router with new firmware to be able to have it memorize the internal ip address/mac address/port combination, but now it’s working!

I must say, it took me an embarrassing amount of time to write this program. For some time, I was stuck on why the socket wasn’t working. Then I found out I shouldn’t use the PortNum constructor to construct PortNumbers, because the endianess doesn’t match on my machine. It turns out your supposed to use the Num instance of PortNumber and use functions like fromIntegral. I’m happy to see other people also noticed how annoying this is, and are discussing a revamped network package.

Anyway, now you can all start starting your machine remotely with wol (which, to be honest, is just a Haskell port of some PHP script I found online…).

Hackage on Twitter

The Haskell community is very active. New packages are released to the central Hackage server each day.

If your like me, and like to keep up on all the different new packages, you can now follow Hackage on Twitter.

But be warned! There’s a lot happening, in the 3 days Hackage has been online, it has already tweeted more than 70 new releases.

The Twitter account is running a tool called hackage2twitter, build on top of the feed2twitter library for tweeting posts from a RSS or Atom feed.

If you want to pipe your own feed to Twitter, you can use the feed2twitter library or executable.

bool-extras released

Ever found yourself in need of a if-then-else replacement that can be partially applied? Something you can pass to higher order functions? In short, ever needed this function?


bool :: a -> a -> Bool -> a
bool x _ False = x
bool _ y True  = y

Well, I did. So I’m very happy to announce my first public Haskell library: bool-extras!