<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:iweb="http://www.apple.com/iweb" version="2.0">
  <channel>
    <title></title>
    <link>http://www.mentalfaculty.com/mentalfaculty/Blog/Blog.html</link>
    <description> </description>
    <generator>iWeb 3.0.1</generator>
    <item>
      <title>Will the Mac Stick?</title>
      <link>http://www.mentalfaculty.com/mentalfaculty/Blog/Entries/2010/8/22_Will_the_Mac_Stick.html</link>
      <guid isPermaLink="false">45674357-3d48-4c50-9931-154331ed7182</guid>
      <pubDate>Sun, 22 Aug 2010 09:20:59 +0200</pubDate>
      <description>&lt;a href=&quot;http://www.mentalfaculty.com/mentalfaculty/Blog/Entries/2010/8/22_Will_the_Mac_Stick_files/Colloseum.jpg&quot;&gt;&lt;img src=&quot;http://www.mentalfaculty.com/mentalfaculty/Blog/Media/object002_3.jpg&quot; style=&quot;float:left; padding-right:10px; padding-bottom:10px; width:254px; height:135px;&quot;/&gt;&lt;/a&gt;Jalkut’s &lt;a href=&quot;http://www.macworld.com/article/153575/2010/08/jalkut.html&quot;&gt;article&lt;/a&gt; expresses a view I have heard from several Mac developers over the past 6 months or so, that the platform is healthy, and will be viable for app developers for a long time to come. My own view, which was expressed in &lt;a href=&quot;Entries/2010/6/13_On_Mac%28k%29_Trucks_and_the_Ghost_of_Software_Future.html&quot;&gt;this&lt;/a&gt; post, is less optimistic: I think the Mac will stay with us for some time, but will not be viable for developers of consumer software.&lt;br/&gt;&lt;br/&gt;The ‘Underpowered’ iPad&lt;br/&gt;Jalkut makes several arguments in favor of the Mac. One of the main points is that apps on the iPad are not yet as powerful as those on the Mac, and will not be for some time to come:&lt;br/&gt;&lt;br/&gt;But the flip side of simplicity is limitation. Every constraint in the iPad’s design prompts a chorus of “if only I could” from crestfallen users. Customizable hardware, integration among apps, processing power, and—yes— complexity are among the Mac’s strengths. Will the iPad ever catch up? Perhaps. Given many years and countless product iterations, it could happen. But in the meantime, there’s a Mac for all of that.&lt;br/&gt;&lt;br/&gt;I don’t agree with the premise that the iPad must match the Mac feature-for-feature in order to compete. Most users only access a small portion of the functionality that Mac apps offer anyway. They are content with the core features, which are usually readily ported to the iPad. &lt;br/&gt;&lt;br/&gt;A good example of this is Apple’s own &lt;a href=&quot;http://www.apple.com/iwork/&quot;&gt;iWork&lt;/a&gt; suite. The&lt;a href=&quot;http://www.apple.com/ipad/features/keynote.html&quot;&gt; iPad apps&lt;/a&gt; are limited when compared to their Mac counterparts, but they are adequate for 90% of users. When faced with the choice of lugging a powerful but ungainly laptop, or a lightweight but less powerful iPad, many will happily sacrifice more obscure features for ease-of-use.&lt;br/&gt;&lt;br/&gt;The current state of affairs parallels to a certain extent the transition from the command-line interface (CLI) to the graphical user interface (GUI) when the Mac was first introduced. You could argue that in some ways the CLI was more powerful — there are many power users and system administrators who still use it — but it was the ease-of-use of the GUI that won the day. In the same way, mobile touch devices will probably come out on top, with the mouse-based GUI relegated to the realm of professional users and developers.&lt;br/&gt;&lt;br/&gt;(The CLI–GUI migration also provides some insight into the time scale over which this could occur. It took about ten years for the mainstream to move from the CLI to GUI, the time between the introduction of the first Mac [1984] and the introduction of Windows 95 [1995]. I think the transition to touch could move faster, perhaps on the scale of 5 to 10 years.)&lt;br/&gt;&lt;br/&gt;Healthy Mac Sales&lt;br/&gt;Another common argument, also expressed in Jalkut’s piece, is that Mac sales are as healthy as they have ever been, and are still increasing at a rapid rate. While this is certainly true, I don’t think you can read too much into this when making predictions for the longer term. &lt;br/&gt;&lt;br/&gt;To begin with, the iPad is still in its infancy, and there are holes to plug before it will be a viable replacement for a laptop computer. Probably the biggest limitation is that the iPad is still firmly coupled via iTunes to a Mac or PC. As Jalkut correctly points out, the digital hub strategy, which Apple introduced around 10 years ago, is still very much in effect. Your digital assets are stored centrally on a Mac, and transferred to touch devices over USB as needed. &lt;br/&gt;&lt;br/&gt;As long as the Mac plays this role, the iPad is a dependent and cannot seriously compete, but how long will the digital hub remain with us? Cloud computing has become the order of the day, and it is hard to imagine that Apple doesn’t have a strategy which will eventually move all of our data to the cloud. If that happens, the need for your average person to own a Mac or PC will be greatly diminished.&lt;br/&gt;&lt;br/&gt;It is also worth pointing out that you don’t need a Mac per se in order to use an iPad — you can run iTunes on a PC too, and more than half of iPhone/iPad users do exactly that. In other words, the Mac/PC is just a convenient storage device, and not much more than that. Move iTunes to the cloud, and most could do without the desktop hardware.&lt;br/&gt;&lt;br/&gt;The Missing File System&lt;br/&gt;The iPad currently has other limitations too. It is missing essential apps, there is no multitasking, and so on. But these issues are easily remedied, and should become irrelevant in just a few months time. &lt;br/&gt;&lt;br/&gt;One of the more serious limitations is that the iPad has no file system visible to the user, and thus no means of organizing the vast quantities of data most of us now have on our hard drives. Until Apple remedies this, the iPad will not supplant your Mac or PC. &lt;br/&gt;&lt;br/&gt;I suspect Apple’s solution for the iPad will not be a traditional local file system, but will be cloud based. If and when Apple reveals its strategy for cloud computing, it will likely also add features for organizing cloud storage on touch devices. If that happens, the era of the Mac as a central storage hub will come to an end.&lt;br/&gt;&lt;br/&gt;MarsEdit&lt;br/&gt;One reason why Daniel Jalkut’s post is particularly relevant is that he is arguably on the frontline of the battlefield. Red Sweater’s flagship product, &lt;a href=&quot;http://www.red-sweater.com/marsedit/&quot;&gt;MarsEdit&lt;/a&gt;, is the dominant blog editor on the Mac, and it is an app that would fit well on the iPad. There is no iPad version yet, but Jalkut has &lt;a href=&quot;http://www.red-sweater.com/forums/viewtopic.php?id=1353&quot;&gt;hinted&lt;/a&gt; one is in the works.&lt;br/&gt;&lt;br/&gt;If I were Daniel Jalkut, I would make that iPad version an absolute priority. There is no decent blog editor on the iPad yet, but it won’t take long for some to appear. If Red Sweater is too slow with a port, they may lose the advantage that their existing code base affords.&lt;br/&gt;&lt;br/&gt;A similar set of circumstances has arisen in relation to RSS readers. The dominant player on the Mac, &lt;a href=&quot;http://netnewswireapp.com/&quot;&gt;NetNewsWire&lt;/a&gt;, was not given the attention it deserved on the iPhone and iPad (IMHO). The end result is that the touch platforms are now dominated by newcomers like &lt;a href=&quot;http://reederapp.com/&quot;&gt;Reeder&lt;/a&gt;. The risk for the longer term is that if the Mac does see a decline, apps like MarsEdit and NetNewsWire may no longer sustain a business.&lt;br/&gt;&lt;br/&gt;Our approach at The Mental Faculty has been to embrace the new touch platforms, prioritizing them in the short term to ensure that we have a serious foothold going forward. When the iPad was released, we put development of &lt;a href=&quot;http://www.macflashcards.com/&quot;&gt;Mental Case&lt;/a&gt; 2.0 for Mac on hold in order to concentrate on a version for the iPad. We are not giving up on the Mac at all — it still brings in most of our income — but we do think that ultimately the Mac will wane as a consumer device, and having a beachfront on iPad is a top priority.</description>
      <enclosure url="http://www.mentalfaculty.com/mentalfaculty/Blog/Entries/2010/8/22_Will_the_Mac_Stick_files/Colloseum.jpg" length="171060" type="image/jpeg"/>
    </item>
    <item>
      <title>On Mac(k) Trucks and the Ghost of Software Future</title>
      <link>http://www.mentalfaculty.com/mentalfaculty/Blog/Entries/2010/6/13_On_Mac%28k%29_Trucks_and_the_Ghost_of_Software_Future.html</link>
      <guid isPermaLink="false">eab1758c-4802-4e1e-adb3-5014a2bd824e</guid>
      <pubDate>Sun, 13 Jun 2010 10:43:48 +0200</pubDate>
      <description>&lt;a href=&quot;http://www.mentalfaculty.com/mentalfaculty/Blog/Entries/2010/6/13_On_Mac%28k%29_Trucks_and_the_Ghost_of_Software_Future_files/Mack%20Truck%20Comin%27%20Atcha.jpg&quot;&gt;&lt;img src=&quot;http://www.mentalfaculty.com/mentalfaculty/Blog/Media/object001_2.jpg&quot; style=&quot;float:left; padding-right:10px; padding-bottom:10px; width:254px; height:135px;&quot;/&gt;&lt;/a&gt;If you follow me on Twitter (@drewmccormack) you're probably a little sick of my postulations about the future of the Mac. I've been thinking a lot about it lately, trying to decide what it all means for the future of software. Is the Mac still a viable platform to develop for? How long will it stick around? These are the questions that keep me awake at night.&lt;br/&gt;&lt;br/&gt;So here's the evidence all in a row:&lt;br/&gt;	1)	When asked about the future of Macs and PCs at the recent D8 conference, Steve Jobs said they will become like trucks (Mack trucks?), specialized devices used by the few, rather than the many.&lt;br/&gt;	2)	When Apple introduced the iPad, they also introduced iWork, a clear message that the iPad is also intended for content creation. (I'm typing this post on an iPad.)&lt;br/&gt;	3)	Apple introduced iMovie for the iPhone at WWDC. The iPhone now has most of the iLife apps in some form or another. Again, the message is that you can do serious content creation on the touch devices.&lt;br/&gt;	4)	For the first time ever, Apple did not present any design awards for Mac apps at this year's WWDC.&lt;br/&gt;	5)	Last financial quarter — before the iPad was available — only around 15% of Apple devices shipped with Mac OS X installed.&lt;br/&gt;	6)	In the first two months after its release, iPad sold at a rate faster than the Mac.&lt;br/&gt;	7)	The App Store already has many more quality RSS readers for iPad than the Mac ever had.&lt;br/&gt;&lt;br/&gt;The biggest worry for the Mac, in my view, is not lack of revenue or market share, it's lack of consumer software. The missing Mac ADAs were probably not a deliberate snub of Mac developers by Apple, but rather a genuine fear that they wouldn't be able to come up with 5 decent candidates this year.&lt;br/&gt;&lt;br/&gt;Contrast that to the situation on the iPhone, and now the iPad, where any attempt to select a design award winner from the thousands of worthy applicants is bound to end with the words &amp;quot;Eeny meeny miny moe...&amp;quot;.&lt;br/&gt;&lt;br/&gt;How long can the Mac, in its current state, remain a serious option for the consumer? If you ask me, not long. I think we will start to see a serious shift to the iPad over the coming year, simply because when you weigh the availability of quality consumer apps on the iPad against those on the Mac, you would almost have to be crazy to go with the Mac. And the fewer consumers opt for the Mac, the fewer developers will develop software for it, compounding the problem further. This descent could be very fast, perhaps spanning the standard computer upgrade cycle of about three years.&lt;br/&gt;&lt;br/&gt;The Mac may look like a Mack in just a year or two, but it won't die immediately, because there are still many professionals who rely on it, and there are apps that simply don't translate to the iPad. But ask yourself this: Do Apple really want to sustain a whole separate OS and set of development APIs for a product that perhaps accounts for less than 10% of it's hardware sales? Questionable.&lt;br/&gt;&lt;br/&gt;Even if the Mac does survive in its current form, if you are a developer of consumer software like me, I suggest you start working on your Cocoa Touch chops. The Mac will be used by professionals in professional environments, and the market for consumer software will be lean to say the least.&lt;br/&gt;&lt;br/&gt;Apple could do a few things to give the Mac a reprieve ... if that's what they want. They could introduce an App Store for the Mac to encourage development on the platform. In my view, the decline of the Mac that I foresee has more to do with a dearth of consumer software, rather than the more obvious differences in user interaction.&lt;br/&gt;&lt;br/&gt;Another way that the Mac could get a reprieve is if Apple made porting iPad apps to the platform as easy as porting between iPhone and iPad is now. At present, the Mac shares very few APIs with its touch cousins, outside of low-level data handling. If Apple were to integrate UIKit into the Mac in some way, many developers would be tempted to support the platform. This may also provide a gradual transition to the eventual merging of the platforms.</description>
      <enclosure url="http://www.mentalfaculty.com/mentalfaculty/Blog/Entries/2010/6/13_On_Mac%28k%29_Trucks_and_the_Ghost_of_Software_Future_files/Mack%20Truck%20Comin%27%20Atcha.jpg" length="146698" type="image/jpeg"/>
    </item>
    <item>
      <title>Keyed-Archiving to Core Data Migration</title>
      <link>http://www.mentalfaculty.com/mentalfaculty/Blog/Entries/2010/4/17_Keyed-Archiving_to_Core_Data_Migration.html</link>
      <guid isPermaLink="false">a7f73579-343e-4940-8239-7bfbe892ea59</guid>
      <pubDate>Sat, 17 Apr 2010 13:02:14 +0200</pubDate>
      <description>&lt;a href=&quot;http://www.mentalfaculty.com/mentalfaculty/Blog/Entries/2010/4/17_Keyed-Archiving_to_Core_Data_Migration_files/Freebird-1.jpg&quot;&gt;&lt;img src=&quot;http://www.mentalfaculty.com/mentalfaculty/Blog/Media/object028_1.jpg&quot; style=&quot;float:left; padding-right:10px; padding-bottom:10px; width:254px; height:135px;&quot;/&gt;&lt;/a&gt;Core Data (CD) is a technology introduced to the Mac and iPhone in Mac OS X 10.4 and iPhone OS 3.0, respectively. It provides a means for developers to graphically define a data model, and have that mapped behind the scenes to a relational database. Previous to that, developers either had to use a custom technology like SQLite, or Cocoa’s Keyed-Archiving (KA).&lt;br/&gt;&lt;br/&gt;Mental Case for iPhone was originally written to run on iPhone OS 2.0, and it was built on top of KA. More recently, this has become a considerable hindrance, with many users complaining about performance for large libraries. So getting from KA to CD has become an A1 priority.&lt;br/&gt;&lt;br/&gt;Last week we finally took the plunge, and were surprised to find that Apple offered no guidance or sample code for this type of migration, even though it must be very common. Having now almost completed the transition, I thought I would blog the solution we came up with, to save others some trouble.&lt;br/&gt;&lt;br/&gt;There are two main approaches you could take to migrating data from KA to CD. If you don’t mind introducing new classes for your model, you could leave the existing KA classes as they are, read in the whole legacy KA file, and then walk through the object tree, generating your CD objects as appropriate.&lt;br/&gt;&lt;br/&gt;There are a few disadvantages to this approach. Firstly, you will need to make wholesale changes throughout your application, replacing code that uses the old KA classes with code that uses the new CD classes. These changes could be far reaching.&lt;br/&gt;&lt;br/&gt;A second disadvantage is that, in all likelihood, you will have two complete copies of your data in memory during the migration: the original KA object graph, and the CD object graph you are forming. This could be a problem on a low-memory device like the iPhone.&lt;br/&gt;&lt;br/&gt;The other approach, and the one which we settled on, was basically to do the migration in-place. Instead of creating whole new classes, we took the existing NSCoding-compliant classes, and simply made them subclasses of NSManagedObject. The encodeWithCoder: method from NSCoding need never be used again, so you can gut that, but the initWithCoder: method will be used to do the migration.&lt;br/&gt;&lt;br/&gt;@implementation MTModelObject&lt;br/&gt;&lt;br/&gt;@dynamic uniqueId;&lt;br/&gt;&lt;br/&gt;-(id)initWithCoder:(NSCoder *)coder {&lt;br/&gt;	MTManagedObjectContext *context = [MTManagedObjectContext importingModelContext];&lt;br/&gt;	NSEntityDescription *entityDescription = &lt;br/&gt;       [NSEntityDescription entityForName:NSStringFromClass([self class]) &lt;br/&gt;           inManagedObjectContext:context];&lt;br/&gt;    if ( self = [super initWithEntity:entityDescription insertIntoManagedObjectContext:context] ) {&lt;br/&gt;        self.uniqueId = [coder decodeObjectForKey:@&amp;quot;uniqueId&amp;quot;];&lt;br/&gt;    }&lt;br/&gt;    return self;&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;-(void)awakeFromInsert {&lt;br/&gt;	[super awakeFromInsert];&lt;br/&gt;	self.uniqueId = [[NSProcessInfo processInfo] globallyUniqueString];&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;-(void)encodeWithCoder:(NSCoder *)coder {&lt;br/&gt;//    static unsigned classVersionNumber = 1;&lt;br/&gt;//    [coder encodeInt:classVersionNumber forKey:@&amp;quot;modelObjectClassVersion&amp;quot;];&lt;br/&gt;//    [coder encodeObject:self.uniqueId forKey:@&amp;quot;uniqueId&amp;quot;];&lt;br/&gt;//    [coder encodeObject:self.modelContext forKey:@&amp;quot;modelContext&amp;quot;];&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;@end&lt;br/&gt;&lt;br/&gt;You can see in the example above that the contents of encodeWithCoder: have simply been commented out, because it should never be needed again. In a typical initWithCoder: method, you would typically chain to the super’s init method, but here we are instead creating an object in our CD managed object context, with the NSManagedObject initializer initWithEntity:insertIntoManagedObjectContext:. To access the managed object context, we have setup a global importing context. If you want to be neater, you could probably subclass NSKeyedUnarchiver, and add the context to that as an instance variable, so that it gets passed in with the NSCoder argument. But this migration is a once off affair, so it didn’t seem so important to us to make this flexible code.&lt;br/&gt;&lt;br/&gt;After the CD object has been created, you can then decode the data as usual, and set the properties. One thing to be careful of here: it seems the initWithEntity:insertIntoManagedObjectContext: method can return a different object to the one allocated. (That’s why we always assign to self in our initializers, right?) The problem with this is if you try to set a relationship from both sides, you’ll get an exception, because the objects won’t correspond properly. The solution is to just set relationships from one side, and let CD handle the inverse relationships.&lt;br/&gt;&lt;br/&gt;Here’s an example:&lt;br/&gt;&lt;br/&gt;-(id)initWithCoder:(NSCoder *)coder {&lt;br/&gt;	MTManagedObjectContext *context = [MTManagedObjectContext importingModelContext];&lt;br/&gt;	NSEntityDescription *entityDescription = &lt;br/&gt;       [NSEntityDescription entityForName:NSStringFromClass([self class]) &lt;br/&gt;           inManagedObjectContext:context];&lt;br/&gt;    if ( self = [super initWithEntity:entityDescription insertIntoManagedObjectContext:context] ) {&lt;br/&gt;        self.notes = [coder decodeObjectForKey:@&amp;quot;notes&amp;quot;];&lt;br/&gt;&lt;br/&gt;This initializer is from a container class, which stores note objects. We decode and set the notes property here, and in the original KA code, we also set the other side of the relationship — the note’s container — in the initWithCoder: method of the note class. This caused an exception. To fix the problem, we simply removed the line setting the container from the note class, and let CD handle the inverse relationship for us.&lt;br/&gt;&lt;br/&gt;Other things to be aware of are that, as with any use of CD, dealloc methods should generally be rewritten as didTurnIntoFault methods. You might also move some of your initializer code to awakeFromFetch or awakeFromInsert.&lt;br/&gt;&lt;br/&gt;That covers the migration, but it leaves one last piece of the puzzle, and it is a big one: how do you get your new objects to work in your existing application code? Most of our model objects have properties for simple types like float, BOOL, and int. In CD, you work with object types like NSNumber. To address this, we simply gave our CD attributes names like isEditableNumber, which would hold a NSNumber boolean value, and then used wrapper accessor methods to box and unbox the objects. The rest of the code would work with a BOOL property called isEditable, but setting this would effectively box the BOOL into an NSNumber, which would be stored in the object model. By doing this, the changes required in the rest of the app were minimal.</description>
      <enclosure url="http://www.mentalfaculty.com/mentalfaculty/Blog/Entries/2010/4/17_Keyed-Archiving_to_Core_Data_Migration_files/Freebird-1.jpg" length="97942" type="image/jpeg"/>
    </item>
    <item>
      <title>Shopping Lists and Twitter Clients</title>
      <link>http://www.mentalfaculty.com/mentalfaculty/Blog/Entries/2010/3/20_Shopping_Lists_and_Twitter_Clients.html</link>
      <guid isPermaLink="false">2da62db8-a706-4cee-8cd4-aa524e872543</guid>
      <pubDate>Sat, 20 Mar 2010 15:21:12 +0100</pubDate>
      <description>&lt;a href=&quot;http://www.mentalfaculty.com/mentalfaculty/Blog/Entries/2010/3/20_Shopping_Lists_and_Twitter_Clients_files/App-Icon-512-screws.jpg&quot;&gt;&lt;img src=&quot;http://www.mentalfaculty.com/mentalfaculty/Blog/Media/object002_2.jpg&quot; style=&quot;float:left; padding-right:10px; padding-bottom:10px; width:254px; height:135px;&quot;/&gt;&lt;/a&gt;At some point, it seems that every software developer writes their own Twitter client, RSS reader, or Shopping List app. This is probably because everyone uses these sorts of apps, and they never quite work the way you want them to. Needless to say, developing your own is generally a waste of time, and very few of these apps make their way into the wild.&lt;br/&gt;&lt;br/&gt;That's how our latest iPhone app, &lt;a href=&quot;itms://itunes.com/apps/shoppingbuddy&quot;&gt;Shopping Buddy&lt;/a&gt;, got started. Marcello Luppi from &lt;a href=&quot;http://www.wrinklypea.com/&quot;&gt;Wrinkly Pea Design&lt;/a&gt;, the company that does the design for all of our apps, had an itch to scratch. He had tried a bunch of shopping list apps, and none of them worked how he wanted them to. To begin with, all of the apps required you to pull your iPhone out of your pocket every two minutes to check off items, and see what you needed to buy next. When Marcello put it to me that there must be a better way, I had to admit that it annoyed the hell out of me too — I do the weekly grocery shopping in our household.&lt;br/&gt;&lt;br/&gt;Marcello's idea was to have the shopping list sorted according to the route you follow, and then to have the items read to you by the iPhone. You could use the headphone clicker to advance or repeat the latest items.&lt;br/&gt;&lt;br/&gt;Sounded like a good idea to me, except that I soon realized the headphone clicker was off limits to developers outside of Apple, so we needed a different approach. We opted instead to use gestures that you could carry out with the phone still in your pocket. Initially, we tried single and double taps, but the single taps turned out to be too easy to trigger accidentally. (Who would have thought that the denim in your jeans could actually trigger touch events?) We settled on a double tap for repeating the latest item, and a long swipe for moving on to the next items.&lt;br/&gt;&lt;br/&gt;Within a few weeks, I was able to throw together a prototype called 'Sound Shopper'. (At that time, the whole shopping robot concept, which is in the shipping product, had not crystallized.) This prototype worked well enough to start testing for real shopping. We were both happy with the concept, and have been shopping this way for the last few months. (Hint: Do your shopping with just one earbud in — it makes you feel like a secret service agent.)&lt;br/&gt;&lt;br/&gt;Another hurdle we had to overcome while developing the app was how to convert text into speech. Marcello was in favor of recording your own voice for the items in your list, which is an option we supported in the final product, but I was convinced most people are too lazy for that. We needed some Text-to-Speech (TTS) technology, and there was nothing Apple made available for the purpose.&lt;br/&gt;&lt;br/&gt;A bit of searching turned up an open source project called &lt;a href=&quot;http://www.speech.cs.cmu.edu/flite/doc/index.html&quot;&gt;Flite&lt;/a&gt;. Someone even had it working on the iPhone, and had posted &lt;a href=&quot;http://artofsystems.blogspot.com/2009/02/speech-synthesis-on-iphone-with-flite.html&quot;&gt;instructions&lt;/a&gt; on how to do it. I played with it for a couple of hours, got it compiling, but could not get it to make a peep. &lt;br/&gt;&lt;br/&gt;At this point I decided to just buy an iPhone-ready copy of the source code, which was &lt;a href=&quot;http://www.tomsoft.co.uk/iphone/flite.htm&quot;&gt;available&lt;/a&gt; from TOMSOFT for $99. I could have persisted on my own for a few more hours, but at some point you are better off cutting your loses and buying a solution, which worked out great for us. &lt;br/&gt;&lt;br/&gt;Installing Flite wasn't the end of the story though, because Text-to-Speech is an expensive operation to do on slow hardware like the iPhone, and Flite couldn't generate sound in real time. Luckily, with this type of application, it is not really necessary to have real time TTS. To get around the problem, we ship sound files for all of the standard products inside the app, and when someone adds a new item, it is converted to a sound file in the background, before it is needed in the shopping list. In this way, all speech is effectively cached in sound files, and need only be generated once.&lt;br/&gt;&lt;br/&gt;After you have a working prototype, it was just a question of making it beautiful, and improving the UI. This typically takes much longer than you think, sometimes even longer than getting the original app up and running. It took us probably a month or two on and off to complete Shopping Buddy, bolts and all.&lt;br/&gt;&lt;br/&gt;The end result is pretty much what Marcello and I had in mind for 'our' shopping list app. Even if you don't use the sound features, it is still a very good shopping app. We were just as determined that it be easy to add products and generate a new list as we were to include the text-to-speech capability.&lt;br/&gt;&lt;br/&gt;Shopping Buddy is also an experiment in App Store sales models. We are giving the app away free, with an In App Purchase option to upgrade to a Pro version with more functionality (eg multiple stores, recorded and written notes, quick text list). We'll have to wait and see if it works better than a traditional upfront sales model. &lt;br/&gt;&lt;br/&gt;In any case, you may as well &lt;a href=&quot;itms://itunes.com/apps/shoppingbuddy&quot;&gt;get your copy now&lt;/a&gt;. It won't cost a penny, and you can hear for yourself whether you think the talking shopping list has a future.</description>
      <enclosure url="http://www.mentalfaculty.com/mentalfaculty/Blog/Entries/2010/3/20_Shopping_Lists_and_Twitter_Clients_files/App-Icon-512-screws.jpg" length="53429" type="image/jpeg"/>
    </item>
    <item>
      <title>About 100 Days to Get Lost</title>
      <link>http://www.mentalfaculty.com/mentalfaculty/Blog/Entries/2009/12/3_About_100_Days_to_Get_Lost.html</link>
      <guid isPermaLink="false">0241a2d9-08ee-4605-9a1d-217d8282d2d8</guid>
      <pubDate>Thu, 3 Dec 2009 10:15:18 +0100</pubDate>
      <description>&lt;a href=&quot;http://www.mentalfaculty.com/mentalfaculty/Blog/Entries/2009/12/3_About_100_Days_to_Get_Lost_files/Dude,%20I%27m%20Lost..jpg&quot;&gt;&lt;img src=&quot;http://www.mentalfaculty.com/mentalfaculty/Blog/Media/object001_3.jpg&quot; style=&quot;float:left; padding-right:10px; padding-bottom:10px; width:254px; height:135px;&quot;/&gt;&lt;/a&gt;I remember seeing ‘Lost’ for the first time when it first appeared on Dutch TV. I didn’t really get it, and I certainly didn’t get ‘sucked in’. &lt;br/&gt;&lt;br/&gt;It was years later before I took a second look, and got completely hooked. By that time I was three full seasons behind, but with the help of my TV, and three months of evenings, I was up-to-date. It was a great way to watch the series — intensively.  I would sit with my wife, who was just as hooked as I was, and watch 2 or 3 episodes a night. It was probably my favorite ‘TV experience’ ever.&lt;br/&gt;&lt;br/&gt;Series four and five came, and we watched them as they appeared. And now we find ourselves on the eve of the sixth and final series of Lost. It begins in February, 2010.&lt;br/&gt;&lt;br/&gt;To prepare, I’ve gone back to revisit the first and second series. There is a lot going on in Lost, and you pick a lot of interesting snippets up second time round that you missed the first time. I love the way the show continuously folds back on itself.&lt;br/&gt;&lt;br/&gt;If you have never taken the time to watch Lost, now is a great time to start. As the title to this post says, you have about a hundred days, and with something over a hundred episodes in total, you could still be up-to-date when the final series premieres, or at least by the time it completes.&lt;br/&gt;&lt;br/&gt;For those who have never seen it, Lost is a great mix of science fiction, mystery, romance, drama, and cliffhanger endings. It doesn’t matter if you are male or female, there are few that can resist Lost after sitting through a few episodes. &lt;br/&gt;&lt;br/&gt;It’s a series you have to watch in it’s entirety. Unlike shows such as House MD and Desperate Housewives, you can’t really skip a episodes. It’s more like a 100 hour movie than a regular weekly TV program. Watch it all — you won’t regret it.</description>
      <enclosure url="http://www.mentalfaculty.com/mentalfaculty/Blog/Entries/2009/12/3_About_100_Days_to_Get_Lost_files/Dude,%20I%27m%20Lost..jpg" length="143054" type="image/jpeg"/>
    </item>
    <item>
      <title>APP STORE LIMBO</title>
      <link>http://www.mentalfaculty.com/mentalfaculty/Blog/Entries/2009/11/19_APP_STORE_LIMBO.html</link>
      <guid isPermaLink="false">93a3f9fd-3549-49f7-9f79-675e11cc76f5</guid>
      <pubDate>Thu, 19 Nov 2009 08:22:02 +0100</pubDate>
      <description>&lt;a href=&quot;http://www.mentalfaculty.com/mentalfaculty/Blog/Entries/2009/11/19_APP_STORE_LIMBO_files/Shipwreck,%20Beach%20Near%20Lake%20Sijung,%20North%20Korea-1.jpg&quot;&gt;&lt;img src=&quot;http://www.mentalfaculty.com/mentalfaculty/Blog/Media/object002_3.jpg&quot; style=&quot;float:left; padding-right:10px; padding-bottom:10px; width:255px; height:136px;&quot;/&gt;&lt;/a&gt;Mental Case for iPhone has just been rejected from the App Store for using an undocumented method call. Mental Case has been calling the method since it first appeared in the App Store more than a year ago.&lt;br/&gt;&lt;br/&gt;Some of you might find this surprising, but it didn’t come as a surprise to me, because the developer community has been awash with discussion over the last few weeks about a new tool Apple are using — a static analyzer — that helps them locate inappropriate use of their APIs. (I actually wouldn’t be surprised if the tool was actually a dynamic analyzer, perhaps based on &lt;a href=&quot;http://en.wikipedia.org/wiki/DTrace&quot;&gt;DTrace&lt;/a&gt;, but that is another post...)&lt;br/&gt;&lt;br/&gt;Two weeks ago, I fixed some fairly significant bugs in Mental Case, and submitted to the App Store review process. I was hoping my use of the undocumented method didn’t constitute a serious transgression, and that it might slip by. No such luck.&lt;br/&gt;&lt;br/&gt;So what is that private method that is being called? It is a method called setOrientation, and it is used in Mental Case to ensure that if you are studying in landscape mode, the interface turns around to portrait mode when you exit the slideshow.&lt;br/&gt;&lt;br/&gt;The problem now is this: How to proceed? Obviously I have to remove the private call. There are 3 options that I can see, none of which are attractive:&lt;br/&gt;&lt;br/&gt;	1)	Leave the bugs in, and don’t upgrade the app.&lt;br/&gt;	2)	Redo the whole interface so that it works in both landscape and portrait modes.&lt;br/&gt;	3)	Remove landscape mode in study slideshows.&lt;br/&gt;&lt;br/&gt;Obviously, (2) is the best solution, but I don’t have time to tackle it at this point, so it seems (1) is then my best option for the short term. In other words dear user, suck it! Apple have just made you swallow those bugs because I have no means of updating the app in any meaningful way.&lt;br/&gt;&lt;br/&gt;This ‘App Store limbo’ is actually a new phenomenon. We have always had apps waiting endlessly in review queues to make their first appearance in the store, but I don’t think any Apple procedural change has ever cut off existing apps from updates. This change will affect a lot of developers, and — more importantly — users.&lt;br/&gt;&lt;br/&gt;I should clarify that I am not opposed to a ban on calling private methods, which is actually quite reasonable, but I am opposed to the way Apple has handled this. Firstly, the problem is actually not that they can now detect use of private APIs, it was that they couldn’t do it to begin with. If Mental Case was rejected initially for this reason, you would all be happily viewing slideshows right now...in portrait mode.&lt;br/&gt;&lt;br/&gt;Having come up with a means of detecting transgressions of the rule, Apple then began using it with no warning to developers. As a developer, you might expect that an app that was accepted last week would also be accepted this week, and that is no longer the case. &lt;br/&gt;&lt;br/&gt;The very least you might expect in such circumstances is a warning that things are going to change. They must have known a large number of apps would be affected, and yet gave no warning. A hint or warning a few months in advance could have saved everyone a lot of trouble.&lt;br/&gt;&lt;br/&gt;The last few months have seen some &lt;a href=&quot;http://www.macworld.com/article/143847/2009/11/rogueamoeba_appstore.html&quot;&gt;big name&lt;/a&gt; developers leave the iPhone because of the App Store review process. The Mental Faculty is not about to do that, but let’s just say we now prefer developing for the Mac, and that is where our attention is mostly focussed. &lt;br/&gt;&lt;br/&gt;From our perspective, the App Store review process offers no benefit whatsoever for developers, users, or even Apple. Yes, the reviewers occasionally find a genuine bug, but the review process itself prevents bugs they missed from being fixed for weeks or months. I assume Apple persist with this madness because its lawyers are recommending it. In my view, there can be no other sane reason.</description>
      <enclosure url="http://www.mentalfaculty.com/mentalfaculty/Blog/Entries/2009/11/19_APP_STORE_LIMBO_files/Shipwreck,%20Beach%20Near%20Lake%20Sijung,%20North%20Korea-1.jpg" length="170533" type="image/jpeg"/>
    </item>
    <item>
      <title>NSViewController and the Chain of Responsibility</title>
      <link>http://www.mentalfaculty.com/mentalfaculty/Blog/Entries/2009/11/14_NSViewController_and_the_Chain_of_Responsibility.html</link>
      <guid isPermaLink="false">605d2099-bb16-4e58-98dd-9ff7c2e253ac</guid>
      <pubDate>Sat, 14 Nov 2009 13:09:02 +0100</pubDate>
      <description>&lt;a href=&quot;http://www.mentalfaculty.com/mentalfaculty/Blog/Entries/2009/11/14_NSViewController_and_the_Chain_of_Responsibility_files/Theyve%20Chained%20Nature,%20but%20They%20Will%20Never%20Make%20It%20Sing.jpg&quot;&gt;&lt;img src=&quot;http://www.mentalfaculty.com/mentalfaculty/Blog/Media/object000_1.jpg&quot; style=&quot;float:left; padding-right:10px; padding-bottom:10px; width:254px; height:135px;&quot;/&gt;&lt;/a&gt;The last few years have seen a trend in desktop app design to single window interfaces. The iLife apps, including iTunes, all share this approach, and third party developers have followed Apple’s lead. Where windows once contained a single coherent piece of the interface, they now group together multiple panes.&lt;br/&gt;&lt;br/&gt;This is fine from a user perspective, but it does pose a bit of a problem for Cocoa developers. With individual windows containing more and more functionality, the window controllers responsible for keeping them in sync with the model layer have the potential to grow into enormous, unstructured masses of code. Categories can help break things down a bit, but ultimately a more modular approach is needed.&lt;br/&gt;&lt;br/&gt;Apple recognized this, and introduced the NSViewController class in Leopard. An NSViewController is to an NSView what a NSWindowController used to be to a single window. Generally, you wouldn’t have a separate NSViewController for every single view, but each logical grouping (ie pane) would be controlled by a single view controller.&lt;br/&gt;&lt;br/&gt;I’ve been developing Mental Case 2.0 for a few months now, and I can tell you that NSViewController has completely changed the way the app’s source code is ordered. In fact, structurally it is now very similar to the iPhone version of Mental Case, which is perhaps not surprising, because the iPhone is where view controllers first made their appearance.&lt;br/&gt;&lt;br/&gt;This is all well and good, but there is one aspect of NSViewController that Apple left hanging: where does it belong in the Cocoa responder chain? It is a subclass of NSResponder, but there is no automatic support for inserting view controllers into the responder chain. It is not clear why Apple have neglected to address this issue, but it may be that it was thought better to leave this detail to developers, because — as we’ll see — there are several ways to incorporate view controllers into the chain.&lt;br/&gt;&lt;br/&gt;When the class first appeared, Cathy Shive and Jonathan Dann wrote an &lt;a href=&quot;http://katidev.com/blog/2008/04/09/nsviewcontroller-the-new-c-in-mvc-pt-1-of-3/&quot;&gt;excellent series&lt;/a&gt; on view controllers and the responder chain. They considered various designs, and eventually opted for one in which the view controllers would all be patched into the responder chain after the window controller.&lt;br/&gt;&lt;br/&gt;When I first saw this solution, I did a double take, because it seemed like a strange choice. The responder chain generally begins at the most specialized object it can find, and moves to more general, high-level objects. For example, the first responder of a mouse click is the view in which the click occurs. If that view doesn’t handle the event, it is passed to its superview, and so forth, up to the window and then the window controller. To insert the view controllers after the window controller seemed odd to me. I had expected each view controller to come directly after its corresponding view in the chain.&lt;br/&gt;&lt;br/&gt;It turns out Shive and Dann did address this issue in a &lt;a href=&quot;http://katidev.com/blog/2008/07/24/simple-nsviewcontroller-sample-projects/&quot;&gt;separate post&lt;/a&gt;. Their first objection to having each view controller inserted directly after its corresponding view was that there was no way short of subclassing NSView to achieve this. Matt Gallagher has independently &lt;a href=&quot;http://cocoawithlove.com/2008/07/better-integration-for-nsviewcontroller.html&quot;&gt;proposed&lt;/a&gt; exactly this solution — subclassing NSView — but Shive and Dann make a very good point: what if you want to have your view controller control an existing view class such as an NSTableView? Using the subclassing approach, you would end up having to subclass NSTableView itself, or insert your table view in a custom class. Not ideal.&lt;br/&gt;&lt;br/&gt;The second objection made by Shive and Dann to inserting each view controller directly after its view was that if you take the case of menu validation, in order for a view controller to validate a menu item, its view would have to be in the responder chain. In many cases, a view controller may not be in the responder chain and thus not able to validate and handle action messages sent down the chain by menu items.&lt;br/&gt;&lt;br/&gt;This is true for some menu items, but not all. Take a Delete menu item. In this case, it really does matter which view is first responder. If you select an item in the iTunes source list on the left, and select Delete, you expect that item to be deleted, and not an item in the table view on the right. It does make sense to have the view controller follow the view in the chain. Equally, it wouldn’t make sense for a view controller corresponding to the table view on the right to be in the responder chain at all. In the design of Shive and Dann, all view controllers are in every responder chain.&lt;br/&gt;&lt;br/&gt;So what’s the solution? I’ve contemplated quite a bit, and here’s what I have decided to do: each NSView has a reference to its NSViewController, in the same way that an NSWindow has a reference to its NSWindowController. The NSViewController is inserted directly after the NSView in the responder chain.&lt;br/&gt;&lt;br/&gt;Hang on. What about Shive and Dann’s first objection to this approach, namely that it requires subclassing? It turns out that recent changes in the Objective-C runtime mean that you can now add a reference to every NSView without subclassing, simply using a category. Categories do not allow you to add new instance variables, but you can achieve almost the same effect using &lt;a href=&quot;http://angrymuon.squarespace.com/journal/2009/9/6/extending-object-behaviour-in-objective-c-with-associated-re.html&quot;&gt;associated references&lt;/a&gt;.&lt;br/&gt;&lt;br/&gt;I was able to piece together a relatively simple implementation using information from the various blog posts above, and &lt;a href=&quot;http://cocoawithlove.com/2008/03/supersequent-implementation.html&quot;&gt;this&lt;/a&gt; post from the Cocoa with Love blog. You can download the source code &lt;a href=&quot;Entries/2009/11/14_NSViewController_and_the_Chain_of_Responsibility_files/ViewController.zip&quot;&gt;here&lt;/a&gt;. (Warning: This code requires garbage collection.)&lt;br/&gt;&lt;br/&gt;To use this code, drag it into your project, and then simply set the viewController property of any view. I usually do this in the loadView method of the NSViewController itself, though you could also override setView: to do the dirty work. Whichever you choose, it’s dead simple.&lt;br/&gt;&lt;br/&gt;That isn’t the end of the story, of course. This design will allow you to handle mouse and key events associated with a particular view, as well as actions from menu items that apply to a particular view. But it doesn’t handle more general actions.&lt;br/&gt;&lt;br/&gt;My opinion is that these more general actions should be dealt with at a higher level, in the window controller. I store outlets to all of a window controller’s view controllers, so the window controller can just catch an event, and delegate it to a view controller if appropriate. This is perhaps not ideal, but it is simple and direct, and you only need to do it for more general actions.</description>
      <enclosure url="http://www.mentalfaculty.com/mentalfaculty/Blog/Entries/2009/11/14_NSViewController_and_the_Chain_of_Responsibility_files/Theyve%20Chained%20Nature,%20but%20They%20Will%20Never%20Make%20It%20Sing.jpg" length="82826" type="image/jpeg"/>
    </item>
    <item>
      <title>123 Support</title>
      <link>http://www.mentalfaculty.com/mentalfaculty/Blog/Entries/2009/11/8_123_Support.html</link>
      <guid isPermaLink="false">b2b80548-f1e6-413c-89a7-c58e41556f31</guid>
      <pubDate>Sun, 8 Nov 2009 15:31:21 +0100</pubDate>
      <description>&lt;a href=&quot;http://www.mentalfaculty.com/mentalfaculty/Blog/Entries/2009/11/8_123_Support_files/Pillars%20of%20Maymont.jpg&quot;&gt;&lt;img src=&quot;http://www.mentalfaculty.com/mentalfaculty/Blog/Media/object040_1.jpg&quot; style=&quot;float:left; padding-right:10px; padding-bottom:10px; width:254px; height:135px;&quot;/&gt;&lt;/a&gt;I’ve been selling software via internet for quite some time, but only started getting serious about it earlier this year. I finally registered a company, and in May I quit my day job and went indie full time. &lt;br/&gt;&lt;br/&gt;Since then things have been picking up, as they usually do when you start devoting yourself 100% to a venture. With increased sales comes increased user support, and there is no help desk to absorb it — in a one-man shop, you are the help desk.&lt;br/&gt;&lt;br/&gt;Over the last few months I’ve developed a system of sorts to help reduce the time I spend lending support, so I can spend more of it actually developing software. I’ve christened the system ‘123 Support’, and it goes like this...&lt;br/&gt;&lt;br/&gt;	1)	If you receive a support request that you have never had before, ie, it is the first time you have ever seen that type of request, you simply respond with a custom email to the user and try to resolve the issue.&lt;br/&gt;&lt;br/&gt;	1)	If you receive a particular type of support request a second time, you create a template response in order to have that issue automated in future.&lt;br/&gt;&lt;br/&gt;	1)	If you get a particular type of request three or more times, it’s time to consider a UI change. You should think about changes to the design of the app which could alleviate the problem users are experiencing.&lt;br/&gt;&lt;br/&gt;Now these stages are not quite as strict as I make out above: you might have custom responses 5 times before creating an automated response, and after 10 requests consider a UI change. The point is not the exact number of requests, more that there are 3 different stages to consider.&lt;br/&gt;&lt;br/&gt;Let’s consider them in a bit more detail. Custom responses are fine, and inevitable for unique requests, but if you find yourself retyping the same information over and over, it’s time to automate things.&lt;br/&gt;&lt;br/&gt;Automation in this context is a very loose term. It could be that you add information to your FAQ, for example. It could be that you come up with a standard piece of text for an email response. Whatever seems appropriate.&lt;br/&gt;&lt;br/&gt;My approach to automating responses is to use &lt;a href=&quot;http://www.smileonmymac.com/TextExpander/index.html?crcat=gaw&amp;crsource=textexpander&amp;crkw=grp1AdA&amp;gclid=CK6k8NzY-50CFZJ_3godignKow&quot;&gt;TextExpander&lt;/a&gt;. This is a nifty little tool that allows you to create macros which get replaced with boilerplate when you enter them in any text field. I don’t use a fully automated email response system, because that can come across as cold, and not endearing to your customers. Instead I personalize parts of the email, and use TextExpander to add useful information throughout. &lt;br/&gt;&lt;br/&gt;For example, I might enter “Hi Bob” on the keyboard. Then I might enter “ssorry”, which would be expanded by &lt;a href=&quot;http://www.smileonmymac.com/TextExpander/index.html?crcat=gaw&amp;crsource=textexpander&amp;crkw=grp1AdA&amp;gclid=CK6k8NzY-50CFZJ_3godignKow&quot;&gt;TextExpander&lt;/a&gt; into “Sorry to hear you are having trouble with our product”. Then perhaps “bbackup”, which would be expanded to “The best way to backup your library is ...”, and so forth. Lastly, I might enter “kkind”, which TextExpander would turn into “Please contact me if you have any further problems. Kind regards, Drew”. You get the idea.&lt;br/&gt;&lt;br/&gt;This approach is both personal, and saves you an enormous amount of time and typing. I highly recommend giving TextExpander a go.&lt;br/&gt;&lt;br/&gt;The third phase, UI redesign, is more extreme because it may require big changes to your product. It’s not always possible to do in the short term, and you may find yourself relying on step 2 for longer than you would like, but any time you get a lot of questions about a particular piece of functionality, it probably needs a redesign. Perhaps a complete redesign, perhaps only some contextual help or rewording. But somethings gotta change at some point in the future.</description>
      <enclosure url="http://www.mentalfaculty.com/mentalfaculty/Blog/Entries/2009/11/8_123_Support_files/Pillars%20of%20Maymont.jpg" length="310112" type="image/jpeg"/>
    </item>
  </channel>
</rss>
