More Glassy Scrolling with UITableView
[A few days ago][first] I wrote about how to help make your table views scroll more smoothly. The tips and tricks in there definitely work, but I’ve just added another layer of smoothness on top of that. It’s rather heavy-handed, but I thought I’d throw it out there anyway.
[first]:http://www.fieryrobot.com/blog/2008/10/01/glassy-scrolling-with-uitableview/
It starts much the same, use a single view for your cell and do all your own drawing. The ultimate solution presented here though is to cache the whole damned view contents. Revolutionary? No. Extreme? Yes. But it’s the smoothest I’ve been able to get it for my situation. I’m not yet 100% sure I’ll ship with this thing turned on, but I think it’s a valid approach for you to explore for your own project.
In my case I’m slowed down a bit by database fetches, text layout, and rounded images with shadows. By only following the techniques in my last blog post on this topic it’s actually not too bad. But with this addition it’s a lot better.
It should be noted this should really only be used as a last resort due to the increase in memory required.
In order to use this method, you need to be able to uniquely identify a cell by some sort of ID (in my case it’s an NSNumber).
– (void)drawRect:(CGRect)rect
{
if ( !_item )
return;
UIImage* cached = [sImageCache objectForKey:_item.identifier];
if ( cached == nil )
{
CGRect bounds = self.bounds;
UIGraphicsBeginImageContext(
CGSizeMake( bounds.size.width, bounds.size.height ) );
// DRAW CONTENT HERE
cached = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
if ( sImageCache == nil )
sImageCache = [[NSMutableDictionary alloc]
initWithCapacity:1];
[sImageCache setObject:cached forKey:_item.identifier];
}
[cached drawAtPoint:CGPointMake(0,0)];
}
This is actually more expensive to draw in two ways:
1. It means you are drawing and then blitting, instead of just drawing.
2. The table view caches the contents of cells itself, so technically we’re buffering yet again.
But the advantage is that we have the caches around for more than just the visible cells (which is all UITableView cares about). So when things scroll back into view, they’re absolutely smooth as silk.
This does mean that as views first load in they will be less smooth than the next time they roll into view. If the user typically only scrolls in one direction, you might not see a lot of benefit. So you could decide instead to pre-cache items ahead of where the user is. So perhaps you precache the first 20 items and after that let it cache as they are encountered.
When To Dump the Cache
—
Obviously, memory-wise this is not cheap. How much should you save? When should you flush it?
There are many ways to deal with this:
1. Let the system tell you when to flush. If you get a `didReceiveMemoryWarning` call, just flush the image cache completely.
2. Cap the cache at some number of items and flush it when it gets to that size.
3. Cap the cache at some number of items and drop the oldest item when a new item needs to be added (Least Recently Used).
I’m actually trying out #1 believe it or not. I also flush the cache when the view has its `viewWillDisappear` method called. Why keep it around if you’re not actively flushing.
Another trick is to use a timed cache. Wait for the table view to stop scrolling (possibly by listening for the `scrollViewDidEndScrollingAnimation` delegate method to be called. When called, start a 10 second timer. If the view starts scrolling again, clear the timer. This way, after 10 seconds of real non-interaction, you’ll get the chance to flush the cache. No point holding them around.
A timed cache was what we used in Mac OS X for menus. One of the old stand-bys for measuring ‘performance’ was how fast the menus dropped down as you dragged back and forth in the menu bar. So we used the same basic method: on first appearance, cache the image, and from then on use the cache. And then we’d set a 20 second timer to flush the buffers so we didn’t waste memory. Since then I’ve used this technique a number of times.
Here’s a quick boilerplate for how you could use a timer:
– (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
// the user is scrolling/dragging, we WANT the cache, don’t clear it!
[self.timer invalidate];
self.timer = nil;
}
– (void)scrollViewDidEndDragging:(UIScrollView *)scrollView
willDecelerate:(BOOL)decelerate;
{
// if decelerating, wait until it stops first, else start the timer now.
if ( !decelerate )
{
self.timer = [NSTimer scheduledTimerWithTimeInterval:10.0
target:self
selector:@selector(flushCaches:)
userInfo:nil
repeats:NO];
}
}
– (void)scrollViewDidEndDecelerating:(UIScrollView*)scrollView
{
// We know for sure we’re done, start the timer.
self.timer = [NSTimer scheduledTimerWithTimeInterval:10.0
target:self
selector:@selector(flushCaches:)
userInfo:nil repeats:NO];
}
– (void)flushCaches:(NSTimer*)timer
{
// FINALLY. Flush it.
[MyFancyCellView flushCaches];
self.timer = nil;
}
Anyway, there you have it. Probably the most extreme method to get ultra-smooth scrolling while still using UITableView. Use it wisely.
Dealing With Memory Warnings in View Controllers
When the iPhone decides you are consuming too much memory (and I’m not sure what the deciding factors are), it calls your application and ultimately your view controllers’ `didReceiveMemoryWarning` method. In here you’re supposed to clean any caches, etc. But there’s a small wrinkle in how you need to handle this in a view controller.
Is My View Still There?
—
Basically, there’s a comment in the template code that says something like:
// Releases the view if it doesn’t have a superview
This is on the line to `[super didReceiveMemoryWarning];`. Well, this news about your view being released is good, because it means that you can undo what you might have set up in `viewDidLoad`, your go-to place to know your view is there and ready for use. In fact, I always try to do the minimum in any `init` method and save it all for `viewDidLoad`.
The problem is that you don’t really know if it threw the view out. You can’t just test `self.view` as this will recreate the view! So I’ve been using a little trick to help me out:
– (void)didReceiveMemoryWarning
{
UIView* superview = self.view.superview;
// Releases the view if it doesn’t have a superview
[super didReceiveMemoryWarning];
if ( superview == nil )
{
// OK. NOW we can assume view is gone.
}
// Destroy any caches regardless here
}
Essentially I see if the superview was nil before calling the super method. If superview was nil, the view really does go away (unless you have a reference to it of course, in which case things get much more complicated). If the view didn’t go away, you still might want to destroy any caches anyway, as shown above.
When we know the view is gone, I usually unregister any observers I might have installed, since they tend to operate on the view, which will just bring it back into being, which is bad. If the view is hidden, why bring it back into existence if no one can see it? Plus, aren’t we trying to use less memory? It should stay dormant until it’s brought back into the visible world.
Anyway, that’s what I’ve learned to do to ensure that my view is gone and I can tear down virtually everything, as if the controller just got initialized. It sure would be nice if we had a `viewWillUnload` method to catch this for realz instead of what amounts to a best guess.
Other Considerations
—
Even if the approach above worked like a charm, you might have other reasons to keep some data around. I had a situation where I had a view pushed onto a navigation controller that referenced the view underneath. Basically an iterator of the list below it, ala Mail. So I couldn’t throw away all my data structures like I otherwise might have when the view disappeared. So I ended up employing this:
// We can only safely purge the world if we are on top.
BOOL isOnTop = ([self.navigationController topViewController] == self);
And inside the `if (superview == nil)` condition I also checked `isOnTop`. If not, I can’t destroy everything.
Keep in mind that isOnTop can be true even the view was not visible. In a tab bar it might be the top controller on the non-selected tab, for example. In any case, if you’re on top you can safely dispose of all of your data structures, as you know there’s no controllers above you.
So there’s two ways I cope with memory warnings. As mentioned, they probably won’t solve 100% of the needs out there, but it might give you some ideas for you own applications.
Glassy Scrolling with UITableView
Now that the [veil of secrecy has been lifted][nda], I think it’s time to share at least one bit of information that I’ve gleaned whilst writing my new iPhone application: how to do fast tables.
[nda]:http://developer.apple.com/iphone/program/
**NOTE:** If you’re not already familiar with how UITableView works, the rest of this might just sound like jibberish. But I think there’s still valid life advice in here, so please read on!
In fact, one of the reasons I even started to write my app was to prove that I could write an app that does super-fast tables. And in my app (which, yes, is still not-to-be-named), I even do my own rich text layout for every cell. And every cell is a different height. Even I was skeptical that I’d be able to pull of fast tables, but it worked out. Phew!
How did I accomplish this? Well, by applying a lot of what I’ve learned over the years. And learning a bit about how UIView performs.
Use Views Sparingly
—
I’m not quite sure what’s going on in UIView. Maybe it’s that all views are backed by Core Animation layers, but drawing using a bunch of views is a sure-fire way to slow yourself down for straight on scrolling performance.
For simple table views (settings, or profiles, etc.) you probably can get away with using views with subviews. But we want smoothness as the user is scrolling through hundreds of items. In these cases, if you need to write a custom cell, you should use one view that draws everything directly.
Use Opaque Views
—
If you have a transparent cell, this can slow you down. If a view is marked opaque, the view system knows it doesn’t have to render the area behind it and blend your view onto it. This seems to make a marked difference at times. I just ran into this myself and switched to filling the view with the background color of the table and it is noticeably smoother now.
Note that this can work against you if you want to use standard cell highlighting, as your item won’t turn blue since the standard highlighting relies on transparency. But it does work great for instances where the items aren’t clickable. In my case, it was a message view modeled after the SMS application.
Be Lazy and Cache Often
—
Quite simply: don’t do anything until you don’t need to do it. And when you do need to do it, try to do it only once.
As I mentioned I render rich text. Sadly, there’s no built-in way to do this at present, so I have to lay the text out myself. This is not really cheap. So I have a layout object that lays itself out and then I keep that object around all pre-calculated. This is very much the way you’d use something like ATSUI or NSLayoutManager. You do the hard work once, then store it off for later. Then when I draw the cell, I just run along the lines of text and render them. I also calculate the rectangles of everything I will draw ahead of time. Then rendering is just a quick operation.
If you are drawing images, try to cache them at the size you’ll render them. If you are resizing them every time you draw them, you’re in for a world of hurt. In my situation, they weren’t too much bigger than my target size and they’re never bigger than a certain size, so I didn’t even bother. But if the images could be any size, it’d be really important to resize and cache them someplace.
Another thing I needed to do was cache the heights of the cells. If you have a table with variable-height cells, the table view will run through every item in the table and ask it how high it is before it renders anything. In my situation, with all the layout I do, that is pretty costly (it can actually take up to 2 seconds on the device). So I cache the heights. As new items come in and go out of my list, I only need to calc the new items, so after the first reload, all subsequent reloads are really fast since I already have the values.
Another cache I use is for the background for my cells for one of my ‘looks’. In this case, I use `[UIImage stretchableImageWithLeftCapWidth:topCapHeight:]` to give me an image I can stretch across the background. BTW, this is one of the most useful image functions in there. It basically takes an image and separates into a piece that acts as an end cap and a stretchable part. There’s effectively a one-pixel band that gets repeated as it stretches. But I digress…
What I ended up doing was taking these images and, because my cells could only be certain heights, as I knew I was using one font size and the cells would be based on the number of lines, there were only a finite number of heights I’d need (I believe 5). So as I encountered the heights, I created a cached version of the stretched image using code like:
UIImage* background = [[self balloonImage] stretchableImageWithLeftCapWidth:0
topCapHeight:35];
UIGraphicsBeginImageContext( CGSizeMake( rect.size.width, rect.size.height ) );
rect.origin.x = rect.origin.y = 0;
[background drawInRect:rect];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
And then I just take that image and store it in the cache. Very simple. I also stored that as the class level so all views can use the cache.
Nothing’s ever free, of course, so keep in mind that if you cache too much, you might find yourself running out of memory. Be prepared to listen to memory warnings via the `didReceiveMemoryWarning` method and dump your cache if needed.
And finally, also keep in mind that the table view only keeps the visible cells around. Every time a cell comes into view, it asks you for a new cell. You can reuse cells, but even that only will get you so much. So don’t assume that once your list has completely been scrolled through that everything is loaded. You cannot rely on such behavior. This piece of information caused me to change my strategy a bit until I arrived at what I am describing here.
How Do You Know What To Cache?
—
Fortunately, I’ve done this for a while, and I know a lot of the gotchas. But no matter how much you know or think you know, the best way to get real answers is to use a tool like Instruments. It is indispensable for finding bottlenecks in your code. For my app, I just kept sampling my application and finding things I should work on. If you aren’t using sampler or something similar, you really should.
Again: indispensable.
What’s Next
—
Next time I might cover performance in general. How to make your applications fast and not impede the user-experience. I’ll also talk about how to handle low-memory. This can be a bit tricky at times.
Until then!
**UPDATE:** Since writing this I’ve sped things up a little bit by going [one step further][update].
[update]:http://www.fieryrobot.com/blog/2008/10/08/more-glassy-scrolling-with-uitableview/
Software Development Meme
I’ve been tagged by [Seldo][seldo], a former colleague from Yahoo!
[seldo]:http://www.seldo.com/weblog/2008/10/01/software_development_meme
How old were you when you first started programming?
–
I believe I was probably 16 or so. I was in high school and we started learning on Radio Shack TRS-80s and Apple IIe’s. It was in high school when I saw what the Mac was and desperately wanted one. But hell, they were pretty expensive. It would be a few years before ever getting one.
What was your first language?
–
BASIC, on the aforementioned platforms. GOSUB FTW!!
What was the first real program you wrote?
–
The first real program that I wrote and ever sent out into the wild was called DoubleScroll. It was an extension for Mac OS that would give your scroll bars two arrows at each end. It wasn’t the first of it’s kind, but my version worked with System 7 as well as 6. It took a **lot** of sitting in Macsbug to figure out that the System 7 scroll bars got a new, undocumented call to allow them to draw the scroll box outline. Bastages!
What languages have you used since you started programming?
–
In no particular order: Basic, Pascal, Cobol, DBase, Perl, Java, shell scripting, C/C++, Objective-C, PHP, SQL.
The most interesting fact is that when I was working during college, I worked at a store that did all their database stuff in Basic as well.
C I learned completely on my own trying to learn Mac coding. This was just as C was becoming popular. I didn’t have the cash to dish out for MPW and all that fancy stuff at the time, so I got Think C.
I know C/C++/Objective-C best and probably PHP second best. But it’s far second.
What was your first professional programming gig?
—
This was at a company called Charles River Analytics. They worked on a piece of Mac software called Open Sesame. It watched what you did and used real honest-to-goodness AI to find patterns and offer to automate certain sequences. I came on to work on the monitoring piece, since by that time I had a decent amount of experience patching the OS with INITs. By the end of my time there, we had Undo working in the Finder. Yes, it was a flying hack, but it worked!
Of course, after I got to Apple, my viewpoint of patching the OS changed dramastically(tm).
One of the cool things about being there at the time was a) it was when the Internet opened up and b) we got to visit Taligent. It was from Taligent’s use of C++ that we learned a lot. It really opened our eyes as to how it could really be used. They had actual real templates back then. Like, our compilers couldn’t even compile stuff they did. Of course, it was the slowest OS I’ve ever seen, so it didn’t completely sell us.
If you knew then what you know now, would you have started programming?
—
Oh hell yes. It’s one of those really addictive things that sucks me right in. It’s just too cool to be able to code something up and show others. Especially these days with the stuff I’ve learned over the years.
If there is one thing you learned along the way that you would tell new developers, what would it be?
—
Wow, only one? Well I’m giving you three!
1. Don’t do ’surface coding’. Always strive to understand what’s really going on underneath some APIs if you can. I find that it really helps me get my head around the way a frameworks, etc. is put together. Sometimes, when I see something odd, I’ll write little tests to kind of see what it’s really doing. Sort of a black box model, I guess.
2. Never assume you know how things are going to perform, or what’s slow and what’s not. You’d be surprised.
3. Be lazy. Don’t do anything in your code that you don’t need to do. This was a huge thing we learned at Apple, and it made huge differences in performance (and perceived performance). I swear I could write a book from all the things I learned while there.
What’s the most fun you’ve ever had… programming?
—
I’ve had many fun times, I enjoyed doing that first DoubleScroll extension as it was such a learning experience both in terms of tech as well as dealing with customers, etc. It was also exciting to be sent a book **with** a check or the software from Michael Crichton.
My time as Apple was very fun, as was some parts of my Yahoo! experience (the Atlantis – Konfabulator 4.0 project).
But I have to say, the iPhone app I’m working on now has been a **lot** of fun. Probably the most fun I’ve had coding in a long long time.
Who’s next?
—
This is a tough question, actually. I think I’m going to tag [Daniel Jalkut][jalkut] next! Since I wrote this in MarsEdit, I felt it was fitting
[jalkut]:http://www.red-sweater.com/blog
CoreGraphics is Right After All
A while back I wrote about a potential [issue with compositing][issue] using Quartz. I’m happy to finally conclude that there in fact is no issue. Yes, Quartz does behave differently than Cairo, but I believe Quartz has the more consistent behavior throughout all its modes. I came to this realization after talking to the engineer who does the compositing work in Quartz.
The main difference is that Quartz will only ever touch pixels within the ‘clip’ of an object, whereas it seems that Cairo will touch pixels outside of it. After thinking about it for a bit this makes much more sense, and seems to be a much simpler thing to implement as well, so I’m not sure why [Cairo][cairo] seems to take the tack they do.
So for example, if you fill a circle in Quartz, only the pixels inside the realm of influence (the circular path itself) will have the [Porter-Duff][pduff] blending applied. This is why things look different in Safari and Firefox when using these modes in a canvas object.
I reported in my prior post that I thought that it **should** affect pixels outside the circle, but this no longer makes sense to me after talking with that engineer. Now, if you were to blit an image of the circle, the area of influence would be the image rect (intersected with any clip, obviously). Then you’d get results more like what you’d expect. So basically, once you know that fact, you can likely still do most of the things you’d want to do using these blend modes.
So in the end it just seems like limiting the blending to the effective clip area is the better method. It’s far simpler to implement, since much like painting the circle in say, source over, you only affect pixels inside the circle. Ever. And that is a constant through all composition modes. This makes it consistent and predictable.
So in the end, it’s right, as far as I’m concerned (and Apple, of course)!
[issue]:http://www.fieryrobot.com/blog/2007/08/11/could-coregraphics-be-wrong/
[cairo]:http://cairographics.org
[pduff]:http://keithp.com/~keithp/porterduff/
Limbo
I’ve recently left Yahoo! after 3 years there. I already miss hanging out with everyone, but it was clear to me that the best thing for me was to get out and find my own path.
I got to Yahoo! through the acquisition of Konfabulator (now [Yahoo! Widgets][ywe]). It was an interesting experience to say the least. I think I could write a small book on my time there. That might be the topic of a future post here. Suffice it to say, I don’t think it went as well as it could have.
But this post is about my current state of limbo. Not quite anywhere right now. It was definitely a little risky to just leave my job and take some time off. I’ve never had the opportunity do it before, and I have a few irons in the fire regarding what to do next, so I figured I’d give it a go. This way, I can really be free and clear to refocus myself and know what I really feel about what I want to do next.
So far it’s been a pretty good time off. I’ve mostly been working on my own iPhone application. I won’t say what it is yet. It’s nothing super-special, but it’s turning out pretty sweet. I know I will use it every day, maybe you will too. I have no idea if I’d even charge for it or not. If I did, maybe it’d be a buck or two. But that’s not even really in my head right now. I just want to finish it!
I’ve really been enjoying coding for the iPhone. Yes, even though it’s Objective-C
The only annoyances for me have been the bugs I keep running into. I’m a good boy though and I write them up for Apple. Heck, I even sent in a test case for one. Fortunately, most of them to date have been duplicates they know about. Hopefully they’ll get squared away soon.
As far as what to do next, I’ll keep meeting with people over the next few weeks and hopefully we can figure this out. While I am enjoying my time to myself, I certainly can’t keep this up indefinitely! Maybe I should be an Indie developer for iPhone/MacOS. Then I can stay home **and** survive.
Stay tuned.
[ywe]:http://widgets.yahoo.com
UIKit: A Fresh Start
Having (like zillions of others) just downloaded and started playing with the iPhone SDK this past week, I’m pretty impressed with UIKit. Being a frameworks/API guy myself, I can fully appreciate they way it’s put together. It’s very easy to do the simpler things and if you want to get down and dirty, you still can. I also really like the fact that it’s fully CG-based (no NSGraphicsContext nonsense), and the best part of all to me: top-left graphics origin! Yes, it’s the simple things in life.
I guess above all this demonstrates that by starting over, they’ve been able to take all the stuff they’ve learned over the past however many years of AppKit and were able to make a much more consistent and coherent set of APIs that demonstrate all those years of learning what works and what doesn’t. This makes UIKit a winner to me. Clean, concise. I’m soooo glad they started over. But of course, it was the right choice anyway considering the device constraints and just how different it is from a desktop environment. They certainly needed something smaller and more tuned to the iPhone. Good call.
The jury’s still out on Objective-C 2.0 for me, though. It has a lot of nice new features, but the syntax is still all wacky. The property syntax is a little heavy for my tastes. Almost too much control via the attributes. But at least you can finally use dot notation to get at your data. The thing is: I *know* I could come up with a way to annotate things and make the syntax more in line with other things out there (C#, etc.) while still preserving the great things about the runtime. I also still seriously wish you could get your constructors called if you put an object in as a member of an Obj-C class. That still seriously irks me. I’d love to hear the reason that can’t be made to work.
My nitpicking aside, I think there’s going to be a *ton* of iPhone apps coming out. And certainly all that use of Obj-C and their MVC model will likely help Apple get more traction for Mac OS X apps too. Once you’re in that door, the skills transfer so easily. I’m sure it wasn’t the primary intention of coming out with a phone, but it’s definitely a beautiful secondary effect.
Silverlight and Yahoo!
Wow. Someone just mentioned [Silverlight][] in something I just read, and it got me thinking about how Microsoft would have a huge network to use it as a de facto standard if this MS/Yahoo! thing really pans out.
[Silverlight]: http://www.microsoft.com/silverlight
I have to say, after going to [MIX][] last year, I was thoroughly impressed by Silverlight, to the point where I thought that Flash was in trouble if they can get some momentum going. Their tool set is very well done, and their ability to separate the design from the business logic to allow some parallelism is pretty amazing. In short, it’s one of the few MS technologies I think they’ve really gotten right. Of course, I haven’t used it personally, so take what I say with a grain of salt.
[MIX]: http://visitmix.com/
So if MS/Yahoo! happens, I could certainly see us starting to use Silverlight more and more. I’m not so sure that’s a bad thing.
YHOO and MSFT
Well, unless you were hiding under a rock yesterday, you saw the announcement that Microsoft offered a bid to acquire Yahoo! Inside the company there was a range of reactions, as you can imagine. But I’ll tell you my own perspective. There’s no inside dirt here, so if you’re looking for secrets, stop reading now.1
Not So Worthless Now, eh?
————————-
Yahoo! has always been a somewhat misunderstood company. And certainly a company that is very undervalued. That’s not to say that it does everything right. There are valid reasons some users don’t appreciate Yahoo! practices at times. But we do in general get a bum rap.
Clearly millions upon millions of people use Yahoo! services every day (and **like** them). If you consider the amount of traffic, users and the raw strength of the brand, our Thursday stock price of $19 was incredibly undervalued. So if nothing else, Microsoft’s fairly generous bid for Yahoo! proves that there actually **is** value to be had, and my guess is it’s northwards of the $31 per share number they threw at us. Clearly people liked the news since the stock jumped to $28.
At least now you’ll actually start to see articles and blogs pointing out the value that Yahoo! has instead of everything they hate about it. And there is a lot of value. But there’s also still a lot of fat (not just the 1000 people who are about to get layed off). I see people who I really don’t know why they’re still there or quite frankly what they do these days still walking around collecting salaries. It’s more than a little frustrating at times. But I digress…
So Should We Do It?
——————-
My feeling (and let’s face it, what the hell do I know) is that we might be stupid not to. In the end, I think it might be the right thing for both Yahoo! and Microsoft. If they could figure out a good way to structure things (keep Y! brand, properties, etc. ditch MSN and merge its technology into Y!), I believe it would be a smart move. I’m sure any agreement we enter into will be well thought out and argued about from top to bottom in lawyer-land (a place of unintelligible language, unthinkable evil and attaché cases). (Update: actually, [here's an interesting way it could be done][not-so-bad])
[not-so-bad]: http://feeds.feedburner.com/~r/typepad/alleyinsider/silicon_alley_insider/~3/228441847/dear-jerry-and-steve-heres-the-answer.html
But of course, from the other more emotional angle, it would be pretty sad to have to do it, right? I mean, it’s Microsoft. You know, with the [mild-mannered Steve Ballmer][nutso]. That makes me a little scared. To some of my coworkers, it makes them physically ill. But objectively it also has me a bit intrigued at the possibilities such a merger would unlock.
[nutso]: http://www.youtube.com/watch?v=Y89wBYVHkY4
I look at it this way: this is about the 3rd (or more?) time that MS has tried to do some sort of deal with Yahoo! Each time, Yahoo! said no, we can fix ourselves. But we apparently can’t. I don’t feel the management team has focused Yahoo! enough and I also feel they took way too long to start trimming the fat (I wouldn’t have stopped at 1000). So maybe this is a blessing. I’m sure Microsoft thinks so.
Other Bidders?
-
I’ve heard about other bidders in the mix from various blogs, but I tend to agree with comments that these other bidders are a much more iffy scenario than a Microsoft deal. And Microsoft is going to be tenacious at this point. There’s no way they can hope to compete with Google without some big game-changer like this. The fact that the letter to the board went public was clearly intentionally done to create I think a reaction from shareholders to force Yahoo!’s hand or something. Also, if you saw that letter they sent out internally (if real), they act like it’s a done deal. Who knows, maybe it is. But I can’t believe that for a second, since there’s so much they’d need to talk about before saying yes.
A Kick in the Pants
——————-
But no matter what happens, we’re way more stronger and more valuable now than we were on Thursday. That, plus the potentially more positive press should put us in a much better position than we were. And that is a great thing.
And in Parting…
-
As you may have heard, Terry Semel left our board the other day. Apparently we paid him half a **billion** dollars to tank our company. I think it’s time for me to have a go at CEO. Hell, I can screw us up good for that kind of money!
—–
- Speaking of secrets, the amount of stuff that happens at Yahoo! that gets broadcast to the outside is out of control. People, shut up!↩
This is Just Plain Nuts
I shouldn’t give this guy more airtime than he deserves. But give this a read:
[Apple iPhone Doomed To Failure][doomed]
[doomed]: http://www.networkworld.com/community/node/23744?nwwpkg=iphone
He tells you it’s doomed, but I never really see him explain exactly why. Because it’s Microsoft? I don’t think so. Wasn’t Vista supposed to take over the world? What happened there? I can’t tell you the number of meetings where directors or VPs would ask us “how are we going to deal with Vista?”. They did this because they believed the media, not to mention they just were kind of knee-jerk reactionaries. In the end, it wasn’t much of anything to worry about. Don’t get me wrong, I like Vista much better compared to XP, but it certainly didn’t have the impact Microsoft was hoping for.
It seems to me that while Microsoft is definitely getting better at their UI, they never quite match the level of quality that Apple puts out. Take a look at the Windows Mobile 7 info and mocks [here][] It doesn’t look too bad actually, but some screens are still too cluttered. In general, with Microsoft designs, they look good at first, but they wear on you quickly. For whatever reason, Apple’s designs tend to stay attractive for a lot longer. And user interaction on Apple products is always consistently better as well.
Apple also has such a lasting effect on the markets it enters these days, and some it doesn’t. Remember when the iMac came out? So many copycat machines and designs were influenced by it. Not just computers, but everything: wastebaskets, etc. Everything starting coming in tons of colors. Then the iPod arrived which really took off when the store came into being (again, Apple was the first to even try selling music online) and now the iPhone. Already LG has to tout a touchsreen that looks remarkably like the iPhone. I’m sure they started on that the second Apple announced. The point though is that Apple changes the game with many of the things they do. For example, the iPhone has visual voice mail. The most amazing thing about that fact to me is that they managed to make AT&T budge. Wow. Meanwhile, the rest of the word is still pressing 7 to delete. Enjoy. 1
The point is, now that the iPhone is out, the bar is raised: people are now going to *expect* phones to be that cool and slick to use. Anything else is just kind of ordinary at this point. I bought and played with a Nokia N95 recently, and while it was feature-rich (some features put the iPhone to shame), it just wasn’t very pleasant to work with from a UI perspective. I just sold it on eBay because it just felt like a step backwards in ease-of-use.
While the first article I linked to sounds like an Apple-hater, I might be sounding like an Apple-lover. That might be partially true, but there are plenty of things I don’t like about the iPhone, or wish it had. It’s just that for my usage the positives far outweigh the negatives.
[here]: http://microsoft.blognewschannel.com/archives/2008/01/06/exclusive-windows-mobile-7-to-focus-on-touch-and-motion-gestures
——
- Oh, and the visual interface that’s on the Treo 700w for voicemail is just graphics buttons for the touch tones. So you’re still pressing 7! ↩