AnyList BlogThe official blog of the AnyList team.http://blog.anylistapp.com/
Wed, 22 Mar 2017 19:21:39 -0700Wed, 22 Mar 2017 19:21:39 -0700Jekyll v2.5.3AnyList is Hiring! Help Us With Customer Service<p><strong>Update (March 22): This position has been filled.</strong></p>
<p>AnyList is hiring! As we grow, we need part-time help to continue providing excellent support to our customers. Hours are flexible and you can work from home, or anywhere with an Internet connection. A full job description is here:</p>
<p><a href="https://anylist.workable.com/jobs/425570">https://anylist.workable.com/jobs/425570</a></p>
<p>If you’re interested, please apply using the link above. If you know someone who would be a good fit, please point them our way!</p>
Fri, 10 Feb 2017 00:00:00 -0800http://blog.anylistapp.com/2017/02/hiring-customer-service
http://blog.anylistapp.com/2017/02/hiring-customer-serviceAnnouncing AnyList For Apple Watch<p>We’re pleased to announce that AnyList is now available for the Apple Watch.</p>
<p><img src="/img/posts/watch-app-lists@2x.png" alt="AnyList for Apple Watch - Lists screen" width="400" height="400" style="margin:auto" /></p>
<p>With AnyList for Apple Watch, you can quickly view your lists right on your wrist.</p>
<p>And now you can do your shopping at the store without ever taking your phone out of your pocket or purse.</p>
<p><img src="/img/posts/watch-app-list@2x.png" alt="AnyList for Apple Watch - List screen" width="240" height="240" style="margin:auto" /></p>
<p>Just tap an item on your watch to cross it off. Crossed off items will remain visible until you drop your wrist. When you raise your wrist again, the crossed off items will be hidden so you can focus on the items remaining in your list.</p>
<p>And of course, changes you make on your watch are automatically synced to your phone and other devices (and vice versa).</p>
<p>If you want quick access to your lists, you can add the AnyList complication to your watch face so that your lists are always just a tap away.</p>
<p><img src="/img/posts/watch-app-complication@2x.png" alt="AnyList for Apple Watch - Complication" width="240" height="240" style="margin:auto" /></p>
<p>AnyList for Apple Watch requires an <a href="https://anylistapp.com/premium">AnyList Complete subscription</a>.</p>
<h2 class="section-heading">Technical Details</h2>
<p>AnyList for Apple Watch runs natively on the watch and has its own independent copy of your lists. This means, you can view your lists and cross off items on your watch, even when your phone isn’t nearby.</p>
<p>If you’re using the app when your watch and phone are connected, changes made on one device will automatically sync in the background to the other device. On the other hand, if your watch and phone are out of range, changes will sync the next time they are connected.</p>
<p>AnyList for Apple Watch requires watchOS 3 as Apple made a number of changes in watchOS 3 that greatly improve the experience of using third party apps.</p>
<p>One major improvement is that recently used apps are kept in memory and launch almost instantly. The best way to ensure an app will launch quickly is to keep it in the <a href="https://support.apple.com/en-us/HT206992">Dock</a> or add its complication to the <a href="https://support.apple.com/en-us/HT205536">watch face</a>.</p>
<p>Another important change in watchOS 3 is that by default the last used app stays open for about 8 minutes after lowering your wrist. In previous versions of watchOS, by default the watch would immediately return to the watch face when lowering your wrist, which would have meant needing to constantly re-launch AnyList while shopping at the store.</p>
<p>watchOS 3 also improved support for background tasks. This means as you make changes to lists on one device, those changes can sync over to your other device in the background so your lists will already be up to date the next time you launch the app on that device.</p>
<h2 class="section-heading">Getting Started</h2>
<p>AnyList for Apple Watch is included in the AnyList v5.5 iOS app update. <a href="http://itunes.apple.com/us/app/id522167641?mt=8">Download it now</a> on the App Store, and <a href="https://www.anylistapp.com/contact">let us know</a> what you think!</p>
Thu, 20 Oct 2016 00:00:00 -0700http://blog.anylistapp.com/2016/10/announcing-anylist-for-apple-watch
http://blog.anylistapp.com/2016/10/announcing-anylist-for-apple-watchA Letter to the AnyList Community About AnyList v5.0<p>We apologize for the frustration and confusion we caused with the recent release of AnyList v5.0.</p>
<p>We appreciate everyone that reached out to us with feedback, and we have just released AnyList v5.1, an app update that addresses the most common concerns with the changes introduced in v5.0.</p>
<p>Our goal for AnyList v5.0 was to add a number of commonly requested features (e.g., bulk editing of items) and also to lay the groundwork for the app’s future. As part of this, we made changes to some of the app’s core interactions, such as introducing a dedicated button for crossing off items. These changes were well-intentioned, but we did not do enough external testing or gather enough feedback before releasing them, and in retrospect, they were ill-advised.</p>
<p>(For a detailed accounting of the changes that we made, why we made them, and why they turned out not to be good ideas, please see <a href="#feature-details">the details</a> that appear after this letter.)</p>
<p>More important than the individual changes themselves is the process by which we made these decisions, and how we intend to avoid causing similar frustrations in the future.</p>
<p>As a company, our foremost goal is to create productive, thoughtful software. When we add functionality to AnyList, or work to address problems with the app, we pride ourselves on exploring lots of concepts and being willing to take some risk. We don’t want to be the kind of company that is afraid to make any significant changes, even if those changes are necessary to improve the app.</p>
<p>At the same time, change for the sake of change is something we want to avoid, and making changes that are jarring or unfamiliar should only happen with very strong justification.</p>
<p>Traditionally, we haven’t done much testing of the app outside of our company. (And our company is just the 2 of us, Jason and Jeff.) One major reason for this is the extra complexity inherent in providing test versions of an app that rely on changes to a server side component. However, in the case of v5.0, the changes in the app were major enough that we should have provided a beta version of the update to a few hundred users to provide us with their feedback. This would have allowed us to discover that the justifications for the changes we made were insufficient without inconveniencing everyone who uses AnyList.</p>
<p>In the future, when making major changes to AnyList’s user experience, we plan to recruit willing volunteers to test beta versions of the app. We really should have done this sooner, but this experience has us highly motivated to make it happen.</p>
<p>We are grateful to have so many people using AnyList who care enough about the app to provide us with thoughtful (and often passionate) feedback. Please continue to let us know what you like and what’s giving you trouble, as we are working on additional app updates.</p>
<p>Thank you for your support.</p>
<p>Sincerely,</p>
<p>Jeff Hunter &amp; Jason Marr, The AnyList Team</p>
<h3 style="padding-top:50px;"><a name="feature-details"></a>Details About the Changes Made in AnyList v5.0</h3>
<p><strong>Crossing Off Items</strong></p>
<p>In AnyList v5.0, we changed the interaction for crossing off items. Rather than tapping on an item to cross it off, we added a button to the right of the item to cross it off. And we changed tapping on an item to bring up the list of edit actions for that item.</p>
<p>There are a couple of reasons we made the change to the way items are crossed off. As the app has grown, performing some kind of edit on items (adding a note or photo, changing the category, assigning a store, etc.) has become more common. This is especially true when people start using the app for different kinds of lists beyond shopping lists, and we think this will be even more true in the future, given the functionality we plan to add to the app.</p>
<p>We also had reports from users that were accidentally crossing off items and our hope was that having a smaller dedicated area for crossing off items would help alleviate that issue without requiring people to change their app settings.</p>
<p>In retrospect, though, making such a dramatic change to this core app interaction for v5.0 was a mistake. Although our motivations for making the change were reasonable, the change did not make the app unequivocally better (e.g. crossing off items for users that hold their phone in their left hand was more difficult) and the benefits were not worth the cost of everyone needing to re-learn how to cross off items.</p>
<p>For AnyList v5.1, we have restored the traditional mechanic of tapping on a list item to cross it off.</p>
<p><strong>The Pencil Icon</strong></p>
<p>We tried a bunch of different options for a ‘cross off’ button in v5.0. Checkmarks and other similar icons didn’t feel quite right, given the way that items get crossed off with a red line. Eventually we settled on a pencil icon drawing a red line, which we thought was nice, since was a pretty direct representation of what happened when the button was tapped.</p>
<p>What we failed to consider, though, was that a pencil icon almost always means “edit” in other contexts. We got tunnel vision from spending so much time working on the v5.0 app update that we thought it wasn’t that big of a deal to re-purpose the pencil icon for our own custom purposes. We’ve heard you loud and clear: using a pencil icon to mean something besides “edit” was confusing.</p>
<p>In AnyList v5.1, we’re back to having items crossed off by simply tapping on them, so the need for a ‘cross off’ icon has been obviated. Furthermore, we’ve decided to fully embrace the true meaning of the pencil icon, and you now tap on a pencil button to edit item details.</p>
<p><strong>Adding List Items</strong></p>
<p>With AnyList v5.0, we wanted to address long standing requests for a way to edit item details while adding an item to a list. Since we had already changed tapping on an item in the list to show item details, we decided to change tapping an autocomplete suggestion’s name to show item details. We then added a button on the right of each autocomplete suggestion to quickly add the suggestion to a list without first editing item details.</p>
<p>We should have realized that this was a bad idea, but we thought it was the right way to go based on the changes we had made to crossing off items. In practice, many people never discovered the button to the right of autocomplete suggestions, and thought that you always had to view the item details screen when adding an item. Also, most of the time you just want to add an item without editing the details, so making that action have a smaller tap target was dumb. (Unlike crossing off items, there are generally no concerns about accidental taps while walking around a store in this case.)</p>
<p>AnyList v5.1 makes tapping the autocomplete suggestion add the item directly, as before. If you want to edit the item before adding it, you can tap the pencil button to the right.</p>
<p><strong>List Name Header</strong></p>
<p>One of the primary goals of v5.0 was to make it easier to switch back and forth between different sections of the app, and to make all parts of the app more discoverable. To accomplish this, we changed the bottom tab bar to always be visible, and adding the meal planning calendar as a tab. As a result, we had to move some list controls from the bottom of the screen to the top, and we needed to find a place to put the the list title and show / hide completed items button.</p>
<p>We ended up deciding to put the list title and show / hide completed button in a header within the list content. It was relatively big, but since it scrolled away, we thought it would be alright. However, we got a lot of feedback pointing out that the list header meant you could see fewer items when opening your lists. In the case of short lists, it meant scrolling when you previously didn’t need to. In addition, putting a commonly used control like the show / hide completed button in a view that scrolls offscreen was also a poor decision.</p>
<p>For AnyList v5.1, we have removed this header. You can now show and hide completed items via the More Actions (…) menu, which is always accessible. If you want to see the list name or item count, it can be seen in the overscroll area above the list content, or you can go back to the main Lists screen.</p>
<p><strong>Store Names</strong></p>
<p>For those using our Stores &amp; Filters feature, v5.0 changed the display of list items to include the assigned store names. We added this feature based on user feedback, but after releasing v5.0 we heard from users that didn’t want this extra information in their list.</p>
<p>For AnyList v5.1, we have added a setting which allows you to turn off the display of store names if you prefer:</p>
<p><a href="http://help.anylistapp.com/articles/show-hide-store-names/">http://help.anylistapp.com/articles/show-hide-store-names/</a></p>
<p><strong>Press &amp; Hold to Reorder Items</strong></p>
<p>Based on long-standing feedback, we added the ability to reorder items using the press &amp; hold gesture. However, a side effect of this was that we could no longer use that gesture for crossing off items.</p>
<p>While press &amp; hold worked pretty well for avoiding accidental cross offs, we still heard from users that would accidentally cross off items with that setting enabled, so we’re thinking of ways we can do better. One possibility would be to offer a different gesture such as a double tap to cross off items.</p>
<p>Another feature we’re thinking about is a dedicated “shopping mode”. In shopping mode, we could hide a lot of the user interface controls that aren’t needed when shopping and we could allow users to choose a custom gesture for crossing off items that would be hard to perform accidentally.</p>
<p>For now, if you notice that you accidentally crossed something off, you can either shake your device to undo the change, or you can add the item back using the Recent Items screen:</p>
<p><a href="http://help.anylistapp.com/articles/recent-items/">http://help.anylistapp.com/articles/recent-items/</a></p>
<p>And if you’re worried that you may have inadvertently crossed something off without realizing it, you can also review your crossed off items just before leaving the store:</p>
<p><a href="http://help.anylistapp.com/articles/show-hide-completed-items/">http://help.anylistapp.com/articles/show-hide-completed-items/</a></p>
<p>While we weren’t able to address this issue in v5.1, we plan to tackle it in an app update.</p>
Thu, 25 Feb 2016 00:00:00 -0800http://blog.anylistapp.com/2016/02/anylist-v5-letter
http://blog.anylistapp.com/2016/02/anylist-v5-letterWhy AnyList Is Not Available For Apple Watch At Launch<p>Many people have been asking us about our plans for Apple Watch, given its imminent release. We decided not to create an Apple Watch app prior to its launch, and would like to explain our reasoning.</p>
<h2 class="section-heading">Design Challenges</h2>
<p>Both Jason and I worked at Apple during the development of the iPad. We remember well the dramatic difference between using a simulated iPad on a Mac and using a real iPad for the first time while sitting on a couch.</p>
<p><img src="/img/posts/steve-ipad.jpg" alt="Steve Jobs Using an iPad" /></p>
<p>Using real hardware in a realistic setting made you keenly aware of the strengths and weaknesses of the iPad, and provided a much better understanding of how to design useful software for the device.</p>
<p>We preordered Apple Watches the instant they were available, and are eager to get a feel for the everyday experience of using the device. This will help us answer critical design questions like these:</p>
<ul>
<li>If you’re walking around a supermarket with a shopping basket in one hand, and trying to tap a small target on a 38mm tall device at the same time, how accurate can you be?</li>
<li>Will it be difficult or unwieldy to scroll a list with dozens of items to the one you want to cross off?</li>
<li>After you cross off an item and lower your wrist to walk around the store, when you raise your wrist to cross off the next item, will your watch still be showing AnyList? Will we need to recommend that you change system settings on your watch so that AnyList will still be visible?</li>
</ul>
<p>The answers to questions like these will help guide us in building a useful and elegant Apple Watch app.</p>
<h2 class="section-heading">Engineering Challenges</h2>
<p>Building high quality software for a hardware platform that you can’t use is very difficult. The behavior of a simulator doesn’t always match the behavior of a real device. Something may perform very well in a simulator on your Mac, but perform horribly on the actual device. The Apple developer forums are filled with posts from developers who have had their Apple Watch apps rejected for performance problems and crashes which they cannot reproduce, since they do not have Apple Watches.</p>
<p>By waiting until we have devices on our wrists, we’ll be better able to ensure a quality experience when using AnyList with Apple Watch.</p>
<h2 class="section-heading">Business Challenges</h2>
<p>It appears that the Apple Watch will be in short supply initially, with ship times currently pushed into June. In the best case, it’s going to take awhile before a significant fraction of our customers have Apple Watches. While the prospect of working on support for a revolutionary new platform is extremely exciting to us, given all of the challenges above, we felt that it was a better use of our time for the last few months to stay focused on improving our core app in ways that have the potential to benefit everyone who is already using AnyList.</p>
<h2 class="section-heading">Can I use Apple Watch with AnyList now?</h2>
<p>Yes, if you’d like to add items to a list. AnyList <a href="http://help.anylistapp.com/articles/reminders-import/">integrates with Siri</a>, and you can use Siri on the Apple Watch.</p>
<h2 class="section-heading">Will an AnyList app be available for Apple Watch in the future?</h2>
<p>Almost certainly. We have watches on preorder and have many ideas for Apple Watch integration. We’ll evaluate those ideas once we have our watches on our wrists. We hope the Apple Watch will be a smashing success and look forward to building a useful and elegant Apple Watch app in the future.</p>
Thu, 23 Apr 2015 00:00:00 -0700http://blog.anylistapp.com/2015/04/why-anylist-is-not-available-for-apple-watch-at-launch
http://blog.anylistapp.com/2015/04/why-anylist-is-not-available-for-apple-watch-at-launchAn Open Letter to Tim Cook Regarding the App Store 70 / 30 Revenue Split<p>Hi Tim:</p>
<p>I’ve got an idea for you. I think it would be a big win for independent developers targeting Apple platforms, and by extension a big win for Apple, if the App Store revenue split used a tiered rate. (Hopefully you agree that a thriving ecosystem of independent developers is an important competitive advantage for Apple.) It would cost Apple some money, but the cost should be relatively low, especially when considering the impact it could have on the vibrancy of Apple’s developer community.</p>
<p>A bit of background: I am the co-founder of AnyList. Our sole product is a highly rated <a href="http://itunes.apple.com/us/app/id522167641?mt=8">shopping list and recipe organization app</a> for iOS. Formerly, I was a software developer at Apple from 2005 - 2010.</p>
<p>Over the past year, several independent developers have written about the revenue generated by their apps on the App Store, including the developers of <a href="http://blog.jaredsinclair.com/post/93118460565/a-candid-look-at-unreads-first-year">Unread</a>, <a href="http://www.marco.org/2015/01/15/overcast-sales-numbers">Overcast</a>, <a href="http://blog.kapeli.com/my-year-in-review-2014">Dash</a>, and <a href="http://blog.desk.pm/2014-yir/">Desk</a>. I think their writings provide a reasonable picture of financial life on the App Store for independent developers. I think it’s safe to say that most independent developers are generating annual revenue in the tens of thousands to low hundreds of thousands of dollars range.</p>
<p>On the other end of the spectrum, common sense dictates that a small number of top grossing apps generate the lion’s share of App Store revenues, and folks like Charles Perry have <a href="http://metakite.com/blog/2015/01/the-shape-of-the-app-store/">conducted analyses</a> that confirm this.</p>
<p>Looking at the numbers reported by independent developers, I think it’s safe to say that Apple’s 30% cut of App Store revenues can have a big impact on their success or failure. For an independent developer, the difference between their gross revenue and their net revenue after Apple’s 30% cut could very well be the difference between being able to work full-time building for the App Store or not. At $100K in net revenues per year, you may be a successful independent developer. At $70K in net revenues per year, your spouse could be telling you to get a day job.</p>
<p>Therefore, please consider changing the App Store 70% / 30% revenue split to a tiered rate, where Apple takes less of the developer’s first revenues. For example, perhaps Apple could take nothing from the first $100K in annual revenue for a developer, and 30% after that. Or maybe Apple could take 10% from the first $100K, 20% from the next $100K, and 30% after that.</p>
<p>This change would be a shot in the arm for Apple’s independent developers, and would allow more people to work full-time on creating software for Apple platforms.</p>
<p>The cost to Apple should be relatively low, I believe. The tier thresholds can be set low enough that all of the top grossing apps in the App Store are still effectively at a 70% / 30% split.</p>
<p>This proposal is self-serving, so feel free to be skeptical, but I truly do think this would be a smart move for Apple.</p>
<p>Best,</p>
<p>Jeff Hunter<br />
Co-Founder, AnyList</p>
Tue, 17 Feb 2015 00:00:00 -0800http://blog.anylistapp.com/2015/02/open-letter-to-tim-cook-regarding-app-store-revenue-split
http://blog.anylistapp.com/2015/02/open-letter-to-tim-cook-regarding-app-store-revenue-splitPorting AnyList from iOS to the Web<p><img src="/img/posts/anylist-webapp.png" alt="AnyList for the Web screenshot" style="margin-left:auto;margin-right:auto;display:block;border:1px solid #ccc;" /></p>
<p>We recently released <a href="https://www.anylistapp.com/web/about">AnyList for the Web</a>, which allows <a href="https://www.anylistapp.com/anylist-complete">AnyList Complete</a> subscribers to view and edit their lists in a web browser on their Mac or PC.</p>
<p>Creating a web version of AnyList is something we’ve wanted to do for a while, as it has been one of our top feature requests. However, we were concerned about the amount of time it would take to rewrite AnyList for a new platform as well as the ongoing effort required to maintain it. As a team of just two people, we must be vigilant about taking on too much at once and spreading ourselves too thin.</p>
<p>Luckily, we found some relatively new technologies that let us get the initial version of AnyList for the Web up and running quickly and that should also minimize the amount of time we need to spend keeping it up to date with the iOS app.</p>
<h2 class="section-heading">oj</h2>
<p>We implemented the web app’s model and sync code using <a href="https://github.com/musictheory/oj">oj</a>, an Objective-C inspired superset of JavaScript that was created by our friend <a href="http://ricciadams.com">Ricci Adams</a> for his <a href="http://www.musictheory.net">musictheory.net</a> website.</p>
<p>Using oj allowed us to write object-oriented JavaScript with Objective-C syntax, including the use of some modern Objective-C features such as @property and @synthesize. The end result is that many of our oj classes are line-for-line equivalent to the corresponding files in our iOS app.</p>
<p>To get an idea of how similar our oj code looks to Objective-C, take a look at this sample from our NavigationController class written in oj. (Note: the <code>@synthesize</code> is only necessary because we wanted to prefix our instance variables with ‘m’ to match the AnyList iOS app.)</p>
<pre><code>@implementation NavigationController : ViewController {
id mToolbar;
}
@property Array viewControllers;
@synthesize viewControllers = mViewControllers;
@property id delegate;
@synthesize delegate = mDelegate;
- (id) initWithRootViewController:(ViewController)rootViewController {
self = [super init];
if (self) {
mViewControllers = [rootViewController];
[self addChildViewController:rootViewController];
[rootViewController didMoveToParentViewController:self];
}
return self;
}
- (void) pushViewController:(ViewController)viewController animated:(Boolean)animated {
var topViewController = [self topViewController];
var delegate = [self delegate];
if ([delegate respondsToSelector:@selector(navigationController:willShowViewController:animated:)]) {
[delegate navigationController:self willShowViewController:viewController animated:animated];
}
[self addChildViewController:viewController];
[viewController didMoveToParentViewController:self];
mViewControllers.push(viewController);
[self _didShowViewController:viewController animated:animated wasPushed:YES];
}
@end
</code></pre>
<p>When Ricci first told us about oj, we were admittedly a bit hesitant about using something that needed to be compiled to JavaScript (at the time, we had been looking into either writing everything ourself or using an MVC JavaScript framework such as <a href="https://angularjs.org">AngularJS</a>, <a href="http://backbonejs.org">Backbone.js</a>, or <a href="http://emberjs.com">Ember.js</a>). However, after experimenting with oj, we quickly realized that we could have large parts of the code for the web app be nearly identical to the code in the iOS app, and the implications of that were hard to ignore.</p>
<p>First, translating our Objective-C code to oj was very straightforward, often involving straight copy/paste and making a few minor tweaks such as replacing NSArrays with native JavaScript arrays. Having such similar code between the two platforms will also be a big win as we continue to maintain the web app. When we make a change in the iOS app, we know that we need to make the same change to the web app and vice versa. In fact, just through the process of porting the iOS code over to the web app, I uncovered a few bugs and ported fixes back to the iOS app.</p>
<p>The biggest benefit of using oj and having such similar code on both platforms is that the web app is now built on code that is already well tested and that we are intimately familiar with. As anyone who has been following <a href="http://inessential.com">Brent Simmons</a> and his series of Vesper Sync Diary posts knows, designing a sync system is an extremely challenging problem. With oj, instead of re-writing our sync code to work within a new framework and having potentially subtle implementation differences between the web app and iOS app, we’re essentially running the same syncing code that has been powering the AnyList iOS app for the last two years.</p>
<h2 class="section-heading">React</h2>
<p>AnyList’s iOS interface is largely composed of UITableViewController subclasses and custom UITableViewCells. For the web, we followed this same basic structure and implemented our own ViewController, TableViewController, and NavigationController classes in oj.</p>
<p>To implement our view objects (e.g. versions of UITableView and UITableViewCell), we used <a href="http://facebook.github.io/react/index.html">React</a>, a JavaScript library from Facebook/Instagram for creating reusable UI components. When writing our React components, we used <a href="http://facebook.github.io/react/docs/jsx-in-depth.html">JSX</a>, a JavaScript XML syntax transform. This allowed us to use HTML-like snippets inside our React component render methods, which makes for very clean and concise code. This is what the render method for our split view looks like using JSX:</p>
<pre><code>var ALSplitView = React.createClass({
render: function() {
return (
&lt;div className="ALSplitView"&gt;
&lt;div className="ALSplitView-MasterContainer"&gt;
{this.props.masterViewBuilder.build()}
&lt;/div&gt;
&lt;div className="ALSplitView-Separator" /&gt;
&lt;div className="ALSplitView-DetailContainer"&gt;
{this.props.detailViewBuilder.build()}
&lt;/div&gt;
&lt;/div&gt;
);
}
});
</code></pre>
<p>Each oj ViewController has a React component associated with it (just like a UIViewController has a UIView associated with it). When a ViewController receives a notification from the model that something has changed, the ViewController simply tells its React component to re-render. Internally, React uses a virtual DOM and with each rendering pass determines what changes need to be made to the real DOM (it does this really, really quickly).</p>
<p>Once we had our base ViewController classes in oj and our UI components in React, we were able to pretty quickly port all of our UITableViewController subclasses over to oj. Often, the oj class needed even less code than its iOS counterpart. For example, the oj TableViewController subclasses did not need a heightForRowAtIndexPath: method.</p>
<p>After the core interface was implemented, we were also able to add some basic animations to the app by taking advantage of React’s <a href="http://facebook.github.io/react/docs/animation.html">CSS animation hooks</a>. For example, we added a sliding animation when pushing/popping views in our navigation controller classes as well as when presenting a modal view controller.</p>
<h2 class="section-heading">Conclusion</h2>
<p>The combination of <a href="https://github.com/musictheory/oj">oj</a> and <a href="http://facebook.github.io/react/index.html">React</a> has worked out really well for us. We were able to make the initial version of <a href="https://www.anylistapp.com/web/about">AnyList for the Web</a> available to our users with just a few months of work and since the code structure is so similar to the iOS app, we expect maintaining it and keeping it up to date with the iOS app to be a relatively easy and straightforward process.</p>
Mon, 21 Apr 2014 00:00:00 -0700http://blog.anylistapp.com/2014/04/porting-anylist-from-ios-to-the-web
http://blog.anylistapp.com/2014/04/porting-anylist-from-ios-to-the-webRampant Abuse of Push Notifications Is Ruining Them For All Developers<p>The abuse of push notifications is spreading across the App Store. As a result, users are starting to reflexively reject app requests to send push notifications.</p>
<p>I always allow apps to send me push notifications, just so I can see what other app developers are doing. Here is a collection of valueless, invasive, and annoying push notifications that I’ve received recently:</p>
<div class="row">
<div class="col-md-6">
<div class="thumbnail">
<img src="/img/posts/key-ring-push.jpg" alt="" />
<p class="caption">It's my lucky day!</p>
</div>
</div>
<div class="col-md-6">
<div class="thumbnail">
<img src="/img/posts/fanhattan-push.jpg" alt="" />
<p class="caption">I have never watched Lost, but this message definitely needs to appear on my lock screen.</p>
</div>
</div>
<div class="col-md-6">
<div class="thumbnail">
<img src="/img/posts/buy-pie-push.jpg" alt="" />
<p class="caption">They must be very proud.</p>
</div>
</div>
<div class="col-md-6">
<div class="thumbnail">
<img src="/img/posts/hero-button-push.jpg" alt="" />
<p class="caption">No!</p>
</div>
</div>
<div class="col-md-6">
<div class="thumbnail">
<img src="/img/posts/draw-something-push.jpg" alt="" />
<p class="caption">Alright, it's a Zynga app, so it's hard to act like I didn't know this kind of junk was coming.</p>
</div>
</div>
<div class="col-md-6">
<div class="thumbnail">
<img src="/img/posts/ziplist-push.jpg" alt="" />
<p class="caption">ZipList sends these every. single. day.</p>
</div>
</div>
</div>
<p>As far as I can tell, many of these notifications are in violation of section 5.6 of the App Store Review Guidelines, although its exact meaning is up for debate:</p>
<blockquote>"5.6&nbsp;&nbsp;Apps cannot use Push Notifications to send advertising, promotions, or direct marketing of any kind"</blockquote>
<p>Compounding the problem is that although there are options to control push notifications on an app by app basis in the iOS Settings app, most non-technical users do not know that these settings exist, or don’t understand the settings if they do happen to stumble across them. Furthermore, there is no way to report spammy notifications or turn notifications off when a notification is received, so for many users, the initial prompt asking for permission to send push notifications is effectively the only shot they’ve got at controlling push notifications. Once they’ve been burned by an abusive app, from there on out, they reject push notifications from all apps.</p>
<p>With AnyList, we strive to use push notifications usefully, so it’s not uncommon for us to receive support requests from people who wonder why the people they are sharing a list with are receiving notifications when a list is modified, but they aren’t. Then we explain to them that they must’ve rejected push notifications when they first used the app, but it’s possible to turn them back on in the Settings app.</p>
<p>I’d like to see Apple make the following changes to push notifications:</p>
<ol>
<li>
<p>Provide a feedback mechanism that allows users to report spammy notifications, and crack down on abusive apps.</p>
</li>
<li>
<p>Provide a quick way to disable push notifications from an app when a push notification from that app is received.</p>
</li>
<li>
<p>Let developers provide a usage description string for the push permission dialog, so they can let the user know exactly why they want to send push notifications. This sort of functionality is already available for the location, calendars, and contacts permission dialogs. (See the documentation for NSLocationUsageDescription, NSCalendarsUsageDescription, and NSContactsUsageDescription.)</p>
</li>
<li>
<p>Allow developers to show the notification settings for an app within the app. I realize that Apple can’t give programatic access to the notification settings, because developers would abuse that, but a way to show a system-provided view controller with the notification settings for my app would be nice. Sticking the notification settings for all apps into a giant list in the iOS Settings app isn’t very discoverable, nor is it very useable when you have many apps installed. When users want to change the behavior of an app, they expect to do it in that app, not in iOS Settings. (This is why the noble experiment that was <a href="http://developer.apple.com/library/ios/#DOCUMENTATION/Cocoa/Conceptual/UserDefaults/Preferences/Preferences.html">iOS Settings Bundles</a> has been a failure, and why very few developers use them anymore.)</p>
</li>
</ol>
Mon, 12 Nov 2012 00:00:00 -0800http://blog.anylistapp.com/2012/11/push-notifications
http://blog.anylistapp.com/2012/11/push-notificationsBeing Featured on the App Store<p>On Thursday May 17th, v1.0 of our new app, AnyList, had been available in the App Store for one week. Our plan with v1.0 was to make sure we’d get through the app review process and get our friends and family to start using the app. We had 215 registered users.</p>
<p>Before telling the press and the world at large about the app, we wanted to wait for v1.0.1 of the app to be approved, since it greatly improved the user experience on first launch. We also felt it was important to fix some architectural performance problems in our server code.</p>
<p>On the afternoon of the 17th, my co-founder Jason and I were sitting around and discussing how to improve our server performance when I suddenly noticed our server logs flying by much faster than usual in an open terminal window. Jason launched iTunes and discovered that AnyList v1.0 was featured on the front page of the App Store as a New and Noteworthy app.</p>
<p><img class="bordered-screenshot" src="/img/posts/anylist-featured-arrow.png" alt="AnyList Featured on the App Store" /></p>
<p>No one from Apple contacted us before, during, or after we were featured, so this was a total surprise. After spending about 15 minutes convincing ourselves that what we were seeing was real and celebrating our good fortune, we realized that we were completely unprepared and we’d better come up with some sort of plan.</p>
<p>The first thing we did was request an expedited review of AnyList v1.0.1. It had already been submitted to the App Store, and since it improved the first launch experience so much, we really wanted all of the new users we’d be getting to have it. For those that haven’t requested an expedited review, when you do it, Apple sends the following auto-reply:</p>
<blockquote>
<p>“We are working hard to process submissions as quickly as we can and expect to complete the evaluation of your request within 1 to 2 business days. If your request is granted, you will be notified and your app will be submitted for an expedited review.”</p>
</blockquote>
<p>Taking up to 2 business days just to evaluate the request didn’t sound particularly expedited to me, but fortunately the request was granted the following day and v1.0.1 was approved in time for us to release on Friday, the 18th.</p>
<p>Meanwhile, our server was getting hammered, with multiple new users signing up every minute. Although the server seemed to be handling the load alright, we weren’t sure when we’d reach the breaking point. If we reached that point and hadn’t fixed our architectural issues, there would be no way to scale the service and our sudden success would likely turn to defeat, with lots of angry users and 1 star reviews in the App Store. So we started working round-the-clock on the architectural issues, since we knew they’d take at least a couple of days to implement and we weren’t sure how much time we had.</p>
<p>I put out a call to the founders from our Y Combinator batch (Summer 2010), letting them know what was happening, and asking if any server experts would be able to help us in an emergency. Almost immediately I got several replies and offers to help. The benefits of YC extend way beyond the weekly dinners and Demo Day.</p>
<p>Interleaved with all of this were periodic checks on our App Store rankings, latest reviews, and responding to a constant stream of incoming user feedback and support requests via email (we make it really easy for our users to contact us within the app). By Sunday the 20th, we were the #1 top free productivity app in the U.S. store (higher than Gmail and Dropbox) and had cracked the top 100 overall free apps.</p>
<p><img class="bordered-screenshot" src="/img/posts/anylist-top-productivity.png" alt="AnyList Top Productivity App" /></p>
<p>Being featured in New and Noteworthy lasts one week, with new selections revealed each Thursday. So we figured that on Thursday the 24th we’d no longer be featured. Fortunately, that wasn’t the case. It turns out that there is another weekly featured section, slightly less prominent, called What’s Hot. I don’t know how the What’s Hot selections are chosen, but it seems like most of the time about 90% of the What’s Hot section consists of apps that were New and Noteworthy the week before. So on the 24th, we moved to What’s Hot and continued to be featured.</p>
<p>Around this time, we completed the architectural changes to our server code, so we could finally sleep a little better, knowing that if we reached a breaking point, we’d be able to scale up.</p>
<p>During our week in New and Noteworthy, we were getting 5,000 - 8,000 new users per day. Moving to What’s Hot cut that approximately in half, as you can see in this graph of our user count during the two weeks we were featured:</p>
<p><img class="bordered-screenshot" src="/img/posts/anylist-user-growth.png" alt="AnyList User Growth" /></p>
<p>By the time we were removed from What’s Hot and no longer prominently featured on the App Store, we had gone from 215 users to over 60,000 users.</p>
<p>This was obviously a dream scenario for us. So, how do you get your app featured in the App Store? The answer is that we honestly don’t know. We’ve had no communication from Apple since we released our app. We have no idea if we’ll ever be featured again. I’m sure luck is a large factor.</p>
<p>That said, I was surprised by how many emails we got from users who told us they had just purchased a new iPhone and AnyList was the first app they had ever downloaded. Given that Apple is selling tens of millions of iOS devices each quarter, and New and Noteworthy apps are what the user sees when launching the App Store for the first time, maybe I shouldn’t have been so surprised. So my best guess at what to focus on if you want to get featured is to build an app that Apple would be happy to have as the first app a new customer ever downloads.</p>
<p>Of course, if anyone out there knows more about how to get featured and wants to provide us with the special direct line to the App Store editorial team, please let us know, privately. :-)</p>
Wed, 22 Aug 2012 00:00:00 -0700http://blog.anylistapp.com/2012/08/app-store
http://blog.anylistapp.com/2012/08/app-store