May 16th, 2013
Ever since becoming someone who works from home, one of the things I’ve struggled with is keeping my focus on what I’m doing, and not being distracted by incoming work. I often find myself checking my email, receiving an email from a client who needs something fixed, checked, or investigated, and immediately dropping what I was currently working on to take care of this new demand. There’s certainly something to be said for clearing the decks and getting things out of the way as quick as possible, but it can also be very disruptive, and worse, inefficient.
I recently came across a podcast aimed at people who work from home, aptly named Home Work. I’ve really been enjoying going back over all the old episodes, and there’s some great discussion in there on all aspects of working from home. If you’re a home worker, I really recommend giving it a try, starting at the first episode.
One of the best tips I’ve picked up from Home Work so far is to consciously schedule your work day. The idea is to not only plan out what things you are going to work on that day, but also to put times against them. I’ve been giving this a try for the past few days, and by way of example, this is what my schedule looks like for today:
- 9am – 10am: write blog post
- 10am – 12.30pm: work on promotional material for an app I’m launching soon
- 12.30pm – 1pm: lunch
- 1pm – 3pm: work on bug fixes for a client app
- 3pm – 5pm: continue developing my new app idea
Once 5pm rolls around, I’ll take a look over all my current projects, decide what I’m going to work on tomorrow, and write up a schedule for myself for the next day. This only takes a few minutes, but so far it’s working out wonderfully. I don’t waste time in the morning trying to figure out my plans for that day, and I feel much more relaxed in the evening after finishing work, knowing that everything is on track, and anything that needs to be progressed has been scheduled in. I think the biggest benefit is that one particular project cannot take priority over another. So if I haven’t finished writing my blog post by 10am, I need to shelve it for the next day – 10am is the time to move on to the next project. This way everything moves along, rather than getting left behind.
At some point I think I’ll start scheduling in half an hour or so each day to take care of “stuff”, such as unexpected phone calls, emails, and so on, but so far I haven’t needed it.
And with that, it’s 10am, and time to move on to my next project. If this idea appeals to you, give it a try for a week – it’s made a big difference in my happiness and productivity.
March 20th, 2013
Adding rotation to your app is one of those things that users often expect, but which can really bump up the complexity of development. In most cases autosizing your content works nicely, but it’s not unusual to run into things that just don’t behave quite as you might expect.
I came across one of these recently with a paged UIScrollView. The content was a number of full-screen photos, which allows the user to swipe left and right to change photos. This is a fairly common use of a UIScrollView, and has a nice bang-for-your-buck feeling about it – it’s pretty easy to setup, and results in one of the most natural way to view your photos.
That is, until you enable rotation. The first problem that you’ll likely encounter is that all your pages suddenly overlap each other (or have big spaces between them). This is easily fixed by updating the origin of each page to reflect the new dimensions of the UIScrollView.
The next problem you’ll come across is that the UIScrollView content offset is still in the same position as it was prior to rotation. This usually results in your UIScrollView being stuck between two photos, with only a portion of each photo being visible. If you’re really unlucky, your content offset will be past the new width of the UIScrollView, so that you can’t see anything at all. Either way, as soon as you try to move the content, it will jerk back into the right position for one of the pages (though, not necessarily the right page).

The easiest solution to this is to simply update the content offset once rotation has completed. As long as you know which photo you were viewing before, and what the width of the UIScrollView is, this is easy to do with some simple maths. However, this approach is not as polished as it could be. You still get all the problems mentioned previously, and the only difference is that the UIScrollView jerks into position automatically, rather than when you try and interact with it.
We can do better. The next approach would be to animate changing the content offset. UIViewController exposes a very handy method that lets you know when the rotation is about to occur:
willAnimateRotationToInterfaceOrientation:duration:
So, we simply make a call to change the content offset inside this method:
[self.scrollView setContentOffset:CGPointMake(X,Y) animated:YES];
However, this doesn’t quite work as expected either. As the rotation animation occurs, you can see the edges of the other photos move in and out. You start and end in the right position, but you shouldn’t see any parts of the other photos as the rotation is going on. I’m not entirely sure why this is – possibly because the content offset animation is handled using the animated: parameter, rather than in a block based animation with the same duration as the rotation. A handy trick when using the iOS Simulator is to tap the Shift key three times. This turns on slow motion animations, and make it’s much easier to see what’s really going on.
The next approach might be to manually update the content offset one pixel at a time, in sync with the rotation animation. This sounds like a nasty hack though, and there’s a better way – it just requires a little thinking outside the box.
The trick is to actually remove the current page from the UIScrollView before rotation, add it to the parent UIView, and hide the UIScrollView. Then, once the rotation has completed, update the UIScrollView content offset (not animated), put the page back into the UIScrollView, update all the frames of the UIScrollView to reflect their new positions, and then unhide the UIScrollView. Something like this:
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
self.scrollView.hidden = YES;
//remove the current PageViewController and place it in the parent view
PageViewController* pageViewController = [self.pageViewControllers objectAtIndex:self.currentPageIndex];
CGRect frame = pageViewController.view.frame;
frame.origin = CGPointZero;
frame.size = kScrollViewLandscapeSize;
if(UIInterfaceOrientationIsLandscape(toInterfaceOrientation)) {
frame.size = kScrollViewPortraitSize;
}
pageViewController.view.frame = frame;
[self.view addSubview:pageViewController.view];
//animate the frame change for the pageViewController
[UIView animateWithDuration:duration animations:^{
CGRect frame = pageViewController.view.frame;
if(UIInterfaceOrientationIsLandscape(toInterfaceOrientation) {
frame.size = kScrollViewLandscapeSize;
}
else {
frame.size = kScrollViewPortraitSize;
}
pageViewController.view.frame = frame;
}
completion:^(BOOL finished) {
CGSize scrollViewSize = [self scrollViewSizeForCurrentOrientation];
[self.scrollView setContentSize:CGSizeMake(scrollViewSize.width*self.tips.count, scrollViewSize.height)];
[self.scrollView setContentOffset:CGPointMake(scrollViewSize.width*self.currentPageIndex, 0)];
//put the pageViewController back in the UIScrollView, and update the frames for all the PageViewControllers inside the UIScrollView
[self.scrollView addSubview:pageViewController.view];
[self.pageViewControllers enumerateObjectsUsingBlock:^(PageViewController* pageViewController, NSUInteger idx, BOOL *stop) {
CGRect frame = pageViewController.view.frame;
frame.origin.x = scrollViewSize.width * idx;
pageViewController.view.frame = frame;
}];
self.scrollView.hidden = NO;
}];
}
}
A neat little trick that has the desired effect – smoothly animated rotations that behave just as you’d expect!
March 7th, 2013
I’m pleased to announce that after many months of hard work, the iPad edition of MyMoodTracker is now available. The app feels great on the larger screen, and should allow for some interesting and useful insights into one’s mental health.
For those who are new to MyMoodTracker, it’s focus is on keeping track of how you are feeling throughout the day, and determining what factors have an influence on your mental state. Did I get enough sleep last night? Did I drink too many soft drinks yesterday? Am I on track with my medication? The things that affect your mood are many and varied, and MyMoodTracker helps you identify those patterns and get on the path to feeling good.
If you’re a regular user of the iPhone edition of MyMoodTracker, you’ll be pleased to know that data can easily be synced between the two. Make your entries on your iPhone when you’re out and about, and analyse them later on the big screen of the iPad. There’s also some interesting additions to the iPad version, such as the handy statistics summary.
For more information, please take a look at the MyMoodTracker website, or simply search for MyMoodTracker on the App Store. Alternatively, if you have any feedback or suggestions, I’d love to hear them!





January 17th, 2013
As I don’t own a laptop, I’ve always felt that by using a mouse that I was missing out on some of the nice touch features of OS X. The Magic Trackpad is the obvious solution, but I was never able to get over that sceptical feeling of how well it would work as a mouse replacement. Since I have several Magic Mouses (Magic Mice?) lying around already, when I bought a new iMac recently I decided to get the trackpad instead. I commited to trail it for two weeks, and if I was still finding it difficult at the end of that period, I’d go back to the trusty mouse. Those two weeks are now up, so here’s my verdict.
The first thing I noticed is that the transition was really quite natural. I have used Apple laptops before so it’s not like I’ve never used a trackpad, but I think all those years of performing gestures on iOS devices just made me feel instantly at home with the trackpad. I was fully expecting to spend at least a few days feeling hindered, but the truth is I was up and running at normal speed almost instantly. All I needed was a little messing around in System Preferences to get the cursor speed correct. The gesture demonstrations in the System Prefs are excellent, and really make it clear what gestures are available.
If you’re not too picky, then that’s really it. Developing in Xcode is great, navigating the OS is fun, and everything just works. Even doing the occasional touchups or cuts in Photoshop works just fine, though I’m not sure how well it would be for someone who spends all day designing pretty things.
If you are picky like me, then there’s two things which may bug you. The first is creating IBOutlet connections in Xcode. I love the ability to drag connections that was first introduced in Xcode 4, and would always do this by right-click and dragging. However, I can’t find a way to make this work with the Magic Trackpad. The only way I’ve found to make connections so far is to hold down the Control key, and perform a 3 finger drag. A little cumbersome, but not that big of a deal.
The other issue I came across is not so much of an issue as it is more of a side effect. When dragging things around with a trackpad, you will inevitably sometimes reach the edge of the trackpad before you’ve fully dragged the item to it’s destination. Imagine dragging a file from one side of the screen to another – chances are you reach the edge of the trackpad first unless you’re quick. To combat this, the trackpad gives you a little bit of time to readjust. For example, you can drag a file halfway across the screen, lift your fingers off the trackpad and move them back to the other side, and continue dragging. As long as you’re quick enough, this works great. The problem comes in when testing apps in the iOS Simulator. Often you’ll need to swipe or scroll, and because of the way the drag detection works, once you finish your swipe/scroll the screen sticks there for say a tenth of a second – just long enough for the OS to decide that you’re not trying to continue the gesture. Imagine scrolling a UITableView, and see it stick for just a little bit of a time after you finish scrolling. This really isn’t a big deal, as long as you test on a device and confirm that this stickiness is not just bad code!
So, all in all, I love the Magic Trackpad, and I’m sticking with it. If you decide to give one a try, spend a few minutes familiarising yourself with all the gestures that aren’t possible with the Magic Mouse. There’s quite a few. You also might want to consider installing BetterTouchTool. It gives you a high level of customisation over how your trackpad behaves. Currently I’m only using it to alter Safari’s behaviour when tapping on links – basically if I perform a 3 finger tap, it opens links in the background.
Enjoyed this post? Subscribe via RSS or follow me on Twitter.
June 26th, 2012
Being a freelancer, I’m always on the lookout for things which can help to improve my workflow. One source of productivity tips is the Back To Work podcast with Merlin Mann. For those who don’t know him, Merlin is what I’d call a productivity celebrity. He created 43 Folders, and invented Inbox Zero. You’d think that after 73 episodes of Back To Work, there wouldn’t be much more to talk about. Unfortunately, I’d probably agree! Each episode generally runs for about 90 minutes, and these days only seems to contain 5-10 minutes of what I’d call useful material. So, instead of recommending you go and subscribe, I’m going to detail a few of the things I learned from B2W that have made a big impact on my productivity – and they’re all to do with email.
The first tip is to realise that it’s very unlikely that you work in a job where you need to respond to an email as soon as it arrives. How often are you in a situation where your livelihood depends on you replying to that email instantly? Not very often I’d say. So how long can you leave it? 5 minutes? 30 minutes? 2 hours? Chances are if the sender does require an urgent response, they’re just going to call you up anyway.
Once you’ve realised that checking your email is not all that important, the next thing to do is turn off that badge. You know, that little red badge in your dock which says how many unread emails you have. If you’re anything like me, once you see a red badge you need to care take of it straight away. It’s sits there whispering to you – “hey, unread email over here…hello, pay attention to me”. Not good! Head on in to preferences and get rid of it, and I promise a few days later you won’t miss it at all. Same goes for your iPhone as well – don’t let your email be pushed to your device, set it to manual fetch only.
The next step is to actually quit your email client altogether. I’ve gotten into a bad habit recently of checking my email whenever I’m waiting for something (eg. a build to complete). Naturally there’s one or two emails there waiting to be read, so I read them, and my attention gets pulled away to something else. Instead, try quitting your email client. Then, once you’ve finished a chunk of work, open it back up and take care of your emails all at once. Or if you have enough self control, just stare out the window while you’re waiting for that build to complete. Hands off the mouse!
Depending on how much email you get, you might like to think about Inbox Zero. There’s a few different ways to approach Inbox Zero, but what I like to do is treat my inbox as a bit like a to-do list for the day. If there’s any emails in my inbox, they’re either unread, or they’re emails that I need to care of that day. Once I’ve processed an email (replied to it, stored the attachment, whatever needs to be done), the email gets archived. So at the end of each day, my inbox is empty. The easiest way to get started with Inbox Zero is just to move all your emails to an archive folder – hey presto, Inbox Zero! You can go back and sort those thousands of emails later if you want, but don’t let that task prevent you from starting.
Inbox Zero also works really well with flags. Flags are great for when you want to clear out your inbox, but there’s certain emails you just don’t have time to take care of right now. For example, any personal emails that I might want to look over on the weekend, I flag with a green flag. Any work related emails that I need to follow up on within the next few days I flag with a yellow flag. Any support requests I flag as blue. These emails can then be archived, and I’ll take care of them in a day or two – this is easy to do using a flags smart folder in your email client. So, when I’m dedicating some time to support, I can quickly call up all the emails with a blue flag and get through them.
The last tip I have is to use a different email client for your personal mail. All too often I want to read my email on the weekend, but I get bombarded with work emails – not good for work/personal life balance. This happens in reverse too – when there’s no boss looking over your shoulder it’s all too easy to open up that funny video your friend just sent you. So, find another email client, and use one for personal email, and one for work.
I hope some of these tips were helpful. Email can be a big drain on your productivity, but only if you let it. If you have any others tips, I’d love to hear them!
Enjoyed this post? Think we’re clever? Subscribe via RSS or follow us on Twitter.
May 16th, 2012
I was recently asked by Beginning iOS Development if I would like to take part in an interview, which sounded like fun to me. We discussed a range of things, including marketing, designs, my background, and development life in general. I’m really happy with how it all turned out, so if this sounds like it might be of interest, wander on over and have a read: http://www.beginningiosdev.com/interviews/interview-with-ben-williams-of-aspyre-apps
Enjoyed this post? Think we’re clever? Subscribe via RSS or follow us on Twitter.
May 2nd, 2012
I’ve been calling myself an iOS developer for a bit over 3 years now, and during that time I’ve released quite a number of apps on to the App Store. Some of these have been in-house apps that I’ve developed for myself, and some have been work-for-hire apps that I’ve written as a freelancer. As I’m an independent, the choice of where I spend my time is up to me, but I often find it difficult to know the answer to that choice. This post will explore some of those options.
At one end of the scale, you might spend all of your available time working on your own apps. I’ve been lucky enough to work on some really great contract jobs, but none of these are quite as satisfying as taking your own idea all the way to version 1.0. I’ve also been fortunate enough to have had apps featured on the App Store, not once but several times. There’s plenty of money to be made on the App Store and the dreams of getting inside that Top 100 do sometimes come true. However, it’s a tough market. You need a certain combination of skill, luck and persistence to succeed in the App Store, and there’s a good chance that you’ll spend months on your dream only to find it sells less than a few copies a day. In my mind, throwing all of your weight behind in-house app development is the riskiest, but potentially the most rewarding (both financially and emotionally). I think the key to success is keeping a close eye on the market, and developing a keen interest on the strategy & business side of creating apps, instead of just the coding.
On the other hand, you could spend your time doing freelance work. iOS developers are in huge demand at the moment, and if you’ve got the skills there’s plenty of good projects out there. Apart from the obvious development skills required, you also need a certain element of people skills – you’ll never be a successful freelancer if you don’t know how to make your clients feel at ease. This doesn’t come naturally to most developers, but with a bit of practice everyone can do it. The main difficulty then comes down to finding work. A lot of this is all about making connections, going to conferences, going to local developer meetups, being involved with the community, blogging, and so on. Freelance work can also open you up to working on some very cool projects, especially if it’s with big brands whose apps are bound to get a lot of downloads. This sort of thing also feeds back into itself – the more freelance work you do, the better your portfolio looks, and so the easier it is to get more work.
There often seems to be a bit of an argument over whether you should charge by the hour or quoted amounts for freelance work. I’m a strong believer that quoted amounts are the way to go. Yes, sometimes you lose out and a job takes longer than you estimated. This is a great incentive for learning how to estimate properly, and track your time sufficiently. It also gives you clients peace of mind that their costs will be relatively fixed unless they change the scope. Removing the uncertainty of how much a project is going to cost gives you a big advantage over other freelancers. And of course, for every job where you don’t underestimate, you overestimate – which works out in your favour.
Another option to consider is whether you should keep your costs low, but ask for a percentage of sales in return. If you’re doing freelance work, you’ll hear this proposition a lot. My advice is to steer well clear of it. Unless you are positive that the idea is definite winner, it’s not worth risking your time and money on. Not only will this app be entering a very crowded market, but you’re also relying on the client to create income for you – which all comes down to how good their app really is, and how good they are at marketing and supporting the app. I believe in creating my own destiny rather than relying on others, and so I almost always insist on full payment for the job. If the client believes in the app that strongly, then they should be willing to pay for it to be developed in full.
So, there’s a few different options there, and if you have any others I’d love to hear about them. I’m fortunate enough that I have a few good clients who keep sending work my way, and so I usually let them dictate my time. If a project comes my way, I’ll work on it, and in the down-time I work on my own apps. This provides enough of an income in order to support myself, whilst slowly building up my own portfolio of apps (and passive income). Sometimes this can be a little frustrating as a lot of work will come in all at once, and I’d rather be working on my own apps, but I’m the first to admit that it’s a good problem to have. And until I hit on that winning app which gets all the way to number 1, it’s a necessary one as well.
April 17th, 2012
As far back as I can remember, I’ve wanted a standing desk. There’s plenty of research out there which indicates that sitting in a chair all day isn’t good for you, but this has never really been much of an influence on me. I simply believe that with most things in life, the key is moderation – and sitting for 8-10 hours at my desk, continued by several hours of sitting whilst eating dinner, watching TV or reading, isn’t moderation.
Keeping this in mind, the main feature I wanted in such a desk is that it’s quick and easy to change the height. I like the idea of switching between standing and sitting throughout the day. I believe you are losing a lot of the benefits by using a desk that is intended to stay at one height, even if that height is standing. Similarly, the height needs to be easily adjustable. The more difficult it is to change height, the less likely you are to do so regularly.
I’d always heard good things about GeekDesk, who specialise in height adjustable desks. Unfortunately for me, they never had something that suited my needs – that is, until the GeekDesk Max came along. The Max has a range of 23-49 inches, but most importantly, it has programmable presets. It sounded perfect, so I decided to pull the trigger.
As I live in Australia, I needed to have it shipped internationally, as well as with a different power supply. All this really meant was that a few emails were exchanged to place the order, rather than buying directly on the GeekDesk website. Really, the process was simple. Unfortunately, when my GeekDesk arrived some parts had suffered damage in transit. I still don’t really know how this happened, as the parts were pretty well packaged, and the boxes themselves didn’t seem to have been damaged much. Regardless, the GeekDesk support was very helpful, and although it was annoying having to wait for replacement parts, the issue was handled perfectly. How a company handles things when they go wrong can speak volumes.
Once I had all the parts, it was time for construction! It took me roughly 3 hours from start to finish to put everything together, but if I’m being honest, most people would do it in half the time. It was the weekend and putting things together is part of the fun for me, so I took my time. The instructions are clear, and there’s some nice spots for hiding all the cables away. Once the desk is setup, you’d barely know it was anything but a regular desk.
Changing the height of the desk is super simple. Press the up button, desk goes up. Press the down button, desk goes sideways – just kidding, it goes down. Being able to key in presets though is the real power of the Max model. All I need to do is press the number 1 button, and the desk raises up to the perfect standing height for me. Press number 2, and roughly 20 seconds later I’m all ready for sitting. The operation is very smooth, and much quieter than I would have expected. The desk also has an acceleration/deceleration curve, so it doesn’t stop suddenly when it gets to the pre-programmed height.
If you’re still reading, you’ve probably got the point by now – the Max is a fantastic height adjustable desk. It’s solid, works very smoothly, and it couldn’t be easier to change heights. But what’s it like to actually use?
So far, it’s fantastic. I’ve spent the last 2 days switching between standing and sitting every half hour. The 20 seconds or so that it takes to change the height gives me a good chance to shake out my legs. It’s much easier than I expected to stand for a period of time, and I love being able to just walk in and out of the room as I please. I don’t know why, but it feels so much nicer to walk up to your computer, rather than plonking yourself down in a chair.
I’m quietly confident that I’ll never go back to sitting all day ever again.

March 6th, 2012
iOS 6 is no doubt still a long way from being released, but I think if you’re a serious app developer, it’s time to start giving it some thought. Apple has a tendency to feature apps that show off the platform, so working in some features of a newly released version of iOS is a good strategy for getting your app on the front page of the App Store. I have no inside information, but I think it’s still possible to take an educated guess at some of the things we’ll see in iOS 6. Here they are in particular order.
Siri API
I think this is a feature many of us are hoping for, but it could go either way. Technically Siri is still a beta product – a pretty rare occurrence for Apple. I’d be surprised if they managed to turn around a beta product in 12 months to one that has full third party support. Still, I have no doubt that they’re working on it, and if it doesn’t appear in 2012, there’s a good chance it will in 2013.
Better Cross-App Communication
Let’s face it – Apple’s competitors currently provide better options for cross-app communication. Sure, we have URL Schemes, but both Android and Windows Phone 7 have much better options. Apple is really great at crossing off items from the list of “Things Competitors Do Better”, and I think there’ll be some nice improvements in this area for us to play with in iOS 6.
Share Everywhere
We’ve already seen some hints of this in OS X 10.8, so I think there’s a good chance we’ll see some improved sharing controls in iOS 6. Although the chances are low, I’d love to see some built in Facebook sharing functionality.
Notification Centre Widgets
Historically, I believe Apple has always liked the idea of widgets. Although they never really made it into iOS, they certainly were given some serious thought. Now that we have the weather and stock widgets in Notification Centre, I think it makes total sense to open this up to third parties. You’ll have a set amount of space to work with, and data calls will only be allowed when Notification Centre is activated. Some developers are going to come up with some really nice ways to use this feature. Personally, this is an area that I’m going to concentrate on.
NFC
Although this is more of a hardware feature, the possibilities for neat things you could do with Near Field Communications are endless. If NFC finally does make it into the iPhone hardware this year, I’m expecting it to be fully locked down – no third party integration for us this year (much like Siri is now). Still, it can’t hurt to start thinking about what sort of things we could do if we had some NFC APIs.
Better Location Support
Apple has already started playing in this area in iOS 5. The Reminders app is a classic example, allowing you to set off a reminder when you leave or enter a certain region. I expect we’re going to see some even cooler things in this area in iOS 6, although I can honestly say I have no idea what!
Release Date
I’m betting the release date will be early October – the same time period as iOS 5. This date makes a lot of sense for Apple, as they can hold off announcing iOS 6 until WWDC. What better venue to announce the new features of iOS than at the premier Apple developer conference for the year? I think there’s very little chance Apple will introduce new iPhone hardware at WWDC this year, and this gives developers a few months to get up to speed before the public release later that year. The iPhone 4S is selling ridiculously well – it just doesn’t make sense for Apple to cut it off early. Finally, an October release is just around the corner from Christmas, perfect for a booming quarter.
So that’s everything on my list. What about yours?
February 8th, 2012
I recently needed to figure out how to take a photo with the camera, and then desaturate it. I needed to control the level of desaturation, ranging from completely greyscale, all the way up to the original image. This turned out to be trickier than expected, but in the end the solution was quite simple.
The first useful looking bit of code I found was on StackOverflow. This code was quick and easy to implement, and works nicely, but unfortunately gives no control over the amount of desaturation. It completely converts the image to greyscale.
StackOverflow then produced another promising looking solution. The DesatView seemed exactly what I was after – create the view, assign the image, and set the desaturation level. Unfortunately, even setting the level to 100% seemed to result in purple blotches on my photos. I’m not sure why, but it seemed to be altering the hues somehow, and I didn’t know enough about it (or have the time) to figure out why.
Next, I came across the GLImageProcessing sample code from Apple. This is an OpenGL ES project, which demonstrates how you can alter the brightness, contrast, saturation, hue and sharpness of an image. As you would expect, the sample code works really nicely, and in fact allows you to both saturate and desaturate an image. I don’t have any OpenGL ES skills but it wasn’t too hard to integrate Apple’s code into my project. Unfortunately for some reason I just couldn’t get the saturation working. I had no problem with brightness and contrast, but saturation just wouldn’t work for me. I’m sure I was doing something wrong, but time was against me.
The solution I settled on turned out to be pretty simple, and in fact used the first greyscale method mentioned at the top of this post. The answer is to create two UIImageViews, with one on top of the other. Assign the same UIImage to both, and then convert the bottom UIImageView to greyscale. By then altering the opacity of the top UIImageView, you get a cheap and easy desaturation effect. If you need 40% desaturation, set the alpha value of the top UIImageView to 0.6. Simple.
If you then need to create a UIImage out of the result, this is pretty easy too:
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, self.view.opaque, 0.0);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage* desaturatedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
This creates a UIImage object out of whatever is currently displayed in the UIView object – you can even use this for subviews, if you don’t want to save out your whole UIView.
This turned out to be a good lesson for me. There’s always more than one way to do things, and the simplest solutions are often the best. It may not be the most performant solution, or even the most intuitive, but the main thing is that it solves the problem. The bonus is that it’s quite an elegant way of doing it, as well.