Or try one of the following: adult swim, Afterdawn, Ajaxian, Andy Budd, Arabic Language, Ask a Ninja, AtomEnabled.org, BBC News, Blogdigger, Brent Simmons, Channel Frederator, CNN, Crazy Apple Rumors, del.icio.us, Digg, Diggnation (Odeo), Diggnation (Video), Dominic Sagolla, Dooce, Flickr, Google News, GVOD, Harvard Law, Hebrew Language, Hungarian Language, InfoWorld, iTunes, Japanese Language, Korean Language, MacNN, mir.aculo.us, Movie Trailers, Nick Bradbury, OK/Cancel, OS News, Phil Ringnalda, Photocast #1, Photocast #2, Photocast #3, ReFrederator, Romanian Language, Russian Language, Traditional Chinese Language, Technorati, Think Secret, Tim Bray, TUAW, TVgasm, Web 2.0 Show, White Collar Ruckus, Yahoo! News, You Tube, Zeldman
inessential.com
Brent Simmons’s weblog.Subscribe: Bloglines, Google Reader, My MSN, Netvibes, Newsburst
Newsgator, Odeo, Pluck, Podnova, Rojo, My Yahoo!, Desktop Reader
NGMoviePlayer - AVFoundation-based video player 19 Aug 2010
I put up on bitbucket NGMoviePlayer — it uses AVFoundation to play movies. It does some of what MPMoviePlayerControllerView does.
(I had to write a custom movie player because of a bug in iOS 4 where after you play a movie that’s embedded in a UIWebView, MPMoviePlayerController won’t work as expected: it plays just a few frames and then automatically pauses the movie. <radr://8326264>)
In writing this code I used a few things that were new to me: AVFoundation, blocks, and UIGestureRecognizer. (I got to do some learnin’, in other words.) (I still have to support older OSes with most of my code, and sometimes it takes a while before I get to use the cool new stuff.)
Side note: one of the interesting things about AVFoundation is that the headers say it will be available for Mac OS X 10.7.
Anyway... if this helps somebody out there at some point, then cool.
Blinklist | Del.icio.us | Digg | Furl | Ma.gnolia | Newsvine | Spurl | Technorati
My personal VisiCalc moment 10 Aug 2010
Every successful computing platform has to have a “VisiCalc moment” — the moment it goes from fun toy and technology demo to “holy crap this thing is useful.”
For the Apple II Plus that moment came the first time people saw VisiCalc. Imagine never having seen a spreadsheet on a computer — imagine always having done that stuff by hand. Then, for the first time, you enter some numbers and formulas into a computer and watch it calculate. Then edit some numbers and watch it recalculate. Pure magic. PFM.
I don’t think there’s a single VisiCalc moment that everyone will have for the iPad — but, for me personally, it was OmniFocus. That’s when my iPad went from toy to indispensable tool (oh, but still a fun toy, too).
Before OmniFocus, my iPad wandered around my desks without a real place. Now it has a place right next to my dev machine’s keyboard.
Blinklist | Del.icio.us | Digg | Furl | Ma.gnolia | Newsvine | Spurl | Technorati
Flexibility and power 10 Aug 2010
Whenever I think about new (or old) features in software, I think about whether they’re flexibility or power features.
They’re different things. Flexibility is the ability to change how software works; power is the ability to do more with less effort.
There’s a complicated relationship between the two things. Sometimes flexibility may add to power — if I could just make these things green, my eye could pick them out more easily, and I’d get my work done more quickly.
But flexibility detracts from power just as often — or more often. Flexibility is an invitation. It says, “Hey, futz with this. And this. And this. You’re not getting anything done, but at least you kind of have the illusion of doing something.”
One thing I love about iPhone and iPad apps is that they have to be designed for power. There’s just not enough conceptual canvas space for a ton of flexibility.
And I think people who use software — which includes you and me and everybody reading this — are learning to value power over flexibility. In part because of iOS apps, and in part because our attentions are further disintegrated and we have less time for each app.
How many more apps do you use now than you did five years ago? You used to get by with email and chat — then you added Twitter and Facebook. And an iPhone and screenfuls of more apps. And an iPad and more screenfuls.
You don’t spend your time skinning your audio player anymore, in other words. You just play music. And you do other things while the music’s playing.
It may go against the grain a little bit, but I’ll say it: I’m incredibly excited for the future of Mac software. I don’t expect we’ll make software that looks and feels like iOS apps (we shouldn’t), but I do expect we’ll learn from iOS apps how power is the real goal, and that flexibility is just a tool to use exceedingly sparingly, only when it substantially increases power.
Blinklist | Del.icio.us | Digg | Furl | Ma.gnolia | Newsvine | Spurl | Technorati
RSTwitterCallGetXAuthAccessToken 2 Aug 2010
I put up some sample code for getting an OAuth access token when calling https://api.twitter.com/oauth/access_token (for xAuth clients).
I was having trouble getting this working, so I wrote a one-.m-file, easy-to-debug class so I could make it work. It’s not meant to be used as-is, but it might be helpful to other folks writing apps that talk to Twitter.
Blinklist | Del.icio.us | Digg | Furl | Ma.gnolia | Newsvine | Spurl | Technorati
Static analyzer rules (for me) 6 Jul 2010
I so adore Build and Analyze.
I’ve developed a small set of rules I follow:
Always run static analysis. There’s a project setting called Run Static Analyzer — if you set it to true, it will always run the analyzer when you build the project. So I set it to true.
If the static analyzer finds a problem, I immediately add a
TODOcomment with a quick note about what needs to be done. Even if I think I’m going to fix it right away. (Because the phone might ring, cat might need dinner, and I’ll forget.)If the static analyzer finds a false positive, I immediately add a comment along the lines of
//Static analyzer false positive. This way I don’t waste time on it later, and nobody else does, either. (Ideally there’s an explanation, too, if it’s not self-evident.)But I still consider a false positive a kind of warning. It’s a good sign that something too clever (in a bad way) is going on. So, if I think I should — and I usually should — I also add a
TODOcomment about revising whatever it was that triggered the false positive.
The goal is, as with errors and warnings, a completely clean bill of health.
Blinklist | Del.icio.us | Digg | Furl | Ma.gnolia | Newsvine | Spurl | Technorati
Follow up to memory management thing 28 Jun 2010
In the previous post I have an initWithString method that looks like this:
- (id)initWithString:(NSString *)aString {
self = [super init];
if (self == nil)
return nil;
something = [aString retain];
return self;
}
I knew, as I was typing it, that I’d get some feedback along the lines that I should use copy instead of retain.
And I did.
And it’s excellent advice, totally, no question. The reason to use copy instead of retain is because it enforces the expected immutability of that incoming string, so the caller is free to change it in case it’s really a mutable string.
However, I don’t follow that advice. One reason is that, in my eight years of Cocoa programming, this has never been an issue. Not once have I run into a problem because I used retain instead of copy in a case like this.
The second reason is that I consider the use of copy here a case of overly-defensive programming. The effect would be to hide a bug, if one exists, and I wouldn’t want that.
Given those two reasons, it’s just bonus that using retain means avoiding the extra allocation that using copy would mean — but I’ll take that bonus.
Update 5:24 pm: Yes, copy returns self for immutable objects. (All the time, at least for Foundation objects? I don’t know.) So, no bonus in those cases. But I myself often pass mutable objects where immutable is expected. So I get the bonus. (And it’s not a bug on my part, no.)
Update 5:41 pm: OK, why do I consider it a bug if aString is really a mutable string and I change it elsewhere? It’s totally legal if aString is really an NSMutableString. I do things like that all the time. But I code as if there’s an implicit contract: any Foundation objects (strings, dictionaries, arrays, sets, etc.) passed between objects must be treated as if immutable. If the object that receives the object wants to do something based on aString, it may, indeed, then have to make a mutableCopy or whatever. And if aString was really a mutable string, the caller has to not change it from that point on.
Why do I code this way? It simplifies things. It removes doubt.
Blinklist | Del.icio.us | Digg | Furl | Ma.gnolia | Newsvine | Spurl | Technorati
How I Manage Memory 28 Jun 2010
I’ve noticed, in looking at other people’s Cocoa code over the years, that sometimes people still do weird things with retain, release, and autorelease — as if they’re not quite sure on the basics of memory management yet.
So I thought I’d talk about how I do things. There are three important points, then a practical explanation of one of them.
Overall memory use is a design issue. It’s not usually a case of over-using autorelease or something like that. (For instance: are all your objects in memory at all times, or do you use something like Core Data so you don’t have to do that?)
Memory management — the nuts and bolts of making sure you don’t leak or over-release — should be as simple as possible and done in the same way every time.
The exceptions to #2 should be done only as a result of profiling in Shark and Instruments.
Practical explanation of #2
I find not-leaking and not-over-releasing very, very easy. That’s because I have a simple system, and I do things the same way every time, except when profiling tells me I need to make an exception. (Which is rare.)
Here’s what I do:
I use properties, and I use the full form: self.something and self.something = whatever. I try to avoid custom accessor methods, just use the standard synthesized methods.
I don’t use the full form in init and dealloc, though, because it might trigger KVO or have other side effects.
So a made-up class might look like this:
@interface BSThing : NSObject {
@private
NSString *something;
}
- (id)initWithString:(NSString *)aString;
@property (nonatomic, retain) NSString *something;
@end
@implementation BSThing
@synthesize something;
- (id)initWithString:(NSString *)aString {
self = [super init];
if (self == nil)
return nil;
something = [aString retain];
return self;
}
- (void)dealloc {
[something release];
[super dealloc];
}
- (void)someRandomMethodThatDoesStuff {
//Let's just change something
self.something = @"Something else";
}
@end
Make sense? Outside of init and dealloc, access is always via self.something.
There are two other things I do:
Pretty much create everything as autoreleased
Seriously. I almost never write code like this:
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; //do something with dict [dict release];
It’s more code and it complicates things and it’s easy to make mistakes. I get confused. I don’t understand at-a-glance that the code is correct. I know there is advice to avoid autorelease on iPhone — but you already know you can’t avoid it, and I’ve found that any drawbacks by use of autorelease are over-shadowed by other issues.
So here’s what I always write:
NSMutableDictionary *dict = [NSMutableDictionary dictionary]; //do something with dict, completely un-worried about leaking it. //I can even return early.
Autorelease pools
One exception to the above is, of course, when you’re doing a bunch of allocations in a loop. Then I will use an inner autorelease pool. I won’t do that crazy thing where you make it drain every 10 times or whatever — I’ll drain it in each pass. Simpler — and no reason to change that unless Shark or Instruments says to change it.
I’ve been doing it that way since reading Mike Ash’s article Autorelease is Fast. Though, obviously, it’s not as fast on iPhone, it’s still probably faster than you think it is.
Recap: my simple rules
Use properties, and use synthesized accessors as much as possible.
Always use the self.something form — no direct access to ivars, except in
initanddealloc, where only direct access is allowed.Create temporary objects, or objects that get returned by a method, as autoreleased.
Use autorelease pools as needed, but don’t try anything fancy.
Profile in Shark and Instruments, and make exceptions to the above only when it makes a real difference.
Consider that your overall memory use issues are probably design issues, not (usually) code issues.
Following these rules, writing Cocoa code is damn close to scripting.
Blinklist | Del.icio.us | Digg | Furl | Ma.gnolia | Newsvine | Spurl | Technorati
Casual 24 Jun 2010
I’m not sure what relative this is, but I love the picture’s Alfred E. Neuman vibe.

Blinklist | Del.icio.us | Digg | Furl | Ma.gnolia | Newsvine | Spurl | Technorati
Road to beach 24 Jun 2010
My great-grandmother (on left) and her sisters (I think) on the road to the beach in New Jersey. Click thumbnail for bigger version.
Blinklist | Del.icio.us | Digg | Furl | Ma.gnolia | Newsvine | Spurl | Technorati
Put weblogs on bitbucket 18 Jun 2010
I’ve moved the repositories for inessential.com and ranchero.com to bitbucket and made them public read-only.
ranchero.com repository
inessential.com repository
It’s just the raw stuff that gets rendered into weblog posts — it’s not the rendering scripts. There’s no actual software. Just a bunch of words.
Not sure why I did this. Maybe just because I could. But sometimes big bunches of text can be useful for somebody somewhere.
The actual posts are in the posts directory. Older posts are HTML, newer posts are written in Markdown. The lines at the top of each post that start with a @ character are metadata. Stuff between [[ and ]] are macros. Stuff between [[= and ]] are includes (grabbed from Snippets folder).
I wrote about my system in early 2009 here. I’ve been quite happy with it. To restate the advantages:
Static HTML pages are fast. I don’t have to worry about getting Fireballed. :) And they’re easily portable, if I ever have to change web hosts.
Static RSS feeds are fast too, which is good because they get requested a lot.
Having source control is especially nice when I’m working on templates.
Having source control is great for offsite backups. (I was using Dropbox before I switched to bitbucket. I’ll probably still keep a backup on Dropbox, just because.)
Being able to search through my weblogs on my desktop using Spotlight or ack is very convenient. (Okay, I admit I use ack mostly.)
The system can generate a local preview version, so I can render my site just on my machine and look at it before uploading. I don’t use that often, but it’s nice when working on templates.
Best part: I still get to use MarsEdit — I have a small Ruby-based server that implements the API that MarsEdit expects. I hardly ever actually look at the weblogs as files-on-disk, and I never edit the posts that way (though I could).
Blinklist | Del.icio.us | Digg | Furl | Ma.gnolia | Newsvine | Spurl | Technorati
Reminder about upgrading NetNewsWire 15 Jun 2010
I don’t usually use my personal weblog for this kind of thing — but it’s important for NetNewsWire users, so I want to make sure all bases are covered.
A couple months ago we released updated versions of NetNewsWire that work with an upcoming change in Google Reader. That change (in the authentication system) goes into effect tomorrow (Tuesday). So it’s important to make sure you have the latest version.
In a nutshell: you should have Mac 3.2.7 or greater (you can look at the About window). For iPhone and iPad, you should just check the App Store to make sure there isn’t an update waiting for you.
More details are in a post on the NetNewsWire weblog.
Blinklist | Del.icio.us | Digg | Furl | Ma.gnolia | Newsvine | Spurl | Technorati
Practical WWDC tips 6 Jun 2010
No time to write something long or organized this year. Quick notes, then.
Drink plenty of water. Make sure there’s plenty of water in your hotel room.
Try to avoid walking the streets at night alone. I wouldn’t say the streets are dangerous. But still.
Avoid the Tenderloin.
You are your fellow developers keeper. Be inclusive. Help anyone who needs help. Be that good person your grandmother imagines you are.
You’re here to learn and see cool things. Part of that is telling other people about the cool things you’ve seen. (Related: you’re not here to complain.)
Go to the ADA ceremony. When you don’t win (odds are you won’t win), remember that feeling. It’s useful year-round. But clap hard for the folks who do win — they worked hard and earned it, and they deserve your support. If you see them later, congratulate them.
Use your iPhone alarm and the hotel’s alarm clock, especially for Monday morning.
Make it drop-dead easy to plug your iPhone into power at night, so you don’t forget.
Put your hotel room number in your wallet.
Use Twitter for organizing and finding out what’s going on.
Remember to eat. Don’t worry about what you eat too much — you’ll go back to being virtuous when you get home. The important thing is to not skip meals: you’ll need the energy.
Remember to listen to music sometimes. You’ll need the energy from that, too.
You won’t be graded on your week — except by you.
The friends you make will mean more to you than the APIs you learn.
Guy English is there only to break your heart. (Total sadist, that guy. Delights in it. Whatareyagonnado.)
Blinklist | Del.icio.us | Digg | Furl | Ma.gnolia | Newsvine | Spurl | Technorati
BSSAXTweetParserDemo 4 Jun 2010
I had reason to look at MGTwitterEngine today. It had been a while since I looked at it, and I was reminded that the libxml-based parser in there was originally based on my BSTweetParser from a couple years ago. (Folks did a real nice job of improving it, of course.)
But I don’t do my XML parsing like that anymore. I still use libxml, but I use the SAX interface these days.
Here’s a new demo project — somewhat like the old BSTweetParser, but using SAX: BSSAXTweetParserDemo. (It’s an Xcode project folder with source.)
I have no special unnatural love for SAX, like some people, but it’s the best way to get both high performance and low memory use. (These days I always use SAX.)
Notes about the code
Twitter’s public timeline XML is very simple, so it makes a great demo. Easy to follow what’s going on.
SAX is event-based.
SAX means you don’t have to have the entire XML document in memory — you can pass it to the parser in chunks. This demo doesn’t do that, but my production code does. (Do you want to hold a 5MB XML document in memory on an iPhone? Nope.) Luckily, NSURLConnection makes this very simple. Don’t append data to build the response body — just pass each chunk to the parser and forget it.
The original BSTweetParser code allocated a ton of strings and dictionaries. This new code still has to allocate memory — but it allocates a whole lot less memory. This makes a giant difference on iPhones and iPads.
The original BSTweetParser code just turned everything into arrays, dictionaries, and strings. This new code is selective: it stores only what it wants to store, and it uses custom objects: BSTweet and BSUser instead of dictionaries. I recommend this when performance and memory use matter (as they always do on iPhones and iPads).
The comments in the demo code hint at, but don’t entirely demonstrate, the best way to parse a stream like a stream of tweets: don’t create a big array — instead, each time you have a new tweet, call some delegate to do something with it. No need to store the whole thing as an array and then process it — that uses too much memory. (But that’s exactly what the demo is doing. To keep the demo simple.)
This code not only does less memory allocation, it’s also more than twice as fast as the original BSTweetParser. (The two things are related, of course.) On my development machine, BSSAXTweetParser parsed the timeline in about 0.0008 seconds, while BSTweetParser did it in about 0.0017 seconds. (“Faster and less memory? Sold!”) (I bet the difference is way more dramatic on iPhones, but I built this is a Mac Foundation tool.)
You’ll probably realize fairly quickly what parts of the BSTweetParser class could be made an abstract class from which your real parsers would inherit.
There’s a bunch more code in BSSAXTweetParserDemo than in BSTweetParser. I prefer less code to more code almost as much as I prefer breathing to not-breathing. But that’s life — sometimes the faster and better thing takes more code.
I put this thing in the public domain. Use however and wherever.
In the tradition of all demos ever, there’s no error checking or handling.
When it comes to things like XML parsing on iPhones and iPads, the entire name of the game is doing the least work possible.
There are ways to make this even faster still.
Blinklist | Del.icio.us | Digg | Furl | Ma.gnolia | Newsvine | Spurl | Technorati
More on Apps that work together – on iPad 27 May 2010
Bill Gray: “However, there’s still no way an app could ‘discover’ what other apps are available and what services they provide under this scenario, and that’s really clutch for this sort of thing...”
Excellent point. It can be done without, but so much better if we had that.
Blinklist | Del.icio.us | Digg | Furl | Ma.gnolia | Newsvine | Spurl | Technorati
Universal Back Button app 27 May 2010
Daniel Stødle: “The idea is to provide a back button that takes you back to the task you were working on, before you opened a file, clicked a link, or similar.”
Clever and interesting. I bet I never would have thought to use the Apple events debug option to make this work. Cool.
Blinklist | Del.icio.us | Digg | Furl | Ma.gnolia | Newsvine | Spurl | Technorati
Re: Apps that work together — on iPad 25 May 2010
Rainer Brockerhoff: Re: Apps that work together — on iPad: “I was thinking about the same issue, coincidentally, and one idea which occurred to me is to use the equivalent of the http referrer URL.”
Blinklist | Del.icio.us | Digg | Furl | Ma.gnolia | Newsvine | Spurl | Technorati
Universal back button? 24 May 2010
On ollicle.com appears an extension to my idea about URL schemes on iPad: a universal back button on Macs. Very interesting. I like it.
Blinklist | Del.icio.us | Digg | Furl | Ma.gnolia | Newsvine | Spurl | Technorati
Shared code management 24 May 2010
We have five Cocoa apps at NewsGator: TapLynx, Social Sites, and three versions of NetNewsWire. They share code.
(You may not have heard of Social Sites. Written by Nick Harris, it’s an iPhone client for our Social Sites enterprise social networking app.)
We’ve just been doing the copy-files thing. Not good. So below I present an (ever-so-slightly edited: took out two words) internal email I just sent about managing the shared code. This is as a sanity check: I think, given our tools, this is the best way to manage this stuff, but I wouldn’t mind hearing that there are other, better ways.
The email: “Shared Code Plan”
Here’s the issue: we have a bunch of code that’s shared between two or more apps. We don’t have a way of managing this right now other than just copying files — which is inconvenient at best, and leads to files being not-quite-the-same in different places as bugs are fixed and features added.
Here’s the solution I’m thinking of. If any of this sounds like the wrong way to go, let me know.
Code shared between two or more apps will all live together in an RSCore repository. (If Apple can keep using NS, we can use RS. I just find the initials more poetic than NG, and that actually, bizarrely, matters to me.) This way the shared code will all be the same for each app.
Existing and new projects will include the RSCore repository as a Mercurial sub-repository (a sub-folder in the project folder).
The RSCore repository will have Foundation and UIKit sub-sections. (This way NetNewsWire/Mac can still use the Foundation stuff.)
A given project will include just what RSCore files it needs. It won’t be presented as a static library, since that makes debugging a pain, and leads to including unnecessary code.
However, RSCore will have a unit tests project, so we can verify code changes before committing, so we can avoid breaking all our apps at once.
Category methods on Foundation and UIKit will begin with an rs_ prefix, to avoid namespace collisions.
New classes in RSCore will be prefixed with RS.
We’ll be conservative about what we add. Only things that are for sure used in more than one app will go in there.
The idea is not to make additional work, but to make less work in the future, to make all this manageable, to increase productivity.
Make sense? Not make sense?
Blinklist | Del.icio.us | Digg | Furl | Ma.gnolia | Newsvine | Spurl | Technorati
Apps that work together — on iPad 24 May 2010
On Macs we have a long-standing culture of apps working together. I can think of a few examples from my own Mac app: you can send a podcast to iTunes, send an article to Twitterrific to tweet it, or send an article to MarsEdit to post it to your weblog.
Of course, on a Mac, the calling app doesn’t quit when you do these things. It stays open. You can get right back to it. (In some cases, the calling app stays in front the whole time, like when sending a podcast from NetNewsWire to iTunes.)
On the iPad (and iPhone) we can sort-of do the same thing. We don’t have AppleScript or Apple events, but we do have the URL scheme thing for inter-application communication. It’s technically possible to do some of these same things.
But we don’t have an easy way to get back to the calling app. Imagine a hypothetical case like this:
You’re in Twitterrific, looking at a web page, and there’s a link to a feed. You want to subscribe to that feed.
So you choose a “Subscribe in NetNewsWire” command. It opens NetNewsWire and subscribes to the feed.
Now that you’ve done that, you want to get back to your place in Twitterrific. You want it to be exactly as if it never quit.
We can do #1 and #2. It’s #3 that’s tricky.
So I have an idea. It just came to me, so I don’t know if it’s good or bad — but it’s worth posting, at least.
What if the calling app added, as a parameter to the URL, a URL to call when the task is completed?
This way the helper app (NetNewsWire in this case) would know, once the task is complete, how to get the user back to their place in the calling app (Twitterrific in this case).
The helper app wouldn’t even have to know anything about the calling app — it’s opening the URL that it was handed. (Maybe there’d be a spot for a success/fail return code of some kind too, but that’s a small side issue.)
Sensible? Silly?
Blinklist | Del.icio.us | Digg | Furl | Ma.gnolia | Newsvine | Spurl | Technorati
Adam Curry on creating the Big App Show 19 May 2010
curry.com: “If my intuition is right, I think we might even see app programmers become the heroes of a generation, where fans can’t wait for the release of the next magical app their idol has become famous for.”
Blinklist | Del.icio.us | Digg | Furl | Ma.gnolia | Newsvine | Spurl | Technorati
