Archive for Mac OS X

Effects of App Store Distribution pt1

Those of you who follow me here or on Coder Radio or on any of the social networks that I frequent will know that I have been running a little experiment with my new Mac Application Code Journal; for those of you who randomly got here via a search or something like that, the experiment was trying to sell a consumer target Mac OS X application outside of the Mac App Store. No need to go into too much detail, since if you want more info you can go check out episode ten of Coder Radio, but the experiment did yield a result and a lot of feedback. Basically, there is ample evidence to support the idea that, in general, apps that target OS X will do better on the App Store than via direct sales.

As with the mobile space, I believe that increased reliance on app stores will have some considerable effects on the business of app development, the developers, and the apps themselves. So I am writing this three part series to discuss those issues and am taking something of novel approach (novel to me at least): I am going to look at this issues by comparing two very different apps Mars Edit, and my own Code Journal. I picked Mars Edit as a point of comparison because it is established and is in a different space than Code Journal, so there isn’t any risk of bias. Additionally, in many ways Mars Edit can be seen to represent the traditional Mac application model while Code Journal more closely resembles the single purpose “app ideal”.

The eight hundred pound gorilla in the room is app pricing. In general it is becoming increasingly hard to sell an app for more than a few dollars; some would argue that even getting the few dollars at all is really hard. Of course, there are exceptions to this, but those tend to be from either large game companies (think EA, Activision, etc) or from established Mac developers. An example of the latter would Daniel Jalkut’s Mars Edit, an app that is currently selling for $39.99 on the Mac App Store. Mars Edit’s success is a great story but also very atypical of pricing for productivity apps in the store and a lot of that may be due to Jalkut’s and the app’s cache’ in the Mac developer / enthusiast community; again for those who don’t know Jalkut was a former Apple engineer and has been fairly active in the community. Additionally, Mars Edit was successful long before Jalkut took it over; he actually bought the app from another developer in 2007.  A quick survey of competing apps in the same space on the store showed that most of Mars Edit’s competitors tend to be in the ten to fifteen dollar range and seem to have poorer placement in the store, which suggests weaker sales. One notable exception is the $39.99 MacJournal; Yes, there are of course other applications on the store that charge more, such as OmniGroup’s OmniPlan, but  we are looking at its competitors here.

What does this all mean? Honestly, Apple is the only who has the data to be able to truly say if the store if pushing prices down across the board. There certainly seems to be a correlation in applications being priced lower and the rise of the app store model, but there is an alternative argument (with an alternative villain) that could be made: free web apps may be forcing prices of native apps down by training consumers that a large class of applications should be free, such as Google Docs. Again, Apple is really the only who can disprove or prove the first point for sure and the web app debate is something for another day.

Check back soon for a look at what the App Store seems to be doing to independent software developers.

If you have some feedback please find me on Google+ or Twitter. Also, if you like my posts or work on Coder Radio, please consider purchasing Code Journal either from the Mac App Store or direct.

Lessons Learned: Code Journal Early Release

As you may know Code Journal had its early release last week and it has been a pretty good experience so far. I got lots of great feedback from users and have already been able to update the application based on that feedback.  The purpose of this post is to share some of the lessons I have learned and create a discussion around independant software development and distribution. I could enumerate all the nice things that have been e-mailed or otherwise communicated to me re Code Journal, but I believe that there is more to be learned from criticism than praise, therefore, I am going to discuss some of  the application’s critiques.

Critique #1: Mountain Lion Only!?!?
Yup, I heard this one a lot. I decided to develop the application for Mountain Lion, because I thought a few 10.8 specific features were essential and that most of the application’s users would quickly upgrade to the new OS. Turns out that even though Apple reported record adoption of Mountain Lion (OS X 10.8), a large set of Code Journal’s potential users are running older systems: mostly Lion (OS X 10.7). The good news is that despite my miscalculation, I was able to rectify the situation quickly; I have already updated the app to support 10.7+ and I am happy to say that the updated version has been live for several days now.

Critique #2: No Pasting Passwords?
This one caught me a little off guard but really it shouldn’t have looking back. You see I have this odd habit of memorising long passwords, so typing them out is a pretty routine task. Most sane people, however, are using something like LastPass or a similar tool. I am happy to report that I have an update to Code Journal in testing that does allow the pasting in passwords and, unless any issues are found, that version will be pushed live early this coming week.

Critique #3: No App Store Version?
If you are a Coder Radio listener (and you should be), you will know that I am doing something of an experiment with Code Journal. Basically, I have not released it on the Mac App Store intentionally to see how that would affect sales and what (if any) feedback I would get regarding its distrobution. Before I mention what feedback I got I should say that this was the single most common critique of the app. In short, a lot of people have a strong preference to get all of their apps from the Mac App Store and do not want to purchase apps from a website. This is good news for Apple, but bad news for devs; I still hold that there is significant value in having a direct relationship to the users of your apps and the delays caused by Apple review process (22 days for Code Journal’s first binary) can be incredibly damaging if your strategy is to build and iterate rapidly. Assuming that the feedback I received is representative of the greater Mac user ecosystem, it seems that the Mac App Store will soon be the only feasible portal via which to sell apps; barring games that might do well in Steam.

Critique #4: What is Gumroad and Why Isn’t It PayPal?
This is another one that really surprised me, but it seems that there a lot of users who are not really comfortable entering their credit card data into Gumroad. Taking a high level look at my data I have x sales but x * 30 sales have ended right at the checkout screen. Think about that for a minute. The vast majority of people who like the info page enough to click “buy now” got all the way through the checkout process and turned back at the final checkout screen. The data aside, I have heard from several people that they or others close to them were not comfortable with entering the credit cards into Gumroad and would strongly prefer that I switch to PayPal. So why Gumroad at all? Well, they do a lot for me for the same cost as PayPal including verifying receipts, sending app updates to users, and a number of other small things that I would have to implement myself with PayPal. I am still considering how to handle this issue.

Bottom Line
In many ways I feel direct distribution has been incredibly successful, mainly because it allowed me to react quickly to user feature requests (back porting to Lion etc), however, the Mac App Store issue is a troubling one; if the percentage of Mac users who strongly prefer to purchase apps via the Mac App Store continues to grow, developers will have little choice but to conform to the somewhat draconian sand-boxing policies of the Mac App Store. Having said that, I am not against distributing Code Journal via the Mac App Store. In fact, if the numbers continue as they have (numerous users declining to purchase until an a version is on the store), then I probably am not going to have much of choice.

Comments? Questions? Find me on Twitter or Google+.

A Look at Control and the Mac App Store

Much like they have in the mobile space, Apple is leading the charge to commoditize software from independent developers, making it more affordable and convenient for users to purchase and keep up to date. The signs seem to suggest that this has on the whole been a boon for most developers but it has also put an unprecedented amount of control in the hands of Apple regarding what apps Mac developers create and what functionality they can and (more importantly) cannot have. Given that control, Apple has chosen to enforce a few policies that are not in the best interest of Mac developers: they refuse to support paid upgrades for large scale apps, enforce a rather rigid and restricting form of sandboxing, prevent developers from using some of the platforms newest and most interesting APIs on apps that are not distributed via the Mac App Store.

Developing software is difficult, time-consuming, and expensive. Traditionally, developers of large applications have used upgrade pricing schemes to maintain recurring revenues as a way to fund future development of their apps; an extreme example of this would the Adobe suite of tools.  Apple currently does not allow developers to charge for updates. Think about that for a second. Users are going to, as they have been trained to for years, expect  their apps to be kept up to date and, in some cases, provide increased functionality as time goes on. However, the current App Store model forces developers to either betray users’ expectations or somehow finance perpetual development of their apps on whatever one time cost they manage to charge on initial purchase; it should also be noted that apps on the Mac App Store have a tendency to be relatively low cost. Some have suggested that developers could take advantage of the Mac App Store’s in app purchasing APIs to make up the lost revenue. In some cases this might be a serviceable option but falls short of being a full replacement for true update pricing. The issue here is that this limitation discourages the continued development of large scale software for the ecosystem.

Security hasn’t been much of an issue for OS X historically. Despite what Apple fans would tell you, that has nothing to do with any sort of enhanced or inherit security on OS X. The truth is that OS X did not have a sufficient install base to make it an attractive target for malware authors. As Apple has been ever so eager to share, Mac sales are growing rapidly when compared to the overall PC industry. In short, OS X is becoming an increasingly attractive target for malware authors. Apple has responded swiftly to these increased threats in what is probably the most excessive heavy-handed PC security policy to date: sandboxing. If you are reading this, I assume that you already know what sandboxing is, so I won’t bore you by reproducing the definition here. In theory, sandboxing is a good way to make an operating system more secure, but in practice, it is more a restrictive mess than anything else. Basically, sandboxing does not provide enough benefits to be worth the onerous restrictions that it imposes on apps’ functionality.

For us developers, APIs are our windows into the platforms we work on. We depend on those APIs being documented, stable, and consistently available. On those first two counts, Apple has done a tremendous job in recent years. However, with the introduction of Mountain Lion, Apple has restricted a number of its newer and more interesting APIs to applications that are sold on the Mac App Store; if you are interested in what APIs are restricted, there are a number of them, but on the whole, they tend to be the ones that have to do with iCloud or the Notification Center. This is something of a Catch 22 for developers, since users are going to increasingly expect apps to provide the functionality provided by these APIs but may not necessarily want to purchase their apps via the Mac App Store. Once again, we have a case of Apple’s policies forcing developers to run afoul of users’ expectations.

What does this all boil down to? Apple’s recent policies make OS X development a lot more complicated for developers who want to keep up with the operating systems newest APIs but also are unable to comply with the restrictions associated with sandboxing. My take is that if you are developing a powerful application for OS X, odds are that you are going to have sell outside of the Mac App Store, due to sandboxing,  and live in fear of Apple one day using GateKeeper to further restrict the distribution of non-App Store apps. For another take on this, have a look at popular iOS developer Marco Arment’s post on the issue.

I know I have made some pretty strong statements here but I stand by them. If you would like to debate me on these issues or have any other feedback, find me on Google+.

Bad Synchronous Call! Bad!

Back in the dark old days of Commodore 64 and its brethren computers were pretty much all synchronous; instructions executed one after the other, one at a time. It was a simpler time. Users did expect a responsive UI during slow operations or so I have been told. Wondering what a slow operation is? Well, how about any sort of IO? or large data transfer? or how about just pretty much any data transfer over 3G? Of course, there are other cases of long operations but no need to open old wounds….

Now I can hear you already, arguing ‘the platforms today are so much more multi-threaded / multi-core by default I don’t have to worry about writing asynchronous code.’ Well sir (or madam), you are dead wrong. It is true that or more modern platforms have done a lot to run their internal operations in a thread safe / optimized way, but there are a lot of cases where YOU MUST make your code asynchronous. The platform is not going to waive a magic wand and make your operation run asynchronously. Need an example? Here you go:

UIImage* image = [UIImage imageWithData:[NSData dataWithContentsOfURL:someURL]];

Looks reasonable, no? Wrong! That code though deceptively simple is actually very bad. Let’s take a look at what is actually happening in this little one liner:

NSData* imageData = [NSData dataWithContentsOfURL:someURL];
image = [UIImage imageWithData:imageData];

Still pretty simple, right? That’s the exact same functionality as the one linear above and the same problem. Take a closer look at that first line. Pretty simple, right? All it is doing is reading the contents of a URL (in this case an image) downloading the data, and creating an NSData object from it. See the problem yet? That is all happening in order synchronously. If the network is slow or the server is slow to return, the UI on your lovely app will lock for a second or so. Bad UX. Very bad. It is important to note that this code is using one of the most direct ways to create an image from an external service provided wholly by Cocoa. Not to hit this too hard, but the platform vendor’s framework (Cocoa in this case) is not doing anything magical to prevent this from happening. Your code is causing the problem and you have to fix it — yourself.

Oh? You actually want to see a correct version of this code? Well, ok. What needs to happen here is that the image needs to be dealt with asynchronously. I like to use the popular (albeit somewhat dated) iOS / Mac library ASIHTTP to accomplish this. For one request it is really easy:

ASIHTTPRequest* request = [ASIHTTPRequest requestWithURL:someURL];
__weak ASIHTTPRequest* _request = request;
[request setCompletionBlock: ^{
UIImage* image = [UIImage imageWithData:[_request responseData]];
}];
[request setFailedBlock: ^{
// handle failure
}];
[request startAsynchronous];

Not too bad, right? Just a quick walkthrough. If you are new to Cocoa you might not be familiar with the concept of blocks. It’s a pretty big topic and worthy of its own post (or series of posts) but they are similar to closures in other languages. Also, the “__weak” is to prevent a retain cycle for developers using ARC; if you are not using ARC in your new iOS or Mac OS X projects, consider it. Ok so what if you have to deal with a large number of images for something like a UITableView full images? Well check this out:

ASINetworkQueue* q = [[ASINetworkQueue alloc] init];
[q setDelegate:self];
[q setQueueDidFinishSelector:@selector(networkQueueDidFinish:)];
[q setRequestDidFailSelector:@selector(requestDidFail:)];
[q setRequestDidFinishSelector:@selector(requestDidFinish:)];
for (int i = 0; [someArrayOfImagesURLS count]; i++) {
ASIHTTPRequest* imageRequest = [ASIHTTPRequest requestWithURL:[someArrayOfImagesURLS count]];
[q addOperation:imageRequest];
}
[q go];

// delegate methods
- (void) requestDidFail:(ASIHTTPRequest *)request {
// something bad happened -- handle it!
}

- (void) requestDidFinish:(ASIHTTPRequest *)request {
UIImage* image = [UIImage imageWithData:[request responseData]];
// do something with the image
}

- (void) networkQueueDidFinish:(ASINetworkQueue *)q {
// do something magical when the queue is done
}

Ok so all that has changed is that we iterate through an array or URLS for the images, create ASIHTTPRequests based on them, add them to our operation queue, and deal with the delegate methods. One thing of note is that there are separate callbacks for when each individual request finishes and for the queue itself and if you fail to implement one of those required delegate methods your app will crash.

Hope this helps someone. I am going to be posting more about writing asynchronous code to best take advantage of the multi-threaded / multi-core nature of our favorite platforms. Stay tuned for a look at this type of thing on Android! Find me on Google+ or Twitter if you have feedback.


WWDC 2012 Keynote Let Down

Earlier today I hosted Coder Radio with Chris Fisher of Jupiter Broadcasting and in the episode we discussed my reactions as a developer to the WWDC keynote this year (2012). First things first. I did not attend WWDC nor have I installed the iOS 6.0 developer release, so some of my information may be incomplete; I have to do this in this way due to Apple’s developer NDA. You can listen to the show to hear what I didn’t like, but I’d rather go through a few things that I would like to have seen that to my knowledge aren’t coming.

Inter-app Communications
This is by far my largest pet peeve with iOS development and using iOS. Why isn’t there are robust way for apps to work together and share data; within reason of course. Android has a version this in the form of “intents” and Windows Phone 7 has a incredibly powerful system called “contracts”. This really gets to me when I consider that iOS is a BSD system yet does not adhere to the UNIX philosophy of allowing many small applications to work together to do big things; yes, I know that iOS apps tend to be smaller in scope than their desktop counterparts but to date there is no real way for them to work together. There is so much functionality that cannot easily be done on iOS due to this restriction.

Widgets
On my Android and Windows phone I can glance at the screen and get the latest tweets, view other data (such as a stock ticker), and play a song, or begin or pause listening to an audiobook. On iOS, almost all of those things require me to launch separate apps. That’s silly not to mention a bad user experience. I know there are definitely battery life concerns if you have too many widgets open, but there is no reason that Apple can’t add some sort of restricted mode for simple widgets to run in.

Siri integration
Ever since I got my hands on my 4S I have been waiting for a full Siri API. Apple has been working on it, but to date there is no fully functional Siri API for third party developers. This is understandable given how often Siri simply does not work but it is still a shame.

That’s all for now. Now I can finally take a look at the dev preview! For feedback please find me on Google+ or Twitter.

Programming Pitfalls: Bit in the ARC

Apple’s ARC (automatic reference counting) for Mac and iOS devices is intended to make Cocoa development easier. For the most part it does. However, in using it I have encountered a bit of a pitfall: by default the compiler does not optimize your code in debugging but uses its most optimized setting for release.  What does this mean? Well, the more you tell it to optimize your code, the sooner it will release objects for you, which can lead to some issues. To be clear the default settings for each mode are zero optimization and the most possible optimization respectively.

Basically,  a lib I was using was working fine in testing but was throwing BAD_ACCESS errors when running in release mode. After over an hour and half of investigating I found:

The screenshot is showing XCode’s “Build Settings” screen, where you can clearly see that a different level of optimization is being used for the two different modes.

From here the fix is pretty easy: tune down that optimization level. Alternatively, you could dig into the code that is having the issues, but that might turn out to be something of a premature optimization for most needs.

Hope this helps someone. You can find me on Twitter or Google Plus.

AppCode VS XCode

I hate XCode but really want to love it. Most Cocoa developers have had more than a few bad experiences with XCode where it has crashed more than once in a day, magically, lost track of files, failed to warn you of naming conflicts in assets, or simply dead-locked your Mac; if you really want to watch XCode cry do a git checkout with a project open, that tends to bring things to a grinding halt, especially if there is a difference between the project files on each branch. This kind of thing becomes very frustrating as I am sure you are aware.

JetBrains has come to your rescue with their new AppCode. AppCode is an alternative IDE for Mac OS X and iOS development. It does a lot of things a lot better than XCode, but there are also some issues with it that prevent it from being a full replacement for XCode.

On the good side, AppCode offers much more advanced refactoring options than XCode, appears to be much more stable, has more intelligent code completion / suggestion. Like XCode, it allows you launch your App on your Mac, iOS device, or iOS simulator. It integrated with SVN, HG, and Git. I can’t speak to that features as I prefer to use source control  from the terminal; it is also significant that as of XCode 4, Apple has added some Git integration into their offering. Unlike XCode, AppCode has full support for plugins and can even use the full range of plugins from JetBrains’ other products, such as IntelliJ. My favorite feature, other than stability, is Vim emulation; yes, AppCode allows you to use Vim keyboard shortcuts while editing if you prefer to work that way.

Naturally, AppCode is not perfect. In fact the issues with are less bugs and more that the product feels incomplete in a number of significant was. It cannot work with nib (or xib if you prefer) files directly. That’s right if you click a nib in AppCode you’re popped back into XCode. This goes the same for storyboards and CoreData data models.

These limitations prevent AppCode for being a full replacement for XCode. However, AppCode is significantly better for actually writing code and if JetBrains was able to get some sort of integrated Interface Builder functionality and CoreData model editing functionality, then AppCode would be a true alternative to XCode and would be my full time IDE.

Thoughts? Questions or comments? Get in touch on Twitter or Google+.

GDrive Mac Performance Issues.

I am always looking for ways to minimize costs and maximize the effectiveness that I get out of my tools, so it should be no surprise that when Google’s GDrive was announced I jumped all over it. The reasons were clear: I was a heavy Dropbox user and Google offers double the storage for half the price. Overall, I am pretty happy with the service, though there are some quality of life changes Google could make: for instance, it would be nice if I could control how much bandwidth the GDrive client uses at certain times of day; this is something that I have come to love in CrashPlan.

Still, it is likely that Google will add that functionality to the Mac client at some point in the future. There is one thing that they should fix now: Performance.

GDrive takes approximately four to five times as much RAM as Dropbox when idle or syncing. In my limited testing on both a 2012 Mac Mini and 2011 Macbook Pro have Dropbox using around 40MB GDrive uses 200+MB. While syncing Dropbox jumps to the high 50’s and low 60’s on my machines. while GDrive gets pretty close to 250.

I did some poking around and it seems that at least part of the GDrive client is written in Python, rather than C++ or Objective-C. This makes a lot of sense from Google’s perspective, since Python can run on Mac OS X, Linux, and Windows. Also, if you know anything about Google’s love for Python you’d know that most Googlers would write a Python script to make a cup coffee. I a am not suggesting that Python is a bad language, so keep the hate mail to yourself. However, this does feel a bit like a case of write once, suck everywhere.

To be clear, this issue is not enough to get me to quit the GDrive just yet, but it does seem like a little more effort could have been put in here.

Objective-C Singletons

A singleton is a way for developers to keep one and only one object of a class in existence for the entire lifecycle of an application; the nitpicky among you will note that there are portions of an app that might not have any instances of a singleton object, since it is common practice not create the singleton until you need it. Some example cases that you would use a singleton include: a player object for a game, a user object for a social app, and a shopping cart.

Creating a singleton is pretty simple:

@interface User : NSObject
static User* userSingleton;
+ (User *) userSingleton {
  if (!userSingleton) {
    userSingleton = [User alloc] init];
 }
return userSingleton;
}

Let’s walk through this. You declare a static user object called userSingleton, then whenver [User userSingleton] is called you check to see if that object is not null and either returns the existing object or alloc/inits the object, then returns it.

Ok, so that’s all well and good, but how do you actually use it. Well it’s simple. Let’s say our User class has a name property. We could access that with our singleton via:

[[User userSingleton] name];

Need to set the name?

[[User userSingleton] setName:@”Luke”];

Not bad, right? Also, note that all other messages can be sent via the same syntax, so:

[[User userSingleton] someMessage];

For those of you coming from a Java background sending a message in Objective-C would be called calling a method in Java.


Now you may have noticed that the above user object will have null values for all of its properties when it is first created and might want to be able to set some default values. For this example let’s assume that User has a few properties (name, fathersName, and saberColor):

static User* userSingleton;
+ (User *) userSingleton {
  if (!userSingleton) {
    userSingleton = [User alloc] init];
    [userSingleton setName:@”Luke”];
    [userSingleton setFathersName:@”Anakin”];
    [userSingleton setSaberColor:[UIColor blueColor]];
  }
return userSingleton;
}

As you can see, if the object is null, then we create it like before, but now we set some default values to its properties. Naturally, these values will be overwritten when you call their respective setters:

[[User userSingleton] setSaberColor:[UIColor greenColor]];


That’s pretty much all you need to know to get started with singletons in Objective-C. One thing of note about my code samples is that they assume you are using ARC, but you are not they still work; you will just have to include the proper retain/release calls. Hope this helps, please get in touch on Twitter or Google+.

***Update: An eagle-eyed reader pointed out to me that my sample here does not prevent you from creating a new instance of the object. So, if you created the object as I recommend but did User* badUser = [User alloc] init] you would have a new user object.  To get a true singleton (ie only one instance allowed) you would have to override alloc and a few other methods; The eagle-eyed reader recommends you see: http://cocoadev.com/index.pl?SingletonDesignPattern. Also, a few of you have gotten in touch with me asking why I did not show the GCD / block pattern. The reason for that is that I feel that it is too advanced for beginners but will write it up shortly. Thanks for all the feedback.

NSTask 100

I’ll get right to the point here. Reinventing the wheel is bad. Period. End of sentence. If you have a requirement that can be met by an acceptably licensed open-source software project and you are not using that project, then you are likely adding unneeded complexity to you project; you are certainly adding development time and therefore cost to the project.

Recently, I have been spending a lot of time developing an internal Mac OS X application for a client. This is a large scale application that has a lot of very specific requirements; these requirements range for media conversions to data sorting. After spending a little time trying to create my own internal Objective-C classes for many of these functions, I started wishing that I could just call down to OS X’s underlying UNIX utilities.

Then I remember something that I had read in a Cocoa book almost a year ago: NSTask. I popped open Dash and got to reading the documentation on this awesome class. Basically, you can use NSTask to call down to a UNIX utility, pass it parameters as you would from the terminal, and deal with its output.

Let me show you an example of how this would work with one of my favorite GPL’d tools: LAME.

NSTask* lameTask = [[NSTask alloc] init];
[lameTask setLaunchPath@”PATH_TO_LAME”];
[lameTask setArguments:[NSArray arrayWithObjects:@”CRAPPY_AUDIO_FILE.wav”, @”NEW_AWESOMENESS.mp3”, nil]];
[lameTask launch];
<

That’s it. It really is that simple. Keep in mind that for this to work the user needs to have LAME installed on his box already for this to work and distributing GPL’d software with proprietary software can be legally jeopardizing, so read those licenses. Also, MP3 is an IP encumbered format and I am not suggesting that you should violate IP by using the above code; I am only using it as a fun and easy to understand example of using NSTask to call a UNIX tool/

I hope this helps somebody out, if you have any questions or comments, please let me know or comment below.