Planet Cocoa

March 09, 2010

Surfin' Safari

Announcing a WebKit Contributors Meeting

Apple will be hosting a WebKit Contributors Meeting at its campus in Cupertino, CA on Monday, April 12 and Tuesday, April 13 from 9am to 6pm PDT. The meeting is targeted at contributors to the WebKit Open Source Project. The meeting will have an “unconference”-like format, allowing plenty of time for impromptu sessions/discussions and hacking.

A new mailing list, webkit-meeting, will be used for general discussion and to communicate additional information about the meeting. You can subscribe at lists.webkit.org. Questions may also be sent to Adele Peterson at adele at webkit.org.

The meeting will be free of charge. All WebKit contributors are encouraged to attend. However, space is limited, so registrations will be accepted on a first come, first served basis.

Please register for the meeting using the meeting registration form by Thursday, April 1.

We hope to see you there!

by Adam Roben at March 09, 2010 08:51 PM

Fun Script

pmougin

In F-Script, blocks combined with message sending can be used to create new control structures fitting your needs (and mood!). Indeed, things like if/else, while or exception handling control structures are all provided at the library level, with no need for specialized syntax in the language itself. In F-Script Switching Options, Jeff explore creating new kinds of conditional control structures:

There are many ways to think through the flow of a program, and times when certain constructs like switch statements are a nice option, even in a language with no syntactical support for it, per se. Philippe Mougin was discussing just such options in F-Script back in the Oughts. I had a need for switching in F-Script, and came up with a few versions that I found useful. Read more…


by Philippe Mougin at March 09, 2010 08:20 PM

Clickable Bliss

ProfitTrain now listed in Bodega

For those who might not be aware, Bodega is an application that acts as a store front for other Mac software. It’s not a controlled system like Apple’s iPhone App Store, but more of an open white pages that catalogs desktop applications.

Bodega

You browse applications via categorized listings or collections such as the staff picks. If you buy the software the transaction goes through the developer’s online store and then Bodega helps the user keep track of receipts, downloads and versions.

I’m very happy to get ProfitTrain listed in Bodega. If you are interested in Bodega I encourage you to check it out. It is a free download at appbodega.com.

by Mike Zornek at March 09, 2010 07:25 PM

Matt Legend Gemmell

Engineer Thinking

I made a remark on Twitter the other day that gave rise to a discussion, and a few of the comments exemplified something I want to briefly talk about.

The actual topic of discussion isn’t particularly germane to my point, but suffice to say that it concerned a situation where Xcode (the development environment for Mac and iPhone/iPad programming) wasn’t doing anything to assist in a very common situation where you’d want to choose one of two possible courses of action, due to an underlying feature of the programming language used.

In probably more than 80% of cases, one particular choice would be made. My point, of course, is that Xcode ought to default to the most common choice, but transparently allow overriding that choice if the other option was needed.

Many people readily agreed, but there were two other types of response which stood out. They were:

  • Xcode can’t know for certain which choice you want.
  • It’s not Xcode’s fault anyway, because it’s due to an underlying feature of the programming language.

Both these responses illustrate what I call engineer thinking, and it’s something that’s both understandable but also incredibly damaging to the user experience of software. (A brief note is appropriate here to say that I’m a software engineer myself; I’m not just pointing fingers.)

Engineering in the real world has taught us (usually the hard way) about tolerances and precision. The axle must be of uniform strength, the furnace must run at a controlled temperature, the structural properties of supporting columns must be carefully designed. Reality tells us that being exacting, and producing the same outcome each time, is the key to not only reliability but even to feasibility itself. That’s all well and good, and has given us our civilisation.

But a problem arises when you allow precision-based design principles to hinder user experience. All too often, when faced with a decision about how to implement certain functionality, engineers take the extreme position that:

  1. A feature must be exactly what 100% of users want.
  2. If the above isn’t true (and it almost never is), the feature must be configurable.

This binary approach is gravely wrong, and unjustly offloads decision-making onto the user of the software. We’ve all seen where this approach ends up: multi-row sets of tabs, scrolling panes of checkboxes, nested radio-buttons and a general overload of configuration.

It has become increasingly difficult to avoid choices in our daily lives, to an extent which many of us find intrusive and counterproductive. Buying coffee in a shop you’re not familiar with leads to momentary paralysis as you work out how to convey the fact that you just want a regular, black filter coffee. This isn’t the way forward.

From the user’s perspective, there is always a default. The engineer will then argue, correctly, that different users will have different opinions as to what that default should be, but here the Universe steps in and reminds us that there’s always a “usual way”. There is always one particular behaviour or configuration or setup which suits more people than any of the others (surprisingly often, there’s one which suits more people than all the rest put together). That is your default behaviour.

The existence of uncertainty is not an excuse for exposing it to the user.

It is software’s responsibility to mask uncertainty and to make the effort to provide a sensible default behaviour. Many users will care more about the fact that there is a default than what the default is. Choice means decisions, and decisions mean effort and second-guessing, and loss of focus and time. The best choice in software is a choice which has already been made for you, invisibly.

There are of course situations where choice is needed, as indeed in the case which spawned this discussion. The key realisation is that there are different ways to present choice. Too often, we’re given choice as a first resort; instead, present choice as a last resort. If the user must be able to choose, then let them do so by overriding a sensibly-chosen default behaviour – and ensure that such situations are as rare as you can make them.

Software cannot just wash its hands of issues of technical complexity or uncertainty; it’s not remotely OK to simply offload that work to the user. Software intended to help with a given task has an implicit expertise; we assume that our photo-editing software knows more about photo-editing than we do. Expertise carries a duty of care whereby the expert is expected to provide the benefits of expertise without the full cost of knowledge. That’s why experts are useful! The same holds for software.

The primary expression of expertise is in knowing effortlessly what the right course of action is in a given situation, and carrying it out without micro-management or endless justification. Make your software such an expert, and a guide and assistant to the user. Don’t force the user to make your software’s decisions for it, or to repeatedly bow down before its keen grasp of the vagaries of choice and uncertainty.

It all comes down to a question of art. Our art (that of software engineering) is not in making it work. If you see it as a significant success that you managed to name some methods, or write code that compiles and runs (or implemented a heap sort, or found the bounding box for a set of points, or parsed some XML), then your career goals are low indeed. Anyone in this industry can do that stuff, including any reasonably proficient final-year undergraduate in Computing Science. That’s core-skillset, vocational learning. You’re not aiming high enough.

Our art is in making the abilities of our software accessible to those who do not know how it works.

Your chance to demonstrate skill and professionalism and genius is by effectively hiding all the circuitry and wiring and batteries and screws behind one big shiny “Get the Job Done” button, whose apparent function is almost magical.

If you’ve exposed underling complexity or unnecessary choice in your software because you see those things as inevitable, it’s because your job isn’t finished. If you’re going to write GUI software for other people to use, do it properly, and treat those people like human beings instead of software engineers. If you want to expose complexity to the user and wash your hands of it, write command-line tools – or utilities that are used exclusively by other machine processes.

You can’t have it both ways. Writing GUI software is for people who strive for excellence not only in the “software” part but in the “GUI” part too.

If you enjoyed this article, you might be interested in following me on Twitter, enquiring about my iPad (and iPhone and Mac) development services, or listening to my thoughts on software design on The MDN Show podcast. I’ll also quite shamelessly link you to my Amazon wishlist.

by Matt Legend Gemmell at March 09, 2010 12:00 PM

Cocoa Kid's Net

Recipe #3: Adding your app to Login Items using LSSharedFileList

I’ve been developing an utility app. I’m really excited about this and I do hope to release it quite soon (still have some issues with choctop and sparkle stuff). I even got an icon for it (thanks, Scarlet Bits!). In this blog post I’d like to share about a solution to a problem that I faced while developing my app – launching it at the beginning of user’s session, i.e. on login.

Since Mac OS X Leopard (10.5) apple has dedicated API for these kind of things. And by writing “kind of” I’m going to quote the Apple developer documentation itself:

The Shared File List API is new to Launch Services in Mac OS X Leopard. This API provides access to several kinds of system-global and per-user persistent lists of file system objects, such as recent documents and applications, favorites, and login items. For details, see the new interface file LSSharedFileList.h.

Read on if you’d like to know how to add your app to login items list.

Getting login items list

First off – we’ll fetch login items to see if our app is already in that list. Well, at first it won’t be there, but it will pay off in the future, trust me. So here’s the code snippet for fetching existing login items and assigning them to an NSArray:

// Some seed data
UInt32 seedValue;
 
// Let's create reference to shared file list
LSSharedFileListRef loginItems = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL);
 
// Then just pop values from referenced list into array
NSArray  *loginItemsArray = (NSArray *)LSSharedFileListCopySnapshot(loginItems, &seedValue);

You can now use this array as any table’s data source to see what this list contains. If you’re too lazy, then I can tell you that each item has “assigned display name, icon, and url as well as other optional properties” (quote from source code).

Now that we’ve got the list of login items – it’s really easy to add/remove our app to/from the list of login items. But for starters – we’re going to check for item’s presence in the list.

Checking for item’s existence

Since it is my first experience with login items and LSSharedFileList, from what I found on the net, I believe that main criteria is to check item’s url against given one. This code snippet shows how it should be done:

- (BOOL)loginItemExistsWithLoginItemReference:(LSSharedFileListRef)theLoginItemsRefs ForPath:(CFURLRef)thePath {
  BOOL exists = NO;  
  UInt32 seedValue;
 
  // We're going to grab the contents of the shared file list (LSSharedFileListItemRef objects)
  // and pop it in an array so we can iterate through it to find our item.
  NSArray  *loginItemsArray = (NSArray *)LSSharedFileListCopySnapshot(theLoginItemsRefs, &seedValue);  
  for (id item in loginItemsArray) {    
    LSSharedFileListItemRef itemRef = (LSSharedFileListItemRef)item;
    if (LSSharedFileListItemResolve(itemRef, 0, (CFURLRef*) &thePath, NULL) == noErr) {
      if ([[(NSURL *)thePath path] hasPrefix:@"/Applications/MyApp.app"])
        exists = YES;
  }
  return exists;
};

Adding an item to login items list

Method for adding an item to login items list is LSSharedFileListInsertItemURL. – method for inserting. This method accepts 7 parameters, but only 3 of them will be of interest to us. These are the accepted parameters:

  1. Reference to login item list (created in the code above. Do not mix up with array of items)
  2. Position of where to insert new login item. To insert item to the beginning of the list use kLSSharedFileListItemBeforeFirst. To insert item to the ending of the list use kLSSharedFileListItemLast. Otherwise pass LSSharedFileListItemRef.
  3. Display name of new login item. Can be NULL. Defaults to app name.
  4. Icon of the login item. Can be NULL. Defaults to app icon.
  5. CFURLRef of item to insert. This usually is a path to your app (like /Applications/MyApp.app)
  6. CFDictionary – dictionary of options for new login item.
  7. CFDictionary – dictionary of options to clear if item already exists in the list.

The ones interesting for us are 1, 2 and 5. So the code for adding an item to login items list could be as follows:

// Reference to shared file list
LSSharedFileListRef theLoginItemsRefs = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL);
 
// CFURLRef to the insertable item.
CFURLRef url = (CFURLRef)[NSURL fileURLWithPath:@"/Applications/MyApp.app"];
 
// Actual insertion of an item.
LSSharedFileListItemRef item = LSSharedFileListInsertItemURL(theLoginItemsRefs, kLSSharedFileListItemLast, NULL, NULL, thePath, NULL, NULL);
 
// Clean up in case of success
if (item) 
  CFRelease(item);

Removing an item from login items list

Method for removal of item in question is LSSharedFileListItemRemove. This method contrary to the one for adding the item to login items list accepts only two parameters:

  1. The reference to login items list
  2. The item reference in question

It could not get simpler than this:

LSSharedFileListItemRemove(theLoginItemsRefs, itemRef);

Conclusion

This is the first part of managing login items in Mac OS X. In next part I’ll show you how to keep track of changes while your app is not running and adding/removing your app to/from login items isn’t handled by your app.

Please note that I found code samples in one place on the internet but was too lazy to bookmark it, hence this code was extracted from the app. If you recognize your stuff – please post a note/link in the comments. Thanks a heap for reading this!

by eimantas at March 09, 2010 08:26 AM

March 08, 2010

waffle

Mac Guys Are Not Going To Just Walk In

Download Squad fails in the most hilarious way possible.

Can Apple really see themselves competing, with a minuscule desktop market share and 25% of the smartphone sector?

Desktop gaming? We’ll see. Obviously, Valve thinks that the Mac market is worth going after and they seem to know a thing or two about moving games. I’m glad that games have been returning to the Mac again for a few years.

Mobile gaming? The iPhone grosses the most games on any phone ever, including some that are by far the best mobile phone games ever. Nokia’s N-”Sidetalking”-Gage is the closest historical competitor and the only credible gaming phone predecessor and even it didn’t ever attract this level of attention, talent or quality. Windows Mobile has had forever to gain a stronghold, and while I have actually enjoyed playing Jawbreaker on a Windows Mobile device on occasion, I don’t see how this argument that you’re trying to make plays out. Regardless of their percentage of the smartphone or overall sector, I don’t see any other phone that competes with the iPhone with regards to gaming.

Steve Jobs has announced Apple’s intent to move into mobile gaming, but can you really see developers siding with the iPhone when Windows Phone 7 is just around the corner? The iPhone has an installed base of about 9 million users in the USA — would you like to guess at the combined figures of Windows and Xbox?

Wow. Do you even know yourself what you’re measuring? Did you switch the comparison halfway through when you realized that even Windows Mobile Classic is now behind iPhone OS in market share; slightly if you consider iPhone only, but by a mile if you also count iPod touch?

I won’t discount the possibility of Xbox and Windows making a difference. But the original Xbox hit the market eight years ago. If Microsoft wanted to parlay this onto the mobile games market, they’ve had five and a half years from the US launch of the Xbox to do so undisturbed, and yet another 18 months before the iPhone third-party apps market opened up. “Microsoft will crush Apple because Microsoft is huge” isn’t a convincing argument in the face of Microsoft having had that opportunity for the past decade, and in the face of Apple actually being huge in the market you’re flailing your arms around about.

Let’s wind down with a bit more level-headed analysis from Mr. Thurrott, in the light of today’s Steam announcement:

[quoting a Steam press release] “Steamworks for the Mac supports all of the Steamworks APIs, and we have added a new feature, called Steam Play, which allows customers who purchase the product for the Mac or Windows to play on the other platform free of charge. For example, Steam Play, in combination with the Steam Cloud, allows a gamer playing on their work PC to go home and pick up playing the same game at the same point on their home Mac. We expect most developers and publishers to take advantage of Steam Play.”

Pfft. See my previous comments about Microsoft trying this as well.

Here, Paul links to some earlier sane analysis. There’s only one problem: Paul correctly took Microsoft to task for attempting this across their own platforms — Windows, Windows Phone 7 and Xbox 360. Valve’s approach involves two gaming computers; Microsoft’s approach involves several different tier devices. I may agree that a good gaming PC and an Xbox 360 could perform on par, but if you’re going to play on a Windows Phone 7 phone, that game is going to have to be svelte enough to run well on a 1 GHz ARM processor, which means that the game will be restricted to the smarts of a smartphone-level device on Windows and on Xbox 360 if it really is going to be the same exact game. You will also have bought that lowest-common-denominator for multiple platforms. Right.

If this is directly comparable to just switching between two different gaming computers and getting a free download of the game for the other computer, I’d like to see how.

by Jesper at March 08, 2010 11:41 PM

March 06, 2010

Clickable Bliss

iTunes U iPhone Classes

This is probably old news for most people but I personally started watching the latest videos and wanted to share.

On the iTunes Store there is a section called iTunes U. Inside you’ll find lots of channels hosting free educational content. One of the more popular channels since iTunes U was introduced has been the Stanford iPhone course.

This course has been ran for a few semesters now. It assumes basic knowledge of OOP. The first few classes get you up to speed with the Objective-C language and the rest jump right into the iPhone SDK. It’s a very well done course and if you are looking to get started a terrific resource to check out.

Huge note here: they seem to remove the files once the class is done. So if you are interested be sure to stay subscribed and download all the files before the class is over. The public class website talks of final projects being reviews on Thurs 3/18, so if you are interested in this class get those downloads started before they disappear.

by Mike Zornek at March 06, 2010 11:55 PM

March 05, 2010

NSBlog

Friday Q&A 2010-03-05: Compound Futures

Welcome back to another thrilling edition of Friday Q&A. This week I want to extend my discussion from last week about futures, and talk about compound futures, an extension to the basic futures system that I developed previously.
(Read More)

March 05, 2010 01:53 PM

Matt Legend Gemmell

iPad Application Design

I held a 6-hour workshop at NSConference in both the UK and USA recently, focusing on software design and user experience. Predictably, an extremely popular topic was the iPad, and how to approach the design of iPad applications. I gave a 90-minute presentation on the subject to start each workshop, and I want to share some of my observations here.

Please note: this is about the user interface conventions and considerations which apply to creating software for the iPad platform (and touch-screen tablet devices in general). It is not a technical discussion of iPad-related APIs (which remain under NDA at time of writing in early March 2010).

As I watched the iPad introduction keynote, there was one thing above all which struck me:

iWork for iPad

That’s iWork (Keynote, Pages and Numbers) for iPad. It’s also a message.

It’s not just a big iPhone

The iPad may be a larger version of the iPhone in terms of the hardware and operating system, but treating it as the same device would be foolish. It turns out that increasing the display size of touch-screen hardware can transform it into an entirely new class of device. The iPad is a productivity platform in a way that the iPhone rightly never tried to be. (And it’s officially OK to charge $9.99 per app.)

When Steve Jobs introduced the iPad, he did so in a very specific way:

iPhone, iPad and Mac. iPad in the middle.

The iPad is in the middle, between the iPhone and the Mac. This isn’t just an acknowledgement of relative display size or processing power, it’s also a strong indication of the market position of the device and its software.

The iPad is a target for apps from the desktop, not just from smartphones. There are some very interesting opportunities here.

The Missing Link

We already have iPhone apps on the iPad (they can run at their native size in the middle of the screen, or be scaled up to fit). That’s useful, but it’s not particularly interesting. Far more relevantly, we can bring desktop-class applications to iPad – but we need to rethink our user interface and design in general. What works on iPhone won’t automatically work on iPad.

The essence of the new opportunities on iPad is that this class of device is a natural home not just for the viewers and small utilities we’ve seen on our phones, but also for creators and editors as we see on desktop platforms. Productivity applications, and sophisticated workflows. There are entire genres of applications which haven’t been truly feasible on an iPhone OS device until now; this is an opportunity to literally pioneer a high-profile touch-screen version of those applications.

In order to work out how to do that effectively, we need to talk about what exactly is different about the iPad compared to the touch-screen smartphone platforms. It all comes down to input and output.

  • The display is much larger; 1024×768 pixels. Apps with more demanding presentation requirements will be at home here.
  • The virtual keyboard is larger, and external physical keyboards are supported via Bluetooth or the dock. Apps which focus on typing are now much more feasible.
  • The iPhone supports multi-touch, but only the iPad can credibly claim to support two hands. We’ll talk more about this later.

These facts lead to a shift in how we can think about what applications and interfaces can exist on the iPad. We just need a set of guidelines to follow.

The iPad introduces and lends itself to some new UI conventions. I’ve compiled a list of thoughts that I’m going to discuss below. Some of these are simply from looking at the built-in apps on the iPad, and some are subjective impressions.

Master-Detail

This isn’t new, but it’s new to the iPhone OS platform. Master-Detail is an interface concept whereby you can see both a list of things, and also additional information about the currently-selected thing in the list. On iPhone, either the Master or the Detail was visible, but not both – there wasn’t room. On iPad, we can again have Master-Detail, as exemplified by Mail:

Mail for iPad

This gives us an easy set of conventions:

  • Master-Detail is feasible and acceptable on iPad.
  • In landscape, both Master and Detail are visible.
  • In portrait, the Master is shown in a transient pop-over.

Two-pane and three-pane interfaces are once again worthy of consideration on this class of device.

Look like a Viewer

The primary warning about designing for the iPad is: more screen space doesn’t mean more UI. You’ll be tempted to violate that principle, and you need to resist the temptation. It’s OK to have UI available to cover your app’s functionality, but a bigger screen doesn’t mean it should all be visible at once.

  • Hide configuration UI until needed.
  • Look like a viewer, and behave like an editor.

Pages looks like a beautiful reading app:

Pages for iPad; document viewing with loupe.

until you interact with something to display relevant editing UI:

Pages for iPad, displaying editing UI

This leads us naturally to the next point.

Edit in place

On the Mac and other desktop platforms, there’s a convention where we have globally-positioned editing UI. Common examples include floating inspector palettes, toolbars, menus, and status-bars. That won’t fly on the iPad, because it introduces a level of indirection between the editing action and the object being edited. It’s a touch-screen device; we should interact and edit directly.

  • Edit object properties in place.
  • Attach the editing UI to the object. Show/hide/move as necessary.

For example, when you edit transition/build animations in Keynote, you do so on the actual object to be animated:

Keynote for iPad, showing an animations editing UI attached to a bar-chart.

Upon adding an animation, the list of available types is similarly attached to the relevant object:

Keynote for iPad, showing an animations list attached to a bar-chart.

The same goes for slides as a whole:

Keynote for iPad, showing an animations list attached to a slide.

It’s a good principle to follow; it’s direct and immediate, and it’s intuitive for a device where it feels like you’re interacting with the actual objects using your fingers.

Inspectors should be Contextual

There can, however, sometimes be value in keeping standard editing interfaces in standard positions; the key consideration is how much UI to show. On the desktop, this is something we often get wrong. Here are two familiar examples:

Inspector palettes for Keynote and Microsoft Word on the Mac, each showing many controls.

These inspectors (for Keynote and Microsoft Word on the Mac) are difficult to use because they show all possible editing controls at once, disabling those which don’t apply to whatever is selected. It’s not easy to find which options apply to what you’re editing at the time, and the density of controls requires the pixel-precision of a mouse pointer and considerable screen space to display.

On the iPad, any globally-positioned inspectors should nonetheless be contextual in terms of what editing UI they show. Don’t overload the user with irrelevant options; hide anything that doesn’t apply. If you’re editing text, show only text editing controls:

Pages for iPad, showing an inspector with text-specific controls.

If you’re editing a chart, show only options relevant to charts:

Pages for iPad, showing an inspector with chart-specific controls.

The guideline is simple, and it’s good advice even for the desktop:

  • Inspectors should present context-relevant UI.
  • Hide controls which don’t apply to the selection or focus.

The concept of context is key to iPad software design. In human-computer interaction, we often discuss this under the title of modes.

Use Modes to simplify UI

Modes, or modal interfaces, are where the user deals just with one particular area of a piece of software at a time. They see only the relevant controls and information for one particular task or type of work; an example would be iPhoto’s photo-editing interface, or the Ribbon in the recent versions of the Microsoft Office applications.

There’s been a history of modes getting some bad press on the desktop. The issue is that they trade stability (things always being in exactly the same place in the UI, and not changing) for simplicity (not having too many controls to look through at once). On the iPad, it’s clear where the winning side of the balance is: simplicity. Modes are completely appropriate on this device.

The challenge is in keeping our UI clear and uncluttered. Not only that, but our UI has to be actually usable with a finger – an incredibly imprecise, enormous, screen-hiding input device – rather than a pixel-perfect mouse pointer. Modes can help us keep plenty of space around. Move UI elements into modes, and/or position them contextually and temporarily – but just don’t go overboard with the number of modes.

  • Modes are preferable to clutter.
  • But removing a feature might be preferable to adding a mode for it.

The modal organisation of features is better than an all-at-once approach, but don’t let it become an excuse for feature creep. One of the primary rules of iPad app design must surely be that less is more.

Fewer Features

Feature-creep or bloat is the bane of desktop software. Any application with a non-trivial feature set isn’t fully used by most of its users; that’s pretty obvious to anyone who has ever used Microsoft Office or Adobe Photoshop or even the iWork apps on the Mac. There are plenty of features there which you’ll never touch, and would probably never miss if they were gone.

Most users need only a small set of features, and software is better when it’s focused. A nice side-effect of focused software is that the UI is easier to design and comprehend (because there’s less of it, and it’s more obvious why each thing is there). The trick is to figure out which small set of features are actually important, and implement only those.

  • Offer only the most-used/needed features. If in any doubt, remove a feature.
  • Discard optional/niche or highly configurable functionality.

This is another rule which is equally true for the desktop. The difference is that people have been trained to accept fuzzy-edged applications on their computers, whereas they probably won’t do so on the iPad. Be focused, targeted and comprehensible. You can add things later when it becomes clear what’s important, but you’ll never recover from a confusing first impression.

Two Hands

Many people are excited about the fact the iPad is large enough to support two whole hands providing input simultaneously. The hardware support is no different from the iPhone, but the available space certainly is. Suddenly we have visions of really usable card games and air hockey and so forth; it’s hard to underestimate the importance of this factor.

The worrying thing is that I’ve heard people talking about providing twice the UI, with strips of buttons and controls down both sides of the screen, just because there’s enough room for that kind of thing now. Resist that temptation at all costs. The way to support dual-handed input on the iPad is in a discoverable and optional way. There are a couple of interesting examples in Keynote:

Phil Schiller using Keynote for iPad, showing two-handed input features.

During the iPad introduction keynote, Phil Schiller was using Keynote on the device, and demonstrated some subtle dual-hand input features. Whilst resizing a photo, you can tap another photo with your other hand and the one you’re resizing will match that other photo’s size. Similarly, whilst dragging a slide you can tap other slides with your other hand to add them to the group being dragged, thus moving them all at once.

The important point is that there are other, more obvious ways to accomplish these things; the two-handed input features are conveniences and power-user features. They’re useful and time-saving and possibly discoverable, but they’re not the only way to accomplish those tasks. We’re only just beginning to come to terms with the possibilities of dual-handed input; essential functionality shouldn’t require it yet.

  • Dual-handed input is acceptable.
  • Be usable with one hand. Don’t require two hands for essential features.
  • But don’t be afraid to offer time-saving, discoverable dual-handed functionality.

The fact that users can use their hands to interact is something to capitalise on; it’s a very important aspect of the attraction to this type of device. Understandably, it’s rooted in human psychology.

Use the Psychology of Touch

This is where it gets touchy-feely, and thus where we engineers are least comfortable. It’s also where we find the explanation as to why your grandmother wants an iPad but wouldn’t touch a Mac or PC. The twin key factors are touch, and the device’s unique form-factor.

Touch is emotionally important to humans; it conveys the identity and “realness” of an object. Direct touch bypasses abstraction and creates a strong connection with the touched object. This is particularly true when the object itself triggers associations in our minds. Due to its very size and weight and display area, the iPad triggers powerful associations with:

  • Printed documents
  • Notepads of paper
  • File-folders from the filing cabinet
  • Clipboards
  • Books

There is something intrinsically “right” about seeing the iPad as a technological successor to, or version of, these physical objects. We’re immediately ready to accept the one as a substitute or enhancement for the other. This is a powerful, and novel, position for the iPad software developer.

It wasn’t true with the iPhone or iPod Touch; the devices are too physically small. The “Notes” app on the iPhone will forever be a simulation of a legal pad; the similar app on the iPad is a legal pad (to your user). It’s an incredibly important distinction in terms of how it influences our design.

There’s a predilection towards “realness” on the iPad which overrides mere fashion and aesthetics as seen on the iPhone; it’s a core component of the attraction of the hardware. The standard apps on the iPad build directly on this by using virtual materials. The form-filling view in Numbers is a good example:

Numbers for iPad, showing the form-filling view: a simulated card file with paperclip and paper.

We’ve all clipped those card dividers into our binders, and seen them become dog-eared. We know how the slightly waxy laser-printer paper feels, and we’ve bent and reshaped that paperclip a thousand times. These are real things, presented virtually.

The iBooks app, showing wooden bookshelves and printed paper.

We’ve all been in the room with these varnished bookshelves, lit by afternoon sunlight. We’ve all bought a new novel, opened it and guiltily buried our nose in the pages just to enjoy the smell of books.

The Notes app, showing a yellow legal pad in a leather case.

We’ve all used this legal pad to sketch ideas. Perhaps we’ve even seen it on the telephone table in the study or hallway, slid into its leather slip-case with an index sheet (all those things are visible in the interface above if you look for them).

The Calendar app, showing wood-backed hard-bound day planner.

We’ve all seen this quality day-planner and wished we had the discipline to use it, because it’s a beautiful analogue thing in an increasingly digital world. We’ve paid ridiculous prices for Moleskines and diaries and fountain pens.

The Contacts app, showing a hard-bound address book with a fabric bookmark.

We’ve all seen this address book sitting on a desk, hard-bound and meticulously re-indexed, with a red fabric bookmark sitting loosely over the cover.

Did you feel an emotional connection to any of these images and statements? Your users will feel those connections too, even if they can’t articulate them. You can, and should, directly capitalise on these feelings and connotations.

Even if you can’t find a way to make your interface be a real thing, you can often make it into a surface for real things. It’s one additional level of abstraction, but it’ll still work.

The Photos app, showing stacks of photos and a light-box view of a single image.

This is the table you empty the photos drawer onto when you want to find a particular image from childhood; the stacks are all that’s left of the long-discarded paper wallets the photos originally arrived in. The full-screen display is a photographer’s light-box. The device becomes physical surfaces we know in the real world.

The iPod app, showing CD album covers laid out in a grid.

Even resolutely abstract concepts like playlists of music can be represented as surfaces of CD albums. There’s often a way to pull your software interface a little closer to a familiar object from the real world, and increase engagement with the user.

  • Make your application a real object if at all possible.
  • Alternatively, make it a surface for real objects.

Our graphic design budget must surely increase, but I think you’ll find the pay-off is more than worth it.

Key Questions

In summary, when approaching iPad app design, do so in a way that acknowledges the strengths and unique advantages of the device and platform. Ask yourself these questions:

  • What are the core features? How can I remove some of them?
  • How can I make this work on a touchscreen device?
  • How do I create an emotional connection?
  • How can I make my app uniquely suited to iPad?

Don’t ship before testing on an actual device, and remember that first impressions last – take the time to get it right. Don’t assume that what works on iPhone will be equally suited to iPad, and certainly don’t generalise from desktop software.

There’s a unique and exciting opportunity here, and just possibly the beginning of the next major stage in software design and user experience. You’re getting in on the ground floor, and there’s every reason to be optimistic. Good luck.

If you enjoyed this article, you might be interested in following me on Twitter, enquiring about my iPad (and iPhone and Mac) development services, or listening to my thoughts on software design on The MDN Show podcast. I’ll also quite shamelessly link you to my Amazon wishlist.

by Matt Legend Gemmell at March 05, 2010 12:04 PM

Safe from the Losing Fight

Redesigning a Software Contractor’s Website

It’s been about eight years since our company website has had a major redesign. But that changed today.

The old design simply wasn’t meeting our needs. Specifically:

  • It didn’t communicate clearly what exactly we do here.
  • It had a search box which, as far as I can tell, didn’t, and has never, worked.
  • It had several pages describing services we don’t perform, at least not when a cop is around. Some of these pages just had boilerplate text in them. e.g. “Item 1″, “Item 2″, etc
  • The visual design was really old and unprofessional. The new is at least not old.
  • The old feedback form demanded a lot of extraneous information like title, company, telephone number, home address, when you shower, etc.
  • It had a copyright date at the bottom of 2002, which caused people to ask: “Are you guys still in business?” This was apparently a barrier to them sending us money.

Fortunately, we mainly rely on word of mouth to get clients, but a bad website certainly doesn’t help our business. We could be missing out on clients who find our website, but don’t contact us for any of the reasons listed above.

I’ve recently had some time between contracts, which I used to think about how a software contractor’s website should be structured and what kind of information it should present. Also, I slept in late a lot. I came to some conclusions:

  • It should immediately obvious to a visitor what the company does, no matter what page they land on.
  • It should have a portfolio so the visitor can see what kind of work we have done in the past, and see if that matches up with what they want done at the quality level they want.
  • A brief description of services that we do provide, explained in layman’s terms.
  • It should be obvious and easy to get in touch with us. The form for submitting a message should have as few requirements as possible.
  • It should contain a brief overview of the company, and the people in it. It should put a human face to the company.
  • Noon really is not a bad time to wake up.

I also decided to add a page for products, mainly for future use.

Overall the project was a fun — and hopefully financially rewarding — exercise. It was interesting to think about what would induce a visitor to stick around on our site, and then actually contact us. I’m not sure if I got it completely right, but it’s at least a step in the right direction.

by andy at March 05, 2010 07:50 AM

March 04, 2010

waffle

Warren

Long ago, Charlie laid out his strongest ambition: “All I want to know is where I’m going to die, so I’ll never go there.” That bit of wisdom was inspired by Jacobi, the great Prussian mathematician, who counseled “Invert, always invert” as an aid to solving difficult problems. (I can report as well that this inversion approach works on a less lofty level: Sing a country song in reverse, and you will quickly recover your car, house and wife.)

Berkshire Hathaway’s annual letter, penned by Warren Buffet, is a better read than most anything; brutally honest, interesting enough even if you don’t follow them or finance at all, and actually funny. This year’s entry is no exception. One more piece:

And now a painful confession: Last year your chairman closed the book on a very expensive business fiasco entirely of his own making.

For many years I had struggled to think of side products that we could offer our millions of loyal GEICO customers. Unfortunately, I finally succeeded, coming up with a brilliant insight that we should market our own credit card. I reasoned that GEICO policyholders were likely to be good credit risks and, assuming we offered an attractive card, would likely favor us with their business. We got business all right – but of the wrong type.

Our pre-tax losses from credit-card operations came to about $6.3 million before I finally woke up. We then sold our $98 million portfolio of troubled receivables for 55¢ on the dollar, losing an additional $44 million.

GEICO’s managers, it should be emphasized, were never enthusiastic about my idea. They warned me that instead of getting the cream of GEICO’s customers we would get the – – – – – well, let’s call it the non-cream. I subtly indicated that I was older and wiser.

I was just older.

by Jesper at March 04, 2010 11:49 PM

Uli's Web Site

Uli's source code is on Github!

So, if any of you are thinking of using my source code, I recommend you head over to my Github page:

github.com/uliwitness

Where I will be putting up the newest copies of all my neat open source classes. And to celebrate, I am making them available under a very permissive zlib-style license, which means you can freely use them.

I am planning to make more code available there, and hopefully also documentation and example projects, which are currently missing.

You can also find my Sparkle branch there, which includes lots of neat bugfixes, plus a few other things I wanted to make available.

March 04, 2010 11:00 PM

March 03, 2010

waffle

For Shame

I am not particularly proud of Apple right now.

I will switch, immediately, to any mobile phone produced by a company that announces and follows this policy:

  • They make a searchable catalogue of all their own patents, including information on where they believe the patented concepts are pertinent.
  • They declare the techniques in the patents free for the taking, royalty free, in exchange for a line in the product acknowledgements.
  • They declare the previous agreement void as soon as any legal action regarding alleged patent infringement is brought against the company.
  • They truly only use the patents to protect themselves against other patent suits.

I was under the impression that Apple was more interested in continuing to think up new interfaces, new approaches and new implementations that might better serve us in the age of multi-touch and ubiquitous high-speed Internet access. That the value in Apple’s products is a cohesive and speedy experience that is easy to navigate, learn and use, and not the various isolated nuts and bolts or building blocks that mindlessly ported in isolation mean nothing but carefully assembled in aggregate mean everything. That the best way for Apple to counter, say, Chinese iPhone ripoffs was to move full speed ahead.

You’re established in a country with really fucked up patent laws, and I can understand that. You get hounded by a company that abuses those laws, and I can sympathize with defending yourself, even with unsavory attitude. But what I can’t forgive is using these same laws as a completely unwarranted bludgeon against someone who isn’t the worst offender while you sit on a 40 billion dollar war chest.

You can’t write your own laws, but being an asshole by abusing them is clearly your choice. I guess I wish you’d have thought differently.

by Jesper at March 03, 2010 11:43 PM

Stuart Connolly

SafariTabs 0.7.2

SafariTabs 0.7.2 is now available for download. As usual this is a pretty minor release that resolves the following issues:

  • New window links not working when the 'Force new window links to open in a new tab' option is disabled.
  • Not saving the current session's open tabs when private browsing is enabled.

The first issue was introduced in the previous release while the second has been around for a couple of versions, which has now finally been resolved. Enjoy.

Update: I've just realised that this version was released exactly 3 years to the day since the first public release (version 0.1). Can't believe it's been 3 years already.

by Stuart Connolly at March 03, 2010 09:27 PM

waffle

Hazing

Valve knows marketing. When was the last time you saw someone enter a new platform with that sort of cultural connection?

by Jesper at March 03, 2010 09:19 PM

Clickable Bliss

On Apple suing HTC

Apple, like many corporations in the US, files for patents, including many software patents. I’ve never faulted them for filing the patents. In the US. when one big corporation sues another big corporation claiming they are infringing on one of their patents, it’s typical to fire back with similar claims and eventually work out a settlement.

I think most corporations view patents as missiles. They line them up, outside the perimeter of the company for all to see and through a blow horn they yell, “Do not fuck with us or we will use these to level your house.”

Despite what the typical layman thinks, this is the real world of the US patent system. (Sad I know.)

So Apple lives in this world. They have their stockpile of missiles but have never been aggressive with them. They have only used them as a response to an attack, until yesterday.

Yesterday, Apple filed suit against HTC for a collection of patents, most related to the iPhone and touch gestures.

In my opinion, this is pretty craptastic. In an open letter Wil Shipley shares similar thoughts:

Enforcing patents is wrong. You’ve famously taken and built on ideas from your competitors, as have I, as we should, as great artists do. Why is what HTC has done worse? Whether an idea was patented doesn’t change the morality of copying it, it only changes the ability to sue.

But when you sue someone for doing something you do yourself, you become one of the bad guys.

I remember back when Steve introduced the iPhone during Macworld 2007. Even on day one he talked about patents and lawsuits:

“We’ve been innovating like crazy for the last few years on this [iPhone] and we have filed for over 200 patents for all the inventions in iPhone [pause] and we intent to protect them. (Keynote speech, 1:30)

Cue audience applause and a huge sick feeling in my stomach (even back then).

A NY Times article posted today addresses the question as to “why did Apple sue HTC and not Google?” They write:

Jonathan Zittrain (professor at Harvard Law School) believes Apple is simply going after a less powerful company first, one with much smaller pockets than Google.

“It clearly involves some form of litigation strategy of picking off the weaker members of the herd first,” Mr Zittrain said. “They can always add Google to the suit later on.”

To say I’m disappointed and troubled by Apple’s actions is an understatement. At heart I think there are two ways to deal with competition.

One, you embrace your competitors. You learn from their mistakes as they learn from yours. You strive to do better, which makes them strive to do better and the improvements become cyclical. In the end, the consumer has a better product because of the process.

Two, you do everything in your power to make sure the consumer has no other choice than to buy your product or service.

With Apple’s original posturing about iPhone patents and now the first aggressive action with them I fear Apple is changing the way is deals with competition.

Related: John Gruber, This Apple-HTC Patent Thing

by Mike Zornek at March 03, 2010 06:16 PM

Cocoa With Love

Load from NIB or construct views in code: which is faster?

You don't have to look far to find people suggesting that constructing views in code will increase the speed of your program. Since interface performance is a serious concern in iPhone development, I thought I'd look at the performance speed in creating complex iPhone UITableViewCells in code versus loading them from a NIB file.

Introduction

The sample program this time is pretty simple: an iPhone application that can load a table containing 20 rows (sized so that they will all fit onscreen), each row containing 20 fully-configured UILabels, a backgroundView and a selectedBackgroundView.

All timing is done on the construct/load only. Adding cells to the table, configuring the cell for its row and drawing to the screen (all of which is identical in either load from NIB or construct in code cases) is not included as part of the timing results.

nibornot.png

The dark line across the right-hand side of each cell is just the word "placeholder" written 19 times on top of itself by the labels added to the cell.

You can download the sample project: NibOrNot.zip

Creating the cell in code

The construction of the cell in code looks like this:

cell = [[[UITableViewCell alloc]
	initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
cell.backgroundView = [[[UIView alloc] initWithFrame:CGRectZero] autorelease];
cell.backgroundView.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.0];

cell.selectedBackgroundView = [[[UIView alloc] initWithFrame:CGRectZero] autorelease];
cell.selectedBackgroundView.backgroundColor = [UIColor colorWithWhite:0.85 alpha:1.0];

UILabel *firstLabel =
	[[[UILabel alloc] initWithFrame:CGRectMake(5, 0, 60, 20)] autorelease];
firstLabel.tag = 1;
firstLabel.font = [UIFont boldSystemFontOfSize:14];
firstLabel.shadowOffset = CGSizeMake(1,1);
firstLabel.textColor = [UIColor colorWithRed:0.0 green:0.2 blue:0.5 alpha:1.0];
firstLabel.backgroundColor = [UIColor clearColor];
firstLabel.text = @"placeholder";
firstLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
firstLabel.adjustsFontSizeToFitWidth = YES;
firstLabel.minimumFontSize = 10;
firstLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters;
firstLabel.lineBreakMode = UILineBreakModeTailTruncation;
firstLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters;
firstLabel.highlightedTextColor = [UIColor clearColor];

[cell addSubview:firstLabel];

//
// Plus the construction of a further 19 labels...
//

In this case, the next 19 labels could all be created in a loop (since they're all identical) but I wanted to code to reflect a proper view where each subview is distinct and has many properties uniquely applied — so a basic loop is not necessarily appropriate.

Loading the NIB

There are many different ways to load a UITableViewCell (loading just the contentView, constructing a UITableViewCell subclass and having it load the NIB, etc). I've gone for the quick and easy approach: loading the UITableViewCell from the NIB in its entirety, passing my UITableViewController as the owner.

[[NSBundle mainBundle] loadNibNamed:@"Cell" owner:self options:nil];
cell = loadedCell;
loadedCell = nil;

It may be hard to see how the loadNibNamed:owner:options: method is connected to the other two lines. In this code, loadedCell is an IBOutlet on self. When the NIB is loaded, it sets the loadedCell value to be equal to the loaded cell (this is configured in the NIB file). After loading, I copy the loadedCell into a local variable named cell (which is later configured and returned) and set the instance variable on the class back to nil (because we no longer need this pointer after returning it).

Simulator results

The first 10 results from the simulator look like this:

Generated in codeLoaded from NIB
Generated cell in 0.00153798 secondsLoaded cell in 0.00184 seconds
Generated cell in 0.00138998 secondsLoaded cell in 0.00168097 seconds
Generated cell in 0.00138199 secondsLoaded cell in 0.00168198 seconds
Generated cell in 0.00139898 secondsLoaded cell in 0.001706 seconds
Generated cell in 0.00167602 secondsLoaded cell in 0.001697 seconds
Generated cell in 0.00235301 secondsLoaded cell in 0.00171804 seconds
Generated cell in 0.00137097 secondsLoaded cell in 0.002105 seconds
Generated cell in 0.00138301 secondsLoaded cell in 0.00173801 seconds
Generated cell in 0.00140399 secondsLoaded cell in 0.00171405 seconds
Generated cell in 0.00137198 secondsLoaded cell in 0.001692 seconds

Constructing in code is generally about 20% faster — although at 1 millisecond per construction in the simulator, it doesn't really matter.

Device results

The first 10 results running on my iPhone 3G look like this:

Generated in codeLoaded from NIB
Generated cell in 0.113011 secondsLoaded cell in 0.131085 seconds
Generated cell in 0.114312 secondsLoaded cell in 0.097244 seconds
Generated cell in 0.101614 secondsLoaded cell in 0.08413 seconds
Generated cell in 0.105022 secondsLoaded cell in 0.081331 seconds
Generated cell in 0.10087 secondsLoaded cell in 0.093407 seconds
Generated cell in 0.105968 secondsLoaded cell in 0.083472 seconds
Generated cell in 0.100045 secondsLoaded cell in 0.091788 seconds
Generated cell in 0.105458 secondsLoaded cell in 0.083763 seconds
Generated cell in 0.098836 secondsLoaded cell in 0.08714 seconds
Generated cell in 0.102028 secondsLoaded cell in 0.109811 seconds

The construction in code is about 15% faster on the first construction but by the third cell, loading from the NIB file is 17% faster.

Running some CPU sampling in Instruments, I was able to work out that adjustsFontSizeToFitWidth was the critical factor here: it appears that Interface Builder precalculates the correct size based on the placeholder string, whereas the constructed code is forced to do this at runtime, causing its performance to suffer.

Turning off adjustsFontSizeToFitWidth in both the generated code and the loaded code (replaced the label.adjustsFontSizeToFitWidth = YES with label.adjustsFontSizeToFitWidth = NO and switched Cell.xib to Cell2.xib), gave the following results:

Generated in codeLoaded from NIB
Generated cell in 0.085553 secondsLoaded cell in 0.095012 seconds
Generated cell in 0.077257 secondsLoaded cell in 0.087141 seconds
Generated cell in 0.084639 secondsLoaded cell in 0.082693 seconds
Generated cell in 0.079142 secondsLoaded cell in 0.098218 seconds
Generated cell in 0.078286 secondsLoaded cell in 0.082136 seconds
Generated cell in 0.087895 secondsLoaded cell in 0.087088 seconds
Generated cell in 0.0792 secondsLoaded cell in 0.082335 seconds
Generated cell in 0.084037 secondsLoaded cell in 0.082358 seconds
Generated cell in 0.076416 secondsLoaded cell in 0.08714 seconds
Generated cell in 0.078426 secondsLoaded cell in 0.084312 seconds

This now swings the performance advantage back to handwritten code by 7%.

Conclusion

You can download the sample project: NibOrNot.zip

Don't assume that NIB files are always slower than generating views in code — it is not always true. While in general, generating user interface views in code appears to be 5-10% faster than loading from a NIB, the reality is that this difference is small enough that it doesn't matter and there are certainly some views that load faster from a NIB than from code.

This doesn't mean that construction speed is unimportant on the iPhone; it clearly is. I was able to create a (slightly contrived) view that took nearly two seconds to load (unacceptably slow). However, saving 10% by moving from NIBs to creating views in code will never fix the problem (1.8 seconds is still too slow). In this case, flattening the view hierarchy (using a single custom view to draw what multiple subviews used to draw), or removing text fields entirely, is the best way to improve performance. This type of redesign can improve performance by a factor of 10 or more.

The conclusion to be drawn is that when choosing to use a NIB file or not, you should use whatever you're most comfortable with and whatever will keep your code maintenance costs low. Don't be concerned that one approach or the other will cause your UI performance to suffer.

by Matt Gallagher (noreply@blogger.com) at March 03, 2010 02:48 AM

March 02, 2010

ansemond.com

Ragdoll Blaster 2

Ragdoll Blaster 2 was released yesterday. It contains some of my code: a number of months ago, my friends at Backflip Studios asked me to optimize the game’s physics engine (ODE), providing free cycles for better graphics, sounds and levels. Of course the main question is … is it fun? I think so!


An amusing factoid: the game screens are rendered by OpenGL, but the rest of the UI is heavily customized Cocoa UI widgets. You can really make UITable look different!

by sengan at March 02, 2010 10:34 PM

Clickable Bliss

ProfitTrain Product Blog

With the release of ProfitTrain I wanted to do more blogging about the product. I also want to keep this blog focused on the trials and tribulations of running an indie software company. Thus a new product blog was born:

Ride the ProfitTrain.com

Ride the ProfitTrain is a product blog and will include tips, tricks, screencasts and anything else I suspect the users of ProfitTrain want to see. If you are interested, please check it out and subscribe.

by Mike Zornek at March 02, 2010 08:10 PM

ProfitTrain 2.0 Released

ProfitTrain

Yesterday I officially released ProfitTrain — the successor to Billable.

ProfitTrain is an application for Mac OS X that helps freelancers and small businesses keep track of what they are doing for clients and create invoices for services rendered. Additionally ProfitTrain will help you keep track of invoice payments as well as business expenses.

ProfitTrain (Download) requires 10.5 or greater. New licenses are $49.95 and Billable upgrades are $24.95. Please use the online store to purchase.

It’s going to be an exciting week. I want to thank all the people who have sent congratulatory tweets and blog posts. This type of word of mouth marketing really means a lot to small indie developers like myself. Thanks again!

by Mike Zornek at March 02, 2010 08:04 PM

March 01, 2010

Clickable Bliss

Lost emails from the store.

Update 5:57 PM (EST) Email should be working better now. But as always free free to contact me directly if you need help.

I’m not going to go into the technical side of it (for now) but I just wanted to quickly let people know that if they request a serial lookup or make a purchase using store.clickablebliss.com there is a fair chance the email receipt will not go through.

Other than the broken emails the store is working fine, feel free to buy our software. We would just ask that you take an extra minute to capture the web receipt in case the email copy does not make it to you.

If you do miss an email from the store and need help please contact me mike@clickablebliss.com and I will look up any serial or forward you any receipt you may need.

Why is email broken?

This has nothing to do with me accept for the unfortunate luck to be using an IP Address in the same range of another address that was flagged as spamming. My server provider Slicehost promises me they are working with the Spamhaus (the gatekeeper) to get the issue resolved asap.

by Mike Zornek at March 01, 2010 01:55 AM

February 28, 2010

Gus Mueller

U.S. Poisoned Alcohol During Prohibition

This is just crazy, and the first time I have ever heard of this: The Chemist's War, The little-told story of how the U.S. government poisoned alcohol during Prohibition with deadly consequences.

Here's a quote:

'The results were immediate, starting with that horrific holiday body count in the closing days of 1926. Public health officials responded with shock. "The government knows it is not stopping drinking by putting poison in alcohol," New York City medical examiner Charles Norris said at a hastily organized press conference. "[Y]et it continues its poisoning processes, heedless of the fact that people determined to drink are daily absorbing that poison. Knowing this to be true, the United States government must be charged with the moral responsibility for the deaths that poisoned liquor causes, although it cannot be held legally responsible."'

The whole read is good, and nuts. It's amazing what folks will allow to happen in the name of "upright behavior".

February 28, 2010 05:02 AM

Brent Simmons: On switching away from Core Data

Brent Simmons: On switching away from Core Data.

Brent talks about how he's switched away from Core Data in one of his apps, in favor of using SQLite dirctly (via my FMDB classes) instead. Manton Reece also explains why he doesn't use Core Data as well.

I've never used Core Data in a shipping product because I've been using SQL for ~15 years now and I'm very comfortable with it. And frankly I just don't like the "smell" of Core Data. I'm not sure how else to explain it, but it reminds me of things like EJB. Why doesn't Apple Mail use it? Why did Aperture 3 stop using it?

February 28, 2010 03:54 AM

Clickable Bliss

It’s beat up on Core Data week!

If you follow other Cocoa/indie blogs, you probably noticed some posts recently about people that are dropping or avoiding Core Data. I wasn’t planing on jumping in but guess what, ProfitTrain dropped Core Data too!

Brent has performance reasons, but my own reasons are more inline with Manton in that moving forward with my 2.0 I wanted to know more and be more responsible for that layer of the system.

Some backstory. When I started working on Billable I was targeting 10.4 which had just introduced Core Data. At the time I was building my first “real” Cocoa app and wanted to take advantage of anything that I could to make my life easier. Things like Core Data looked delicious.

Early development went well and after the 1.0 release I continued to expand and strengthen the foundation of my app. It was around this point where I started to feel like I was too dependent on black magic. I seemed to spend a lot of time trying to figure out what Core Data was doing and how it worked in order to get performance gains or integrate it with other technologies like AppleScript.

When I started work on ProfitTrain it was the perfect opportunity to re-evaluate all the code that had gone into Billable. Additionally, while there is no iPhone companion to ProfitTrain today, nor is there any formal syncing support; these are two major issues that I think many data-capture apps like ProfitTrain will face in the future. I feel like if I am ever to overcome these challenges I need to have a firm grasp and understanding of my persistence layer.

At the end of the day, I don’t think the benefits of Core Data outweigh the learning curve and the inevitable quirks, such as clunky migrations, you need to deal with. If Core Data brought more to the table like free AppleScript access and/or syncing tools I might have a change of heart. However for me, and the needs of my app as of today, I feel more empowered using SQLite directly through FMDB.

Update February 28, 2010 — Nice to see Core Data still has some love out there. Collin Donnell shares some reasons why he enjoys using Core Date for his iPhone apps.

by Mike Zornek at February 28, 2010 02:44 AM

February 27, 2010

Parmanoir

Core Image black fringes

That's a subtle one. When rotating a CIImage with [CIImage imageByApplyingTransform:t], you'll see incorrect blending between the image and its background. In this case, a black and grey image on a red background shows darker interpolated pixels than exist in both image and background.

Image:Core Image black fringes - CIAffineClamp and CICrop.png

Core Image is by default assuming a black border when blending the image. CIAffineClamp mentions black fringes when using a Gaussian Blur — when blurring, Core Image will blend border pixels with black. Adding CIAffineClamp will extend the image infinitely to blur border pixels with a copy of themselves.

Any filter that starts blending out-of-image pixels will benefit from CIAffineClamp — this will remove black borders in CICrystallize, CIPointillize, … and all the blur filters.

by Patrick Geiller at February 27, 2010 12:24 AM

February 26, 2010

NSBlog

Friday Q&A 2010-02-26: Futures

Welcome back to another shiny edition of Friday Q&A. Guy English suggested taking a look at implementing futures in Objective-C using blocks, and for this week's post I'm going to talk about the futures implementation that I built.
(Read More)

February 26, 2010 06:19 PM

Clickable Bliss

Mac Indie Marketing

I suspect it’s very easy for most indie Mac developers to be ‘heads-down coders’ who don’t think too much about marketing. The cruel reality however: building that great app is only the beginning. If you are going to grow a successful company you need to market yourself and your app. The following is a collection of some helpful resources.

One classic resource is Adam Engst’s Hacking the Press series. Adam has been giving variants of this talk since the MacHack days and a more recent dissertation was given (and captured) at C4.

At that same C4 we also got to watch Wil Shipley do a talk called Monster Marketing. In it Wil talks about hype, polish, buying google ads and more.

If you are looking for a more regular supply of marketing wisdom you must subscribe to Dan Wood’s Mac Indie Marketing blog. It’s been running for a few months now and it has a lot of great advice and interviews. I highly recommend subscribing and catching up.

And then there is your blog. You do have a blog don’t you? What?!?! You haven’t posted in months! What the hell man, get it together.

Seriously though, I think a big part of marketing you and your app is putting it all out there. Sharing your experiences; your wins and your loses. Be real. Be honest. Twitter is fine, but I think spending some extra time crafting your thoughts into meaningful blog posts, that will last for years to come, is worth your time.

by Mike Zornek at February 26, 2010 05:09 AM

Cocoa With Love

StreamToMe 2.0 is out (and Cocoa With Love is 2 years old).

Two different things turning two different kinds of "2". Snap.

Cocoa With Love is two years old today

I've been writing a feature article every week for two years now — haven't missed a single week yet (hope that doesn't jinx me).

To commemorate, I've put the complete list of downloadable code samples from my blog on the Projects With Love: Open Source Projects page.

StreamToMe 2.0 is out!

For those who don't know, StreamToMe is an iPhone application for streaming video and music from your Mac to your iPhone/iPod Touch. Plug your phone into your TV and you can use it to stream your Mac's music and video files to your TV. No prior conversion necessary — a huge range of codecs and formats (including AVI, WMV, MOV, MP4, FLV and more) will just play.

StreamToMe 2.0 adds:

  • Thumbnail previews for video files
  • Album artwork for music files (including while playing)
  • Artist and title metadata display
  • Subtitle rendering (including SRT and SSA files, MKV embedded SSA tracks and MOV text tracks)
  • Multiple audio tracks
  • Continuous and random play modes
  • Sort options including folder flattening (so you can view the full hierarchy of your iTunes collection as a single flat collection)
  • Preliminary support for EyeTV streams
  • Persistent playback — if you quit or are interrupted by a phone call during playback, you can continue from where you were.

And more!

StreamToMe is available to purchase from the iTunes App Store:

Download StreamToMe 2.0 from the AppStore now

Free upgrade for existing customers. Lucky them! Don't forget to update ServeToMe to enable some of the newer features.

Windows XP support for ServeToMe is coming soon (I'm hoping by the end of March).

Here's a few screenshots of the new version of StreamToMe in action:


by Matt Gallagher (noreply@blogger.com) at February 26, 2010 01:21 AM

February 25, 2010

waffle

Pixillated

Ed Catmull explains what makes Pixar work. Part of a recurring pattern: Less prestige, the right kind of structure, allowance to fail often and quickly so that you may move on, and high goals.

We shouldn’t be thinking that it’s okay to be doing something which isn’t great.

by Jesper at February 25, 2010 11:17 PM

Red Sweater Blog

Always Be Marketing

Dan Wood just posted an interview with me on the Mac Indie Marketing Blog. I love how interviews tease out thoughts that had never previously been fully gelled in my head.  Thanks for the thoughtful conversation, Dan.

Out of this experience came a new personal mantra: Always Be Marketing. This catch-phrase came to me as I tried to discover what it is that I actually do to market myself, my business, and my products. The answer fell somewhere between nothing specifically and everything specifically!

Another catch-phrase I bring up a lot when talking to other indie developers is Say Yes. This captures my belief that we developers are shy, scared, and would rather be programming than doing anything “out there in public.” So I often implore other developers to say yes to interviews, speaking engagements, etc., before your scared nerd-brain can take over and run screaming.

But Always Be Marketing sort of captures the same sentiment while driving the message home:

  • The local user group wants me to present, should I go?
    Always be marketing.
  • Another developer wants to co-market my product with theirs.
    Always be marketing.
  • What the … CNN wants me to be a talking head?!
    Always be marketing.
  • Should I really have a Twitter account and a Facebook account?
    Always be marketing.
  • I don’t have time to monitor searches, comments, feedback.
    Always be marketing.

OK, I’m running dangerously close to being a world-class prick if I really reduce my conversational skills to this kind of catch-phrase smack-down. But you can bet this is what my  internal dialogue is going to sound like from here on out.


by Daniel Jalkut at February 25, 2010 03:08 PM