Friday, April 23, 2010

iPad Max Touches

One thing I've been curious about for a while is what is the extent of the iPhone's ability to detect and track multiple touches. On the original iPhone, I've been able to detect and track 5 touches, though my fingers are large enough that I rarely could get it to recognize more than 4 distinct touches.

On the iPad, we've got a much bigger screen that will let all ten fingers touch at the same time without running together.

So, can the iPhone SDK track 10 fingers at once? Yep. It sure can. I wrote a simple program to just record the count of the touches set provided to the four UIResponder touch-related methods, and it had no problem identifying and tracking 10 separate fingers at the same time.

I don't know what the hardware or software limitations are on Apple's multi-touch technology, but it seems to be high enough not to be an issue.

MacTech 25 Most Influential?

Today, I received the most recent issue of MacTech Magazine. The cover story was about The MacTech 25: The 25 Most Influential Rock Stars, MVPSs, Prophets and Pundits of the Apple Technical Community. Curious about who made the list, I flipped to the cover story and started reading through the names.

At the start, the list was pretty much the people I expected, but when I turned the page, there was my name, following Dan Lyons and Brent Simmons, and preceding Leo Laporte and David Pogue. I knew a couple people had voted for me, but I really didn't expect to actually make the list. I'm still a little stunned, to be honest, and flattered. I haven't figured out yet if I'm supposed to be an MVP, "rock star", prophet, or pundit, though, but I'm flattered no matter which it is.

The fact that enough people appreciate my work enough to have voted for me means an awful lot more to me than actually being on the list, so I want to send a very sincere thank you out to the people who voted for me.

Thursday, April 22, 2010

Table View Cells Redux

Quite a while ago, I posted about Apple's recommended way of doing custom table view cells in Interface Builder. The code from that post has been available for 9 months and today, for the first time, somebody pointed out to me that the attached project didn't reuse dequeued cells because I forgot to type the cell's identifier in Interface Builder.

Which is the weakness with Apple's recommended approach. It's a real Achille's heel. It's really, really easy to forget that step, and the code works perfectly fine if you do forget, you're just eating memory and getting poorer performance than you should. Unless you profile your apps or test with very large data sets, you could very well ship your app like this and not even realize it. You never want your customers to discover these things before you.

Now, I didn't even know I had made this mistake until today, but I've known it was a potential problem for quite some time, which is why, in my contract work, I've started using a modified version of the technique. My earlier mistake now gives me a good excuse to post that modification.

Mostly, it's the same technique as I discussed before, only I start out by defining a constant for the identifier. I actually create a header file in my Xcode projects ConstantsAndMacros.h in my project, which I add to my pre-compiled header file. This means that any constants and any macros I put in ConstantsAndMacros.h will be available to all my source code files in my project without having to manually import them. For a simple project, that file might look something like this:


#define TABLE_CELL_IDENTIFIER @"Table Cell Identifier"
#define NSStubLog() NSLog(@"%s", __PRETTY_FUNCTION__)¹

Once I have that file, I add it to the .pch file in the Other Sources folder:

#ifdef __OBJC__
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "ConstantsAndMacros.h"
#endif

Now that constant is available project wide². Then, in my UITableViewCell subclass, I override the reuseIdentifier method and add a class method with the same name, like this:

+ (NSString *)reuseIdentifier
{
return (NSString *)TABLE_CELL_IDENTIFIER;
}

- (NSString *)reuseIdentifier
{
return [[self class] reuseIdentifier];
}

By doing this, the system will ignore any identifier I set in Interface Builder, or any value I set in code using the setBundleIdentifier: mutator method. For instances of this particular class, it will always use the same identifier. By creating the class method, I have access to that identifier even if I don't yet have an instance of the class.

For all the other steps in using custom table view cells loaded from a nib, the process is the same as the previous tutorial and it works great. Here's an example tableView:cellForRowAtIndexPath: method using this technique:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{
TestCell *cell = (TestCell *)[tableView dequeueReusableCellWithIdentifier:[TestCell reuseIdentifier]];
if (cell == nil)
{
NSLog(@"Loading new cell");
[[NSBundle mainBundle] loadNibNamed:@"TestCell" owner:self options:nil];
cell = loadCell;
self.loadCell = nil;
}

cell.cellLabel.text = [NSString stringWithFormat:@"Row %d", [indexPath row]];
return cell;
}

Notice the NSLog() statement? I can open my table view cell in Interface Builder and set any identifier I want, or set no identifier at all, and it will still re-use table view cells. Run the app, and no matter what you do in Interface Builder, you'll only see a handful of rows loaded from the nib file. After the initial loads, it will just keep reusing the same cell instances over and over. This is far less fragile than having to make sure the identifier in IB and the one in your code match.

There might be times when you don't want to set it up like this - when you need to have multiple identifiers for the same table view class, but those situations will be exceedingly rare. In most practical situations where you are subclassing UITableViewCell, you will want a single identifier for all instances of that class. What you normally won't want is the fragility of having to make sure the value in your code matches the one in IB exactly, especially given that there are no obvious signs that you've forgotten to do it.


1 This macro just logs the name of the method of function that it's placed in when that method is called. I use it whenever I stub out an IBAction method to make sure my connections are all made correctly, hence the name, but it's useful for debugging as well.

2 If you will only use a table view cell in a single controller, you probably don't want it here. In general, I try to create table view cells to be generic enough to be used in more than one controller. Sometimes that's not possible or practical, and in those cases, #define your identifier in the table view controller header instead.

You can find a sample implementation project right here/

Misc Ramblings

Wow. It's been a while since I've posted anything. I don't think I've gone this long without a blog post since I started. Maybe towards the end of writing the books I might have, but not otherwise. Anyway, let me catch you up on a few things while I eat my lunch.

I've got a few tutorials that have been simmering, but finding time to write them down has been hard. Programming is a feast-or-famine business, and thanks to the crazy success of the iPhone, iPod Touch, and iPad, things seem to be very much in feast mode lately. Not that I'm complaining - it's far better than the alternative - but when you spend twelve or more hours at your desk writing code most every day, it's hard to motivate yourself to write a tutorial about writing code in your spare time. I think I might be getting a breather here pretty soon, so I'll try and get some new iPad related tutorials out and hopefully another OpenGL ES one at some point.

Rumor Mill


Let's see, what else is going on in the world? There was a rumor that Apple's looking at buying ARM, ARM shares soared, then ARM came out and said flat out it wasn't true, and their stock stopped soaring. Call me cynical, but I still think it's a possibility. It'd be a great match and a great strategic move for Apple. Apple has the cash. If they bought ARM and a graphics chip maker like NVidia, they'd have total control of the entire A4 SOC except for the mass production side of things, and I'm sure that would be desirable to Apple. They love control.

ARM is a mobile and embedded powerhouse. Apple would get control and a big sledgehammer over many of their competitors. At first blush it seems like it might hurt Apple's relationship with Intel but, actually, it would be great for Intel, because it would drive a lot of Apple's mobile competitors exclusively to Intel's Atom chipset.

I have no idea if it'll happen, or if there was ever any validity to the rumor in the first place, but it "feels" like a good move for Apple if they could pull it off and it "feels" like something they would do. They've got to have plans for some of that cash they're stockpiling. If not, well, feel free to call me, Steve… I'll be glad to hold onto some of it for you.

Ebert


I have a number of friends and acquaintances who are game designers, and there's been quite a buzz lately over Roger Ebert's recent statement that games can never be art. I, of course, disagree with his statement. In fact, I find it almost laughable. Of course games can be art. I mean, I'm not a big gamer, but I've played enough for that to be obvious to me. Roger Ebert, by his own admission, hasn't. He's judging based on YouTube videos, screenshots, and people's descriptions.

But it's hard to see how many games wouldn't qualify as art. Saying otherwise is saying that the whole is somehow less than the sum of the parts. Sculpting (digital modeling is just another form of sculpting), painting (digital is just another medium), writing narrative and dialogue - these are all things that are widely considered art. How can you put those things together into a package and have something that can never be art?

Now, I like Roger Ebert's writing. I don't agree with his tastes in movies all that often, but I like the way he writes. When I read his reviews of movies, I generally know enough to know if I'm going to like it or not even when I disagree with his assessment. He generally communicates well. This post isn't like that. It's rambling and self-contradictory. It's post-hoc rationalization for an opinion he already held. There is no exploration. Most of his "logic" could just as easily be applied to any commercial artistic endeavor, like movies. The rest of his logic is basically nonsense.

But here's the thing: So what? The question of "what is art" is completely unanswerable in any way other than a completely subjective and personal one. To Roger Ebert games aren't art. To me and especially to people who love games, they clearly can be and often are. It's okay for us not to all agree on this particular subject. It really is. It clearly wasn't meant as an insult, just as a statement of opinion on an inherently subjective topic.

There are many things that are widely considered art that I, personally, don't consider art. To me, a lot of 20th century art simply isn't. Most of the work by, for example, Jackson Pollock and Isamu Noguchi simply do not match my personal, subjective definition of art. To me, they're silly, but not in a Monty Python, intentionally silly way. It's silly stuff that takes itself way too seriously. These works don't convey or communicate or show us anything. They evoke no emotion, recall no events, inspire nothing. In my mind, they take no talent¹ to produce and the world is no better for their creation.

Yet, the vast, vast majority of people (very possibly including you), and nearly all soi-disant experts on art disagree with my assessment in these cases, and that fact doesn't influence my opinion in the slightest. I suspect Roger Ebert is no more likely to be swayed on the subject of games as art than I am about a lot of 20th century art, no matter how impassioned or well-reasoned the response.

Or, in other words: Get over it. Don't waste your time arguing with someone who isn't going to be swayed and probably won't even bother to argue back. Saying something isn't art isn't saying it has no value. That's the way we often interpret it, but we're being too sensitive when we do. If you create, and people like what you create, who cares if there's somebody out there that doesn't like or care about it? You can't please everybody. Most books on Amazon with five-star ratings also have some one-star ratings (including mine). What appeals to one person will revolt another. Such is life, and you'll be happier if you don't rely too much on external validation of your work.

Apple


Well, Apple is clearly on its death bed once again. The iPad, as many pundits predicted, has been a miserable failure, and sales of iPhones and iPod Touches have stalled as they fail to compete with the flood of innovative new Android and Palm phones that have come out this year.

Okay, maybe that's not entirely true.

Whatever your personal feelings about Apple, they're on quite a roll. It's a great time to be a programmer with iPhone SDK experience. We've got to be getting close to a hundred million iPhone OS devices sold - last I knew, there were over 85 million. That's a huge potential market. We've now exceeded or, at least, are getting very close to the installed base of Mac OS computers, even taking the phenomenal recent growth in Mac sales into account.

Well, that's all I have for now. I'll hopefully be back to technical posts in the not-too-distant future.




1- That's not to say these men didn't have talent, just that much of their work product didn't require it. Isamu Noguch's earlier works, such as his Undine, are absolutely phenomenal.

Monday, April 12, 2010

Can We Stop with the "Evil" Thing?

I always enjoy reading James Higgs' commentary on iPhone issues even though we often disagree on issues. That is true for today's piece entitled iPhone OS 4.0: Now With Added Evil. He makes some good points, many of which I disagree with, but, I have one big pet peeve with his post, which is…

…can we please stop with this trend of calling things we dislike or disagree with "evil"?

Evil is baby killing… pogroms… serial killers… the Jonah Brothers. You know, bad shit. Evil is not restricting the choice of languages you can use when you write software for a single software platform from a single vendor. My gosh, people. Talk about skewed, first-world perceptions! This is, at worst, "annoying", "frustrating", or maybe even "bothersome". It's certainly not "evil" in any reasonable sense of the word. It's not even immoral, unethical, illegal or fattening, no matter how much you may dislike it.

(Sorry, James - you're not the only one to do this, yours was just the proverbial straw that broke the camel's back)

I appreciate that people don't like the recent SDK agreement changes, and I even understand why. But let's keep some fucking perspective, can we? We all signed an agreement that said Apple could unilaterally change the terms of the agreement by giving us notice, and we were okay with that because we wanted to be part of the App Store. Now that Apple has actually gone and changed it a few times, people are whinging like the world is ending. The door's not locked, people. Feel free to leave if it gets too onerous for you. If you're not willing to man up the way Dan Grigsby did, then register your complaints using the bug reporter and move on with your life.

I don't always like the decisions Apple makes. I think the app store censorship is sucky, the review process is still too arbitrary, and 3.3.1 is worded more broadly than it should be. But none of those are bad enough to make me leave the platform. I like the platform, and there's still so much opportunity here that I definitely want to stay. So, I've lodged my complaints and have moved on.

I really don't want to get sucked into the argument about 3.3.1, but I need to point out that there is a valid reason why Apple would choose to do this. Even if you don't agree with their decision, you should at least acknowledge that it's not arbitrary (something I've seen as an implicit assumption in many of the rants and arguments against 3.3.1)

If you use Apple's provided tools and frameworks, when you submit your app, all the code that makes up your app is available. Apple controls part of it, and you control the other part. With an intermediate layer, there's a third chunk of code that's a black box. Apple can't get to it and you can't get to it, either. Have you noticed that we're also not allowed to build frameworks for the iPhone the way we can on the Mac. Same exact reasoning.

The changes Apple is having to make to the frameworks to accommodate the multitasking APIs in 4.0 offer a good example of why Apple feels they need to do this. I can't discuss technical details of 4.0, but I will say that by tweaking the frameworks and APIs, Apple has been able to maintain a surprisingly high level of backwards compatibility with older apps. Guess which apps aren't playing nicely with the new multitasking functionality?

Yes, it's about control, but no, it's not arbitrary or without reason. You are welcome to disagree with Apple's judgment, but don't assume the changes ares being done for arbitrary reasons: to spite Adobe or because Steve Jobs is in a bad mood.

Let's look at a hypothetical situation. Let's say that instead of the handful of Flash-generated apps that Adobe snuck onto the App Store, let's imagine that there are 5,000 of them. Let's also say that hypothetically, for some reason, Flash-generated apps don't work with 4.0, and Apple can't reasonably make them work with 4.01. When 4.0 is released and all of those apps break, who's going to end up looking bad?

If you responded with anything other than "Apple", you're delusional or, at least, don't understand customers. Customers don't know or care how their apps were made. They know that yesterday, their apps worked, today they don't and the only difference is that they updated to a new version of the OS. What's the logical assumption for somebody who doesn't know the underlying technical details to make? There's only one: That Apple's new OS sucks. Would it be an accurate assumption? No, but that's the perception people would be left with, and to Apple, customer perception is king.



1- Yes, Apple could work with Adobe to get the Flash Packager changed, but a) Apple has some reason to anticipate that Adobe would drag their heels, since they've dragged their heels for ten years on moving Creative Suite to Cocoa, and b) they'd have to test a good portion of the 185,000 apps on the App Store to even know which third party library was at fault, which just isn't practicable.

Core Data Library

For quite some time, I've been thinking about ways to improve the use of UITableViewController. I experimented a bit with a property-list driven model, and then simplified that into the paired-array version that is in More iPhone 3 Development. One of the things on my "would like to do list" has been to revisit that and create a good, robust tool to make table-based editable detail views easier.

Somebody beat me to the punch though. I haven't tried it out yet, but first impressions are positive and it looks like a great tool for anyone writing apps with table-based detail views.