I'm not sure I ever actually released v0.12, even though I announced it back in November. How'd I get away with that!?

To make up for that I released v0.13 a bit preemptively. I try and keep the master branch for bug fixes, but I accidentally merged a fix that was from my development branch, and decided it was as good a time as any to release a new version.

Some stuff might break on you!

The UITableView.plain and UITableView.grouped methods used to return a "full screen" view, but the iPhone 5's 4-inch screen made that a bit cumbersome, plus the fact that the iPad has a different size again... rather than do device/screensize detection, these methods return a UITableView with size [0, 0]. Check your code for these methods, and update as necessary. If you've been adding support for the 4-inch screen, you probably already have fixed this change.

Another strange bug that I came across is in the NSUserDefaults methods. Here's the bug:

NSUserDefaults['key'] = nil

You can't assign nil to NSUserDefaults. Bah. Now, in this case you could just remove the key instead of assigning it anything. When you try and fetch the value later, you'll get nil. And you're right, and SugarCube does do this. But what about when you have a container that has a nil value:

(main)> NSUserDefaults['test'] = [1,2,nil]
2012-12-28 08:07:26.756 Foo[37985:1dc03] *** -[NSUserDefaults setObject:forKey:]: Attempt to insert non-property value '(
    1,
    2,
    "<null>"
)' of class 'Array'.  Note that dictionaries and arrays in property lists must also contain only property values.
=> [1, 2, nil]

** kaput *! The approach I took is a temporary hack, and I apologize for it. I'm going to move the nsnulldammit project *into SugarCube so that we can have a real nil value, but for now it converts it into false, and stores that instead. Better than nothing, I guess, but still, very wrong.

Yet Another Gesture Wrapper

I can't promise that this code will stick around, because I'm going to talk to the BubbleWrap guys and see if we should merge our implementations, or if we should break it out into a new project. But in the meantime, here they are!

This is an "opt-in" part of SugarCube, it is not available just by installing the gem. In your Rakefile, add:

require 'sugarcube-gestures'

And you'll gain these methods:

view.on_tap
view.on_pinch
view.on_rotate
view.on_swipe
view.on_pan
view.on_press
view.on_gesture gesture

Rather than document them here, I just added Yard documentation to those methods, so check them out [at rubydoc.info]http://rubydoc.info/gems/sugarcube/0.13.5/UIView#on_gesture-instance_method

SugarCube::Adjust is even more helpful!

Everyone's favorite REPL helper has a few changes to make it more useful.

  • gloabls. Instead of using class variables, I'm storing the adjust item and the tree items in global variables ($sugarcube_view and $sugarcube_items)
  • tree. More than just views! You can pass it a UIViewController, UIView, or CALayer and it will output that hierarchy.

to_s methods

I'm trying to add sensible to_s methods so that the tree view is more useful. UILabels and UITextViews output their content (truncated), UIColor tries to output it's hex code, that sort of thing. If you are writing a UIView and you want to support this, you can use code like this:

def to_s
  if defined? SugarCube
    super inner: {text: self.text, placeholder: self.placeholder}
  else
    super
  end
end

NSData <=> {NSString,UIImage}

You can convert to & from NSData, very helpful for POSTing via HTTP. The default encoding for strings is UTF8, and the default image reprsentation is PNG.

# image => data => image
image.nsdata.uiimage
# string => data => string
string.nsdata.nsstring

Date styles

Date formatting is a bizarre topic in Cocoa, if you're used to strftime-flavored methods. But once you get the hang of it, it IS much better, because it takes localization into account. A few basic formats:

date = NSDate.new
# pre-baked templates
date.string_with_style(:short)
date.string_with_style(:medium)
date.string_with_style(:long)
date.string_with_style(:full)
date.string_with_style(:none)
# custom
date.string_with_format('LLLL d yyyy')
# => "December 28, 2012"

new is broken!

On some classes, the new method is downright deadly, and as I find those I'm adding them to SugarCube. Two so far: NSDate and NSError. Both accept zero arguments, and so are "backwards compatible" with the versions that never worked in the first place.

Actually, NSDate.new works, but spits out a memory error. NSDate.date doesn't complain, and that's what SugarCube uses.

NSError.new accepts an error message and options:

NSError.new  # => 'Error'
NSError.new 'An error occurred'
NSError.new 'could not find it', code: 404
NSError.new 'could not find it', code: 404, domain: 'http'
NSError.new 'could not find it', code: 404, domain: 'http', userInfo: { any: 'thing' }

UIActionSheet, the sensible accompaniment to UIAlertView

UIActionSheet.alert('message', buttons: ['cancel', 'DESTROY', 'ok']) { |pressed| puts "pressed" }
UIActionSheet.alert('message', buttons: ['cancel', 'DESTROY', 'ok'],
  cancel:->{ puts "canceled" },
  destructive:->{ puts "destroy" },
  success:->{ puts "success" })

Pretty much like UIAlertView, but tailored for the action sheet interface.

UIImages never looked so good!

You can do some pretty handy image editing using the UIImage additions:

  • tileable(insets) # insets are optional
  • stretchable(insets) # insets are optional
  • scale_to # scale without stretching
  • in_rect # stretchs
  • darken # e.g. for a 'pressed' button
  • rotate

I hope you enjoy!