Skip to content


On the Postage Rejection

Note: A technical post follows. If you’re not interested in iPhone programming, you can safely ignore it.

Technical Analysis
An update to RogueSheep’s Postage app was recently rejected by Apple because of a supposed overriding of a private method in a category. Apple most likely used a static analyzer to determine this problem. As far as I can tell, Apple has a bug in their static analyzer.

Three20 adds a category method -previousViewController to the UIKit class UIViewController. According to RogueSheep:

The notice from Apple indicated that we had used a private method of UIViewController called previousViewController.

As far as I can tell, there is no private method in UIViewController called -previousViewController. There is, however, a private method on UINavigationController (a subclass of UIViewController) called -previousViewController.

However, this should not be a problem. Subclasses of UIViewController which implement -previousViewController themselves will override the category method defined on UIViewController by Three20. This includes UINavigationController and whatever other Apple-defined subclasses exist for UIViewController.

I have filed this as Radar #7414099 (rdar://7414099 for Apple employees). The test project is available at: CategoryBehavior.zip

Opinion
Ultimately, if my analysis is correct, this is just a bug. They happen. Static analyzers are especially difficult to get right, especially when the source isn’t available. This shouldn’t be read as an indictment of Apple, or of Apple’s intentions. They’re just trying to protect the user experience of their products and head off binary compatibility problems.

However, I personally think they’re going to have a difficult time trying to detect private methods with a static analyzer. They might have better luck doing analysis at runtime — checking the actual class hierarchy and interposing on method calls.

Meanwhile, there will be a lot of false positives caused by this, which is going to be frustrating for a lot of iPhone app developers.

Posted in Miscellany.

Tagged with , .


bit.ly + tinyurl.com = FAIL

For awhile now, Planetary Scale LLC has been using bit.ly to link to Mappity Quakes on the iTunes App Store from our homepage. I chose to use bit.ly because of their statistics tracking on clicks, something I couldn’t get just by linking directly to iTunes page for the app.

Tonight, while writing another blog post, I tried clicking on the bit.ly link to go to my app’s page, and instead saw this:
bitly fail

Somehow, my link had been flagged as malicious and I’ve been missing out on potential sales because bit.ly decided to break my link. Why though?

Looking at bit.ly’s FAQ, they say:

Bit.ly filters all links through several independent services to check for spam, suspected phishing scams, malware, and other objectionable content. We currently include Google Safe Browsing, SURBL, and SpamCop in our operations.

Checking Google Safe Browsing, SURBL, and SpamCop, I see neither planetaryscale.com nor itunes.apple.com are blacklisted.

Okay, that’s weird… but wait! It looks like when I originally created the link, it was actually a link to a tinyurl.com link. That was kind of dumb of me. However, as a sanity check, I’ve created a link to Disney.com with tinyurl to see if it too will be blacklisted by bit.ly. Unsuprisingly, it is. Checking Google Safe Browsing, tinyurl.com is listed as an intermediary to malware, as is bit.ly.

So, the takeaway from all of this is: as far as I can tell bit.ly is flagging all links to tinyurl.com as malware, even just a link to the tinyurl homepage.

Why is this worse than just a screwup on my part? Consider that bit.ly is used to automatically shorten URLs in a lot of services, such as Twitter. A quick check shows bit.ly also flags links to the homepage of is.gd, tr.im, cli.gs, tiny.cc, BudURL.com, snipr.com, snipurl.com, and kl.am, all of which are competitors. In fact, if I tried to link to the Enterprise Edition of BudURL in a tweet, it would be automatically converted to a bit.ly link. Clicking on that link would take someone to a giant warning page, rather than the product of a competitor.

I realize bit.ly is trying to do this as a safety feature, but as it stands I’m moving my web links to direct URLs. The added value of their statistics tracking just isn’t enough to offset the risk of them breaking my links.

Posted in Mappity, Miscellany.


iPhone App Sales Heatmap

David Smith has a great post over at Revolutions on charting time series as calendar heat maps in R. He includes source code from Paul Bleicher to create the heatmaps in R.

I track the sales data for my company’s iPhone apps using AppViz and thought it’d be interesting to whip up a graph of my iPhone app revenue in this format. Here’s the result (red is low revenue, green is high):
iPhone App Sales Heatmap

Sales peaked in January when the Mappity offline city maps apps were released, and have been falling since then. Those blank spots in the second half of 2009 are days of $0 in revenue.

Interestingly, it looks like Mondays and Tuesdays are relatively weak days for sales. This is probably due to customers going back to work or school.

If you’re an app developer and would like to generate a graph like this of your own, it’s really easy. If you have AppViz, export your data in the “Revenue by Day” format. Then, run the Python script I wrote to convert the data, which is available on GitHub.

Download the calendarHeat.R file from the original blog post and import it into R. Then, import the reformatted revenue data and generate the graph with this bit of R code:

data <- read.csv("PATH TO DATA", as.is=TRUE, sep='\t') data <- transform(data, week = as.POSIXlt(Date)$yday %/% 7 + 1, wday = as.POSIXlt(Date)$wday, year = as.POSIXlt(Date)$year + 1900) calendarHeat(data$Date, data$Converted.Revenue, varname="iPhone Revenue")

Replace "PATH TO DATA" with the path to your CSV file to import the data. Enjoy!

Posted in Mappity, Products.


Tweeteorites OAuth Support

I’ve just put the finishing touches on Twitter OAuth support for Tweeteorites. This means you can now favorite tweets and follow users directly from the Tweeteorites web site.

It also means that rather than contacting @tweeteorites on Twitter to have timelines set up for your user, you can just authenticate with OAuth (by clicking on the login link) and timelines will be set up for your user automatically.

We don’t use your OAuth permission for anything other than favoriting tweets and following users (and only at your request), so you don’t need to worry about us using up your API requests. But if you are an OAuth user on the site, your favorites and friends’ favorites will be looked at more often by our software, which will help keep your timelines up to date.

Enjoy!

Posted in Products, Tweeteorites.


Today Was Fun

There’s been a lot of interest in Tweeteorites since we launched. Specifically, people are wondering why we ask people to message @tweeteorites on Twitter to set up timelines. Well, here’s why.

There are a few distinct “pages” on Tweeteorites. One is the Leaderboard: this is the tweets that have been favorited the most in the last 24 hours by the people we’re tracking. This is a global view, in that it is looking at all tweets the Tweeteorites server has seen.

Then there are the individual views — views limited to one user. For example, if you click on a user picture on the front page, it will take you to that person’s “Favorite Stream” page (example). Other individual views are the “Ego Boost” (who has been favoriting that person’s tweets) and “Should Follow” (a recommendation of who that person should be following based on who their friends are favoriting/following).

For an individual’s Favorite Stream to be built, we need to see what their friends are favoriting. This is pretty easy: we just grab all their friends, then see what their friends favorite. For the Ego Boost, it’s harder. As of this writing, Ashton Kutcher has 2,675,471 followers on Twitter. In order to reasonably expect to find everyone who has favorited one of his tweets, we’d need to scan all 2 million+ of his followers. Our request quota to Twitter is 20,000 requests per hour — hence the problem. We try to be smart by grabbing favorites on a schedule proportionate to the how often a user favorites tweets, but that’s still a whole lot of requests. Plus, we’ve got other requests to make, like updating social networks, etc.

So, our solution is this: we only even attempt to build full “individual” pages (which we call timelines) for users who request it. That is, until we can get some API from Twitter that lets us see all the favorites happening all the time (which would be super awesome).

That’s why the site says that if you want timelines enabled for a user you should ask @tweeteorites, which is our account on Twitter. You can format the message however you like, send us a direct message, or whatever. We may not reply to you, but we will most likely enable timelines for your account.

And, yes, it also means that we get some extra exposure to people who are following you and see you request timelines on Tweeteorites. If that bothers you, DM us or change the formatting of the tweet to start with “@tweeteorites” rather than “Hi”.

So… why was today fun? Today I wrote some software that lets me respond to all of those tweets to @tweeteorites and enable peoples’ timelines. I’ve been working night and day on Tweeteorites for 2 months, and it was nice to respond to so many peoples’ requests individually. The software I wrote was basically a custom Twitter client that lets me see who is messaging @tweeteorites and respond to them with an individualized message and enable their timeline at the same time, saving me a whole lot of work.

Today was also fun because as I worked I had a window open looking at my server logs as people visited the site. It was very rewarding to see so many people visiting the site I’ve spent so much time on recently. I’m especially thankful to those of you who’ve sent me messages saying you like Tweeteorites. I look forward to seeing what everyone thinks as I improve upon it, as there are more interesting things to come!

Posted in Tweeteorites.


Announcing Tweeteorites

Tweeteorites, our Twitter favorites tracker, is now live! This project has been exactly 2 months in the making, and is finally at the point where I think it’s usable.

What is it? If you’re a Twitter user, you know that you can mark individual tweets as favorites. It was always really frustrating to me that I could never see what my friends were “favoriting” though. So, Tweeteorites scans through all of your friends’ tweets, building timelines of what your friends are favoriting.

Another frustration for me was that it was hard to know who to follow on Twitter. So, I built a system that analyzes who you’re following, who your friends are following, and what they’re all favoriting. Then, it recommends the people it thinks you’d be most interested in following. Basically, the people you might get the most enjoyment out of following.

That’s the short description! There’s more exciting stuff coming soon, so I’ve got to get back to work!

Posted in Tweeteorites.

Tagged with , .


Recent Activity and Search Location Changes

I just rolled out a couple of quick changes to Amidst. The first is that your activity now shows up in your “Recent Activity” stream, along with that of your friends. Previously, it had just shown what your friends were doing. This brings things in line with what people have come to expect from services such as Twitter, and adds some context as to when things happened.

The second change is that the default location in the search box is now determined by Google the first time you use it. This is thanks to the handy ClientLocation object provided by the Google AJAX Loader, and should be accurate enough for your first location-centered search to work.

Posted in Amidst.


Oops.. amid.st DNS Mistake

While I was away for the weekend camping, I accidentally let the amid.st domain expire. I really shouldn’t have let this happen, and apologize to everyone who was affected. I renewed the domain today, so once the new domain information propagates everything should be back to normal.

Not only did Amidst go down, but Mappity Quakes didn’t work during the duration of the outage due to being served off of the amid.st domain. I’m sorry for the downtime and am really embarrassed that I let this happen.

Posted in Amidst, Mappity, Products, Status.


Email Invitations and Follow Notifications

Since our soft launch of Amidst, I’ve been busy fixing bugs and adding user-requested features. Starting today, I’ll start blogging the new things we’ve added…

So, to start off, a minor but important feature has been added for inviting your friends via email. The emails are short, to the point, and will only be sent to an email address once.

Also, we now send an email notice when you follow them. Unlike Twitter, however, we only send this follow notification once. This avoids the awkward situation when you un-follow someone for a time, then re-follow them and they get an email which lets them know you haven’t been paying attention to them. We debated a bit between doing things this way or with a “pause” button, ala Merlin Mann’s suggestions. Ultimately, though, we think this is a pretty clean way to do it. It solves the problem without new UI, and prevents the downsides of the re-follow problem. Notifications can be turned off altogether in your settings.

More features are on the way soon!

Posted in Amidst.


(Soft) Launch Day

We pushed Amidst live today, removed the invitation wall, and asked Hacker News for their thoughts on the project. So far, the feedback has been incredibly helpful, and we’re really thankful for the constructive comments from the Hacker News community.

We intended today to be a bit of a soft-launch, to gauge people’s reactions, figure out the pain points, and learn what we needed to tweak, and so far that’s exactly how it’s working out. So, now I’m off to my favorite cafe to work on some of the many, many problems people found. Fun stuff.

Posted in Amidst.