Wednesday, October 14, 2009

Can I make a UIView transition to itself?


Sure, why not?

Let's say you have a UIViewController and you want the base view to do a CATransition from itself to itself:

- (void)doTransToSelf {
    CATransition *anime = [CATransition animation];
    anime.type = kCATransitionPush;
    anime.subtype = kCATransitionFromRight;
    anime.duration = 0.5;

    UIView *mySuper = self.view.superview;
    [self.view removeFromSuperview];
    [mySuper addSubview:self.view];
    [mySuper.layer addAnimation:anime forKey:nil];
}


Or, changing this to work on a subview of self.view is trivial.

So, why would you want to do this? In my case, I have a collection of data objects and a UIView that is the user interface for editing one object. When the user is ready to move on and edit the next object in the collection, the user interface doesn't substantially change, I'm really just changing the data object that is the target of the user's edits. So I want to re-use the same view with the same set of IBOutlets, and just do the transition as a visual cue to the user - "okay, you're working on a different object now."

Sunday, June 28, 2009

Why won't my backBarButtonItem use its action?


Or, How to make a backBarButtonItem send its action to its target.

Answer: you don't.

Because a backBarButtonItem is a UIBarButtonItem, it has "target" and "action" properties, leading you to believe that if you assign values to those properties, shit will happen. Alas, shit will not happen. Or rather, the usual shit will happen, but not the extra shit you hoped would happen. The backBarButtonItem is special - no matter what you do with those properties, «target» will never receive a message for «action».

What you can do instead is assign a delegate to either your UINavigationController or UINavigationBar. Both of these classes have delegate protocols that give you opportunities to act when the stack of view controllers changes. I've been using my root view controller as the delegate object, since that one never gets popped off the stack.

Friday, May 22, 2009

Sun. Oracle. Ponytails.


So... Sun. Oracle. And of course Schwartz. Schwartz, Schwartz. Blogging his way through the graveyard, chanting his open source mantra. As if clinging to all the right buzzwords would make up for not having an actual strategy. "I'm a CEO with a blog! How can my company fail??"

There are lots of companies that get by without a strategy, at least for a while. Hell, I used to work for one. But if you're going to get into the business of being a VAR for a product (free software) whose starting cost is zero and whose cost of duplication is zero, you better have a Goddammed plan of how you're going to add enough value to be attractive.

That's why, even as I care less about free software, I do continue to admire Redhat. They started their business with a plan. And when the market changed and the plan faltered, they got to work on a new plan. This happened to them at least twice, until now Redhat is basically a large consulting firm - which is where most free software VARs seem to end up. But hey, as long as they're making money at it, there's nothing wrong with that.

Sun, on the other hand, seemed to get sucked into the open source zeitgeist of the last decade, rather than deliberately enter it. By 2006 when Schwartz became CEO, the vicious round of consolidations and closures among open source companies was ancient history and he should have been able to learn from it. Instead he seemed to think it was still 1996 and he threw more money at open source products without any clear strategy that I could see. That's why Redhat grew from a dorm room operation to a successful corporation, while Sun dwindled from being a key player to being an easy acquisition.

Friday, May 01, 2009

A Thread Across the Ocean


A Thread Across the Ocean was (to my surprise) the only book I could find that tells the story of laying the first transatlantic communications cable. Luckily, it's a good book. It's a classic story of 19th-century ambition to conquer nature (and get rich doing it) and this book tells it well. Recommendation: acquire.

See also: Cryptonomicon.

Wednesday, April 15, 2009

Putting a background behind a UIView transition


When doing a setAnimationTransition: with a UIView, you can do a "flip left/right" or a "curl up/down". If you do a flip left/right, you'll usually see a blank black screen "behind" the view as it flips. (The built-in Stocks app does this.) Recently someone asked me if you could have something else back there, and I thought "huh, that's interesting, I never tried that" and we investigated. It turns out that you can, but you have to set up the view stack properly.

So let's say we have 3 UIView objects, frontView, backView, and rootView. Before the transition begins, frontView is a visible subview of rootView and backView is not yet in the view stack. You begin an animation block and then (usually) do [frontView removeFromSuperview] followed by [rootView addSubview:backView], then commit the animation block and watch the animation take place. You might think that adding another subview of rootView, one that sits below frontView, would make that view be visible behind the animation during the transition. At least, that's what I thought, but it doesn't work. I'm not sure why, but it seems that rootView and all of his subviews become "invisible" during the transition.

But, but! if you put another UIView under rootView, that view will be visible during the transition. Maybe in your project, your views are already set up that way. But if frontView and backView are immediate subviews of the main window, then of course nothing can be below the main window, and you'll need to interpose another UIView object into your view stack.

Instead of posting sample code, I'm going to suggest downloading the LocateMe sample app from ADC. It's already designed with a "main" view and a "flipside" view who are subviews of a root view, and the root view is a subview of the main window. Get the project, open the MainWindow.xib, and add a UIImageView (for example) in the main window:


Make sure the toggleView method is using UIViewAnimationTransitionFlipFromLeft(Right) in its animation block (it doesn't make sense with the curl up/down animation) and then build and run the project.

Tuesday, January 27, 2009

Rails: Database-less ActiveRecord models


It's not unusual in Rails projects to have one or two model classes that don't inherit from ActiveRecord and don't require an associated table in the database. But what if we want half of that? What if we want a model that does descend from ActiveRecord but doesn't exist in the database? I finally found some code for doing exactly that. Here's an example:


class Feedback < ActiveRecord::Base
  validates_presence_of :mailfrom, :comment

  def self.columns
    @columns ||= []
  end

  def self.column(name, sql_type = nil, default = nil, null = true)
    columns << ActiveRecord::ConnectionAdapters::Column.new(name.to_s, default, sql_type.to_s, null)
  end

  column :id
  column :mailfrom
  column :comment
  column :ipaddr
end
I derived this from the code at Caboose's blog. He says he got it from Techoweenie but I can't find it on Technoweenie's site anymore.

So anyway, why would you want this? In Rails, the ActiveRecord class is super powerful. It is of course an ORM first and foremost, but it has other great features. Also, other parts of Rails, ActionView in particular, function at their best if you can provide them with an object descended from ActiveRecord. If you don't have an ActiveRecord object, you have to use form_tag() instead of form_for(), text_field_tag() instead of text_field(), etc. You don't get to use error_messages_for() and you don't get the nifty pre-fills of the model's existing values when you error flash back to the same form.

In my case, I was creating a very simple feedback form so a visitor could provide their email address and leave a comment. The comment would be mailed to the site admins via ActionMailer. I actually had a seperate model, which was descended from ActiveRecord, that made a database record of the time, date, and IP address, but there was no requirement to store the comment itself in the database, so I thought that the Feedback object didn't need to inherit from ActiveRecord. Mistake! Cutting myself off from the best helpers that ActionView offers, something that should have been a dead-simple one-page form became a tedious slog[1] to program. I finally came to my senses and googled around until I found the above code.

I've used ActiveRecord-less models before, so at first I was surprised by my unpleasant experience. Then I thought about it and realized that none of my previous ActiveRecord-less models involved user interaction. They were all "plumbing" and I never needed, or missed, the ActionView helpers. If you're making a view for a model, and that model doesn't inherit from ActiveRecord, you're not doing it The Rails Way.

 [1] "Tedious slog" being relative. I find that Rails raises the bar for ease of (web) programming, to the point where it's actually a shock to deal with the same level of drudgery that PHP inflicts on me on a good day.

Friday, January 23, 2009

EventMachine: a TCP server module for Ruby


I just discovered EventMachine. EM is, at its least, an event-driven library around which you can build a custom TCP server. The nitty-gritty of listening, sending and receiving, and multiplexing connections is all done for you.

That's selling it short, though, because EventMachine can do a lot more. In its own words, EventMachine "provides event-driven I/O using the Reactor pattern." It can be used for other client/server models like serial ports or even interactive keyboard I/O. But it really stands out for abstracting away the low-level hassles of writing a TCP daemon.

Here's a simple Echo service built using EventMachine. (Borrowed from the README file)


require 'rubygems'
require 'eventmachine'

module EchoServer
  def receive_data data
    send_data ">>>you sent: #{data}"
    close_connection if data =~ /quit/i
  end
end

EventMachine::run {
  EventMachine::start_server "192.168.0.100", 8081, EchoServer
}
Here's an example I made. You can pass a class to EventMachine::start_server, and each new connection will create a new instance of your class. That allows you to use instance variables to record distinct state for each connection. This example buffers up the client input until the client sends a ".<CRLF>" a la SMTP, or a maximum of 10 lines.


require 'rubygems'
require 'eventmachine'

class DataBuffer < EM::Protocols::LineAndTextProtocol
  def initialize
    puts "init'ing new instance of #{self.class.to_s}"
    @line_ctr = 0
    @databuf = []
  end

  def receive_data(data)
    @databuf << data
    @line_ctr += 1
    if data == ".\r\n" || @line_ctr == 10
      if data == ".\r\n"
        @databuf.pop
      end
      send_data(@databuf.to_s)
      reset_databuf()
    end
  end

  private
  def reset_databuf
    @line_ctr = 0
    @databuf = []
  end
end

EventMachine::run {
  EventMachine::start_server "127.0.0.1", 8081, DataBuffer
}
And the best part is, I've only been playing with EventMachine for about an hour! I've only begun to understand what it can do.

So, yeah. EventMachine is badass. You should check it out.

Tuesday, January 13, 2009

The Palm Pre SDK, or, In Defense of Javascript


So the Palm Pre is generating a lot of (mostly) positive buzz.[1] There are still a lot of unknowns around it, details of the SDK are still vague, and it may yet all turn out to be sound and fury, especially since no one is allowed to touch it yet.

Most of the negativity so far has targeted the choice of Javascript as the programming language. Personally I've never had a problem with Javascript the language. I think Javascript gets a bum rap. It's a dynamically interpreted, loosely-typed, object-oriented language. Functions are first-class objects, and it has an eval() operator. Sounds a lot like... Ruby. Or Python. Or Perl. What more do you want? Closures? I suspect the Javascript hate comes out because most programmers only work with Javascript in the context of emitting Javascript code from their C# or PHP on the server side, and/or dealing with the inevitable cross-browser inconsistencies of the various Javascript runtimes. Those things do suck, but that's not the fault of Javascript the language. When I heard about an SDK with an Eclipse-based IDE that uses Javascript for programming and HTML5 for UI, my first thought was "Oh, okay, just like Flex Builder, Actionscript, and MXML."

Okay, back to the Pre: the party line is "it's just like building a web app", but we also know the Pre has features that have no analog in web app development. I'm curious to know how they handle things like the camera, or playing sounds, or playing videos. I'd guess the SDK comes with a library of Javascript APIs for interfacing with such things, but again, we don't really know yet.

 [1] I don't like that name though. "Pre", by itself, implies that something newer and better is already imminent if you wait for it. A Palm exec said they wanted to communicate the idea of "the beginning of something new." It took Thomas 5 seconds to think of "okay, how about 'Premiere'?"

Friday, January 09, 2009

iPhone: Development provisioning profiles and the Entitlements file


I found what appears to be a disconnect between Apple's provisioning documentation and what actually goes on in Xcode. If you want to build your project for development (testing) on your own device, the documentation says to select the top-level build target of your application, open the Info window, click the Build tab, and set "Code Signing Identity" -> "Any iPhone OS" to be "iPhone Developer: YourFirstName YourLastName". (Presumably you must enter your name exactly as it appears on the Team page of your developer portal.) That part works fine. Next, according to the documentation, you should set "Code Signing Provisioning Profile" to be the provisioning profile you created for your combination of name/device/application. When I go to my XCode, there is no such entry!

Instead, just above "Code Signing Identity" is an entry called "Code Signing Entitlements". What I had to do is create a new property list file in my project called Entitlements.plist. The contents of that file look like this:



Where the application-identifier is the exact App ID from your developer portal, including the 10-character prefix. And then back in the Info window, set the value of "Code Signing Entitlements" to simply be "Entitlements.plist". Drag and drop the provisioning profile onto the XCode Organizer, if you haven't already. Now you can build and push the app to your iPhone.

Monday, January 05, 2009

Two Desktop icons in Open File sidebar


I recently had a problem similar to this one:

Fix multiple ghost aliases in the Finder's sidebar

I had two Desktop icons in the sidebar of my Open File dialog boxes, in all of my applications. I had only one Desktop icon in the sidebar of my Finder, though. The advice on that page is good advice, but you don't have to trash the sidebarlists.plist file. Instead you can edit it with the Property List Editor, and under "useritems" you'll find the duplicate entries that are giving you grief. Delete one of them, save it, and then - this is key - logout and log back in.