Here’s why there’s no Flash on the iPhone/iPad/iPod

This is a detailed letter from Steve Jobs as to why Flash isn’t on the iPhone/iPad/iPod.

You really need to read the article to get all the details, but briefly:

  1. Flash is a closed system. Yes Apple admits to some level of being closed, but HTML5, CSS, JavaScript are open standards.
  2. The “full web”
  3. Reliabilty, security, and performance. Flash fails in all 3 areas.
  4. Battery life. Flash drains it heavily and quickly.
  5. Touch interfaces. Flash isn’t designed for that.
  6. Inserting a third-party into the user experience can yield less than optimal results.

Speaking as not only a consumer of these products but also as an Apple Developer for almost two decades, I can say Apple’s reasons are quite sound.

One very telling and modern reason?

Flash was designed for PCs using mice, not for touch screens using fingers. For example, many Flash websites rely on “rollovers”, which pop up menus or other elements when the mouse arrow hovers over a specific spot. Apple’s revolutionary multi-touch interface doesn’t use a mouse, and there is no concept of a rollover. Most Flash websites will need to be rewritten to support touch-based devices. If developers need to rewrite their Flash websites, why not use modern technologies like HTML5, CSS and JavaScript?

This is quite true. Touch-based is where computing is headed, and Flash just doesn’t grok it. So yes, if you need to rewrite, might as well rewrite in more modern technology.

Anyway, instead of whining to get Flash, we should be encouraging web developers to move beyond Flash.

Code Bubbles

For you developers out there, check this out: Code Bubbles.

And you really need to watch it full-screen, high def, as it’s hard to understand what they’re talking about without being able to see the text they’re editing.

Present development IDE’s are all about text files… you are organized based upon the way the data is stored. I recall long ago thinking about how that, well, sucked. 🙂  It’s one way to organize things for sure, but why should we be limited by the storage constraints of the system if that’s not the best way to actually organize and access the data? We should be able to abstract that notion away. Isn’t that part of what computers are all about?

I really like how this “code bubble” approach works to allow you to focus on work. The data is just the data. You work with the data. You can see how the data relates to other data. If you need to add your own data, like a flag or a note, you can do that. How you can preserve data that is generated, such as a debug session, and then come back and revisit that at another time be it just starting a second debug session or something you did weeks ago. How documentation, how bug reporting, how annotations are just integrated into the system and so you can hook all of these things together to allow you to work on a problem with all the necessary parts just right there and connected together. Then how you can take all of this and serialize it to share with a colleague?  That’s pretty cool.

I will say, some of the bubbles are a little annoying, mostly because I think the left-to-right hierarchical structure is a bit cumbersome on screen. But that’s a minor nit, and they’ve actually done a fair job at trying to address a lot of that mundane usability minutia. The concepts here are really good, and I figure all it takes is time in use to actually develop and truly refine the workflow. Bubbles may not be the final solution to improving the developer workflow, but it’s great to see someone working to develop a model that rethinks the whole process and strives to improve upon our existing paradigms.

Neat idea.

Verbose booting

While the Mac prides itself on being so user friendly, it’s a computer like any other… written by humans… worked on by humans… and so, there’s always a chance for problems and things to go wrong.

One handy thing to do is to set your Mac to boot into verbose mode. This way when your Mac boots, instead of just seeing the spinning daisy and other pretty non-informative information, you can see all this stream of geeky stuff going by. You probably won’t know nor care what most of it means, and that’s fine. But there will come that day when something odd will happen. Maybe you installed something new, maybe something on the computer decided to go south, and now the machine acts strange at boot time. This is when you’ll be happy to have booted up in verbose mode. Even if you don’t understand what’s going on, being able to relay that information to your local geek helper can be useful towards remedying your problem.

There are two ways to do it.

The simple way is to hold down a key combo at boot time: command-v. That is, hold down the command key and the “v” key as soon as you hear the restart chime. The command key is the key immediately adjacent to the spacebar, with the Apple and little “cloverleaf” symbol on it (I tried to display the symbol here, but WordPress is acting strange). The verbose mode should start immediately and most obviously, and then you can release the key combo. The benefit of this approach is it’s on-demand, but the downside of this approach is it’s on-demand; once the boot sequence starts, you cannot press cmd-v to see what’s going on so if something ugly happens during the boot process you won’t see it.

A more permanent solution is to launch the Terminal.app and enter this command at the prompt:

sudo nvram boot-args="-v"

Which will pass the “verbose” option to the boot arguments stored in the nvram of the machine. This way every time you boot your machine it will boot in verbose mode. This is how I set every Mac I own. 99% of the time I don’t care what’s scrolling by on screen, but there are days when I’m glad to see the information going by.

One thing to note. If you zap your PRAM (command-option-p-r at the boot chime) it will clear the nvram and your verbose argument will be lost. So when zapping your PRAM, zap it, and as soon as the machine chimes again immediately press cmd-v to go into verbose mode. Then once the machine is properly started up and you have logged in, launch the Terminal.app and enter the nvram command.

BBQ Not Found

A few days ago I was in a business that had lots of old vehicle license plates decorating the walls. Some were just plain plates, others were vanity plates. One in particular caught my eye. Given it’s age (well before the Internet) I have to assume it the combination of letters and numbers was coincidence. I forgot to get a picture, but I can’t forget what the plate said:

BBQ 404

All I could think to myself was “BBQ not found? How sad.” 🙂

Stupid iPhone

Last night at the Motörhead show my iPhone crapped out on me… again.

So much for getting pictures.

I actually had taken a couple pictures of The Sword.

I intentionally left the phone on “Camera” so I could take more pictures, especially of the Motörhead performance. But then I pull out the phone, press buttons and no response. Damnit. I fiddle with all the buttons I can, and nothing. The phone, she’s dead. Last time this happened to me I had done a similar thing: the phone was likely left on an application, I put the phone into my back pocket, pull it out and she’s dead. That time I had plugged in the phone and eventually saw the battery come alive with almost no charge… so the battery had run down. I figured that’s what happened here so I just forgot about it until I got home.

However when I got home and plugged in the phone for a while, it didn’t come back. Uh oh. I Googled about it and apparently this is not an uncommon problem. The solution?

A hard reset.

Press the power button and home button together and hold… you might have to hold for a little while (30-60 seconds?), but eventually you should see the Apple logo on screen. When you do, it’ll churn away and eventually you go about your business. I did have about 70% battery left, which means some battery was drained but not everything.

Digging deeper into my ~/Library/Logs/CrashReporer/MobileDevice/ folder of my sync machine, it looks like the phone had a kernel panic.

Ah… modern computing.

Anyway, now that I know about the hard reset, next time this happens I’ll try that and see how it goes.

NSRuleEditor – you are so cool but so frustrating

If you’re not a Mac programmer, you can stop reading now. 🙂

Apple has this cool new widget called NSRuleEditor, introduced in Mac OS X 10.5. A lot of the software I’ve written over the past some years involves searching for things and often the user needs to provide you with rules by which to search. I’ve always had to invent my own solutions, and it’s a non-trivial thing to do. So when I finally heard about NSRuleEditor some years ago I was most excited to finally have an OS-provided solution.

The way Apple implement the widget is pretty cool. They realize people will use it to display whatever arbitrary data model they have, so they structured it that way. The NSRuleEditor iself is a single control, the contents of which are opaque to you… mostly. There’s your data model objects, which NSRuleEditor calls your criteria (that bugs me, as “criteria” is plural and the API uses it in a singular sense, but oh well… I can understand why they did that). The criteria can be whatever you want them to be, it doesn’t matter. But each criteria object then has a “display value”, which is how the criteria is displayed and/or worked with in the GUI, such as a string or a menu item or a text field or date picker. Thus I can have a LabelObject, an OperatorObject, and a TextObject which represent my data model. The LabelObject would have a display value of “name” and a predicate value of “left hand expression” and kMDItemDisplayName, the OperatorObject would have a value of “contains” and a predicate operator value of  “IN”, and the TextObject would have a display value of an NSTextField and a predicate value of the “right hand expression”. Thus I could get the GUI to display “name contains <foo>” and create a query string like “kMDItemDisplayName IN <foo>”.

It’s a little obtuse to wrap around at first, but once you figure it out, it’s actually pretty well done. Apple has to make a generic control that anyone can use, and rule display/editing is non-trivial. Really, they did a pretty good job with this.

One thing to realize is the displayValues are not necessarily what is displayed in the GUI. Yes they generally are, but when you do this there is no localization. However, NSRuleEditor has a way you can provide a dictionary of formatting strings that allow you to change the displayed format. You see, the criteria objects are truly the data model. The displayValues aren’t truly the view… they can be, but they’re like “one step back” from being the view. Really, you should be using the formatting strings to get the real view… and then it’s like the displayValues are a “view model” for the view. Confusing? I know, but this is how it is. The formatting strings are your way to localize the display, but of course you don’t need to use it for localizing… you could just use them to change what is truly displayed to something other than the strict “view model”. There’s flexibility in the mapping the formatting strings provide.

So for instance I want to do a name criteria. The formatting strings are a key-value pair. The key is a pattern that matches the labels of your criteria objects. For instance:

%[Name]@ %[matches, contains, is, begins with, ends with]@ %@

Provides the formatting key. The %@ groups demarcate special identifiers, so that in your value, you’d have something like:

%1$[Name]@ %2$[matches, contains, is, begins with, ends with]@ %$3@

As the formatting value is parsed, it picks up the “x$” identifiers and knows this affects the ordering of the elements in the string, so you could shuffle things around. As well then, the items within the brackets are also ordered. So for instance if I had a value string like:

%1$[Name]@ %2$[ends with, begins with, is, contains, matches]@ %$3@

then when my data model said “matches” the GUI would present “ends with” to the user. Of course, this would be highly confusing to the user thinking they were doing an “ends with” search but the actual search ended up doing a “matches” search. But it shows what you can do.

Of course, the real benefit of this is localization. Let’s say we were converting “name contains foo” to Japanese. The key is the same as above, but the value then becomes:

%1$[お名前は]@ %$3@ %2$[が入っている]@

Which is “name contains”.

All of this is good and great. But where it falls flat? You have no way to know what NSRuleEditor is displaying. What if you wanted to get that that information? You can’t. You can get the -criteriaForRow: to get the row’s criteria objects. You can get the -displayValuesForRow:, which gets the raw display values. But you can’t get the formatted display values, like a -formattedDisplayValuesForRow:

*sigh*

This put a big crimp in things for me and the code I’m presently working on. Granted, I can get all the elements myself, of the criteria, the display values, and the formatting strings, but to apply the formatting strings to the display values is a non-trivial task. IMHO, a bug/shortcoming in the NSRuleEditor API. Bug filed: rdar://problem/7741182.

NSPredicate trick

That all said, there is a cool NSPredicate trick.

This comes from blacktree-alchemy’s code for QSMDPredicate. It’s basically a way you can shove a MDQuery syntax string into an NSPredicate and have it all work out. Handy because NSRuleEditor is based upon NSPredicate, but since NSPredicate and the MDQuery syntax don’t have a perfect one-to-one correspondence (or maybe you’re using MDQuery instead of NSMetadataQuery), it’s handy.

In case the QSMDPredicate code ever goes away, here it is. Again, this is NOT mine, just someone thankful for it’s existence and release under the Apache License 2.0.

QSMDPredicate.h

//
// QSMDPredicate.h
// QSSpotlightPlugIn
//
// Created by Alcor on 5/6/05.

//

#import

 

@interface QSMDQueryPredicate : NSPredicate {
NSString *query;
}
+ (id)predicateWithString:(NSString *)aQuery;
- (NSString *)query;
- (void)setQuery:(NSString *)aQuery;
@end

QSMDPredicate.m


//
// QSMDPredicate.m
// QSSpotlightPlugIn
//
// Created by Alcor on 5/6/05.

//

#import "QSMDPredicate.h"

@implementation QSMDQueryPredicate
- (id)generateMetadataDescription{
return query;
}
+ (id)predicateWithString:(NSString *)aQuery{
QSMDQueryPredicate *predicate=[[[self alloc]init]autorelease];
[predicate setQuery:aQuery];
return predicate;
}
- (NSString *)predicateFormat{
return query;
}
- (NSString *)query { return [[query retain] autorelease]; }
- (void)setQuery:(NSString *)aQuery
{
if (query != aQuery) {
[query release];
query = [aQuery copy];
}
}
- (id)copyWithZone:(NSZone *)zone
{
id copy = [[QSMDQueryPredicate allocWithZone:zone]init];
[copy setQuery:[self query]];
return copy;
}
@end

 

(Wow… I just realized my current WordPress.com theme is crappy at handling blocks. I need to learn more CSS so I can tweak that).

Today is going to suck.

I just bit myself, hard.

Day job has me as a software developer. I was testing out some changes to a window layout. This window allows you to configure automated tasks… so say, at midnight your computer will automatically execute whatever you told it to do. Well, I was just testing out the GUI changes but needed a task in the window so I created a dummy task. The task ended up being set to move basically every file in my home directory into my Documents folder. I didn’t set it that way, those are just all the initial settings when you create a new task. I didn’t care.. .it was just to be a dummy task for the GUI testing, right?

Only I forgot to remove the task before I stopped work for the day.

I get to my work computer this morning and about shit myself because I saw everything was gone.

Only no, it’s not all gone, it just moved some 97,000 files to a single folder.

Shit. Shit. Shit!

And the sad thing is, my Time Machine backups were turned off because last month it started to constantly choke on these particular files, and I couldn’t resolve the issue. So the last backup I have is a month old. But hey, if I had a backup from a few hours prior I could just blast it back and be done with it.

Damnit.

Well, I know what I’m spending today doing.

*sigh*

Car Code

I figured with the growing amounts of electronics in cars that there must be a lot of code behind it, but I didn’t realize just how much code until I read this article.

Speaking as a software developer, that is massive amounts of code. Huge. Trying to maintain that would be a bear. Furthermore, trying to ensure it’s error/bug-free? A monumental task, edging on impossible.

I don’t know how the automotive industry works in terms of producing this software, but if it’s anything like most commercial software companies then lord… it makes me want to drive a Model T, that’s all mechanical and easy to fix. All I can do is hope they have a good understanding of proper software development process and are not willing to sacrifice solid reliable code because they need some new feature and needed it yesterday.

I also hope they understand how simple is better. All those millions of lines of code? Gosh… if they can take the time to simplify and trim that down, so much better in the long run. More maintainable, less chance of errors and problems and risking catastrophic failure.

Gosh I hope they do things right.

Of course the geek in me wants to know nitty gritty details now like the language they’re using and the toolset. 🙂

-[NSTableView setDoubleAction:] not working?

This is documented but in a subtle way, so I thought it’d be worthwhile to mention in a more obvious way.

If you are using NSTableView’s -setDoubleAction: method, the action is only invoked if the cell or column double-clicked upon is uneditable.

Thus, it may not be enough to go:

[theTableView setDoubleAction:@selector(myAction:)];

You may also have to do something like:

[theTableView setDoubleAction:@selector(myAction:)];
[theTableColumn setEditable:NO];

I ran into this just now because I had a single-column table (just a simple table to display a list of stuff, thus the user wasn’t allowed to edit anything) and I wanted to allow a double-clicking on the item (row/cell) to advance the user to the next stage of things (they could also single-click to select the item then click a “Go” button… double-click would just be a shortcut). It actually was working fine under Mac OS X 10.6 Snow Leopard, but the double-click was failing under Mac OS X 10.4 Tiger. Once I made the table column explictly uneditable, it started working and the table received the clicks, the clicks didn’t fall through to the table column.