Skip to: categories | main content
Macs & more
Recently, Mark Wadham dumped his iPhone 4 in favour of an Android-based phone, the HTC Desire S and wrote a blog post about his switching experience.
Overall, he really seems to like his new phone, but he also lists a number of shortcomings compared to the iPhone. I noticed that one particular complaint stood out amongst the others, and Mark tried to play it down a little:
While certainly not bad, the UI clearly wasn’t designed by the UX experts at Apple and I spotted a number of irritating inconsistencies and unintuitive aspects of the ui.
It’s hard to gauge just how much of this is simply me being used to iOS, but there is definitely some room for improvement of the user experience. I think if the UX guys at work tried this phone they would find it quite irritating to use.
To disable [haptic keyboard feedback] I had to turn off two settings in completely different parts of the menu…. yeah, people into UX shouldn’t get this phone
It’s not as fun to use as an iPhone, and if you’re a real UX freak you should probably stick with the iPhone at least for now
Despite the lesser UI experience, I actually like Android, mostly because of the freedom.
[The Android phone is] missing the cleanness of the user experience, consistency in the user interface […]
Overlooking the irony that Mark switched to Android because it's more "open" than iOS, he apparently thinks only "UX freaks" would care about the user experience, which couldn't be more wrong. We are all users, which is why we all care about user experience (except maybe for @evilmattgemmell).
Perhaps only a user experience expert can pinpoint what exactly is distracting or imperfect about a device's user experience, but those shortcomings are certainly going to annoy all users. If your device or software (or any other kind of product really) annoys your users, you have utterly failed in designing something worthwhile. A simple "usable" doesn't cut it.
Today is my last day as an employee at Enough Software and as of tomorrow, I will be independent. Hopefully this means I'll get to spend more time working on iOS and Mac projects of my own, but especially in the early stages of my new-found freedom, I will do a lot of contracting to cover the bills and make enough money to pay for our upcoming wedding (in September) and our honeymoon (January 2012).
Over the years, I got to work on a number of exciting projects (such as S-Banking, which was #1 in the German App Store for quite some time and was even featured in one of Apple's TV commercials in Germany) at Enough Software, and I'll really miss the place and my co-workers. There are a lot of talented and bright people working here (including the best boss in the world), and transitioning from working at an office to working from home won't be easy. I'll also miss downtown Bremen, which is an awesome place to work - everything is so close!
On the other hand, I already have the best co-workers in the world, on Twitter. Fraser Speirs once said that Twitter is like an office for the self-employed, and I couldn't agree more. Before Twitter, it would have been harder for me to take this step. I am pretty certain that I would feel that my fiancé, Maxie, and I were going through this alone and that no-one could possibly relate to what we're doing. With Twitter, I know there are dozens of others who have made the same experience or are doing it right now. When I tweeted about my last day as an employee, I got over 50 people congratulating me and wishing me good luck in my future endeavours in a matter of hours. People were even complaining (jokingly, I hope) that their timeline consisted of nothing but people congratulating me. If this isn't the right place and the right time, what is?
I am really excited about the upcoming changes, but of course, as with any life-altering decisions, I am also a little scared. It might all backfire and I might be looking for a new permanent position in a few months. I am hoping that my skills as an Objective-C developer are sufficient, so this hopefully won't happen. But there are just too many variables in a situation like this and it might not depend solely on my abilities.
I'm already working on a new iPhone app which I'll hopefully be able to tell you more about in a few weeks. I also have just started a contracting gig for a well-known Cocoa developer here in Germany, so my bases for the beginning should be covered. I also have a half-finished update for Folio Case, which needs just a little fine-tuning, localization and beta testing before it's ready to go out. Looks like there won't be a shortage of projects for a while. :-)
In the end, working on my own means that I will enjoy a lot more freedom than I used to have. I will have a say in which projects I will do, and which projects I won't do. If the market stays the way it is, this might mean that I will get to try new things and even have my input on UI and UX valued - which isn't always the case when you're contracting. It means letting go of a steady income, which is something I will have to adjust to, but I am pretty certain that eventually, it will be worth it from a financial perspective - not to mention my personal happiness.
Today is my last day as an employee. Tomorrow, I will be an indie.
ARAnnotatedSliderView, which is my class to manage the UISlider and the bubble that is being conditionally displayed, I have the following method:kARPageScrubberViewKeypathFrame and kARPageScrubberViewKeypathTracking are simple constant NSStrings, @"frame" and @"tracking", respectively. The first property I want to observe is the knob's frame, to be notified of changes in the knob's positioning. The second property I want to observe is the UISlider's tracking property, to be notified when the user starts tracking the knob with his/her finger and when they stop, so I can dismiss the bubble. When one of those notifications kicks in, I react to it using this method:UIScrollViews that show a little bit of the neighbouring pieces of content instead of displaying a single view controller over the whole width of the screen. I think those previews are a really great UI element, since they're much easier to spot than the UIPageControl which usually sits right below the UIScrollView. It shows the user that there is more (or no more) content right next to what they are currently seeing.UIScrollView's pagingEnabled property, you probably know that this is not easily doable. The UIScrollView will stop only at multiples of its frame's width and cannot be configured to stop at shorter intervals. I recently needed to implement a paging-enabled UIScrollView and was trying to replicate this behaviour and found a way to implement these previews.Ever since the inaugural NSConference 2009 ended, I've been looking forward to the next one. I, pretty much like everyone else, had a fantastic time there and really enjoyed Scotty's approach to hosting a conference.
Despite a number of really great and thoughtful presentations at NSConference 2009, the main focus and benefit for me was community. I met so many interesting and smart people there who have helped me become a better Cocoa developer in every regard. NSConference is the kind of event you can benefit from even if you don't think the sessions will bring you much new knowledge.
With this kind of experience from last year's conference, Scotty (@macdevnet) and Tim (@timisted) had a lot of work to do. According to a blog post by Scotty, 85% of the delegates in 2009 signed up for the 2010 conference. That's a huge number and goes to show just how great the conference last year was. The question on my mind was not if this year's conference could live up to our expectations, but more how they would do it.
There were some major changes in this year's conference. The most obvious one was that in addition to the workshops, which took place on Sunday, and the main conference (Monday and Tuesday), there now was an optional iPhone day that could be booked in addition to the main conference or on its own. This day even saw a number of new attendees, most of which did regret not going to the main conference after they experienced NSConference for themselves.
Another major change compared to last year's conference, which took place at the University of Hertfordshire campus in Hatfield, was that all workshop rooms, the main conference room and our hotel rooms were now in the same building. Even the restaurant and bar were there, which made it really easy to get to places and to find people.
A very welcome change were the sponsored soft drinks during the coffee breaks, including Red Bull. Yes, there was free Red Bull. It was awesome.
The venue for this year's event was in a rather remote location in a town called Wokefield Park near Reading, England. It was easily reachable by car, but I took two wrong turns on the way and ended up really close to the edge of the world. A lot of attendees got there by public transport, which wouldn't really have been an option for me, since I was traveling from Stansted Airport. Given my plane landed at 7pm and the train line between Stansted and London isn't currently operating on weekends, it would have taken me at least 5 hours to get there. So instead I chose to rent a car and get used to driving on the wrong side of the road and lots of roundabouts.
Remote location aside, the venue was a great choice for the conference. The rooms were rather nice, they had Nintendo Wiis there (although I didn't have time to play) and they had a number of coffee makers in the hall way, which all provided decent coffee. The instructions to make tea were a little confusing, but fortunately Mike Lee (@bmf) applied his engineering talent to the problem and quickly figured out what they meant.
I did sign up for Matt Gemmell's (@mattgemmell) workshop appropriately titled "The World According to Gemmell", but because of conflicting schedules, I only got to experience about half of it. There was a lot of talk about the iPad, bathroom reading and the opportunity for us developers to create apps for the device or adopt our existing ones. We were sitting in groups and, as a group exercise, got to design an iPad app. Matt graciously provided a number of ideas for groups who couldn't decide what to do. There were also some opportunities to get live feedback from Matt and the rest of the group on problems people were currently facing in their own apps.
As I had to leave rather early, I don't really have any more insight to the end of Matt's workshop and no idea what was discussed in Drew McCormack's (@drewmccormack) workshop at all, but I'm sure others who were there will fill this void.
The main conference keynote was delivered by Mike Lee (of Delicious Library fame), who told us various anecdotes where he could apply his engineering skills to everyday (and rare) situations in his life. While doing that, he disclosed his super secret algorithm for awesomeness and encouraged us to fix problems whenever we encounter them and be the hero. During his session, Mike established the ongoing Matrix theme that we could see throughout the entire conference.
After an encouraging keynote, Jonathan "Wolf" Rentzsch (@rentzsch) took us on a journey through many inner workings of Mac OS X and Objective-C applications. He delivered great insight into static analysis, runtime analysis, code injection and enhancing. He introduced us to various tools and showed how they relate to our jobs as Cocoa developers and did a really great job of not diving in too deep, so even people unfamiliar with the subject and the tools could follow his presentation. Some of the things I took away from this presentation are of a philosophical nature which should prove helpful in my future career.
After this exciting subject, Dave Dribin (@ddribin) gave his talk about clean code, which involved a lot of practical tips and some really controversial theses about various design patterns, such as delegation vs. notifications vs. KVO and the use of singletons. These statements caused a lot of discussion during Q&A and during the whole conference, but Dave had a good answer to every single question that was asked, which for me really made the impression that he had some great points there. I left the session feeling good about the design principles I currently employ and with the intention of adopting even more of the practical tips he presented.
Next on the agenda was Drew McCormack's talk about data presentation, in which he focused mostly on table views (cells vs. views) and the Core Plot framework, which he started and helped develop last year. He presented various actual uses of the framework, which is still in development and pre-1.0. Based on my observation of the talk and what various other developers said during the break, Drew really got some attendees thinking about implementing the framework in their own apps.
The final session for the first day was Marcus Zarra (@mzarra) on Core Animation, which he just recently wrote a book on. His talk was aimed at novices and didn't dive in too deep, but gave a good overview about the topic. He introduced us to implicit and explicit animations, and showed a small demo app that proved how little animation code you actually have to write to get decent animations. Unfortunately, the allotted time for the session didn't allow him to go deeper and teach us about more in-depth procedures.
The first day of the conference came to a close with a delightful banquet, which took place in the same room where we had our sessions. We all got to have some great conversations with like-minded people over wine and a three-course dinner. It moved to the bar once the wine was empty where we continued to have a phenomenal time that caused many of us to go to bed rather late and catch little sleep.
The second day of the main conference was kicked off by Jeff LaMarche (@jeff_lamarche), who was still severely jet-lagged and missing his clothes (he had replacements though) because the airline misplaced it and didn't deliver it until later that day. Jeff told us about some Objective-C language and design features and gave us an overview of runtime features, such as reflection/introspection. He made a point to make it clear that messing with the runtime can be rather dangerous, but he gave some safe-to-use examples of what can be done.
The second session of the day was Andy Finnell's (@macgeek02) in-depth talk on OpenCL using an example app where he modeled the effect of painting with watercolour. He talked about OpenCL devices, contexts, vectors and queues as well as the meaning of OpenCL kernels and various implementation details. Unfortunately, the physics involved in modeling the spread of watercolour on paper are rather extensive, and Andy lost me and several other listeners during that segment. However, he did put up the source code to his sample app, so we can investigate this on our own.
The next two sessions, on source code control by Dave Dribin and code signing by Graham Lee (@iamleeg), filled in for Matt Gemmell, who unfortunately had to leave the conference early for medical reasons. We were relieved to head that he did get better and is fine again now. Dave delivered his talk based on a talk he gave last year for a CocoaHeads group. He referred to version control systems as "Time Machine for your source code" and gave us various reasons on why we should use VCSs. His talk was very fact-based and had a history of source control systems up to current DVCSs such as Git and Mercurial. Graham Lee gave an overview of code signing and cleared up some myths around the topic and concluded with a demo.
Following the lunch break, Aaron Hillegass (@AaronHillegass) of Big Nerd Ranch and Cocoa Programming for Mac OS X fame gave a talk on data persistence. He commented on the change away from direct file system access which we're currently seeing in the "cloud" and on the iPad. He followed it up with rather interesting bits about sync services, algorithms, examples, archiving and DBMS, which lead to notes about Core Data. Aaron had various pros and cons about every persistence solution he talked about, even Core Data, which led to his recently developed open source BNRPersistence framework, which looks very promising and is a lot faster than Core Data in most cases. He mentioned that the framework is still work-in-progress and that the community is welcome to supply patches.
Right before the mysterious Cocoa Rumble, which I am not going to talk about here (you have to see it to believe it), Danny Greg (@dannygreg), Martin Pilkington (@pilky) and I (@arepty) presented Scotty with a few gifts that dozens of Mac developers from around the world contributed to. We have video for it, so I am not going to write everything down. Just see for yourself.
Obviously, this day was followed by a lot of drinks and chatter in the bar, and much like the previous nights, everybody seemed to enjoy themselves and went to bed way too late at night. Unfortunately, this marked the end of the main conference and already saw a good number of developers leaving.
The day saw Mike Lee delivering his keynote titled "Meet the User" to a partially renewed crowd, and Mike does really know and understand the user he wants us to meet. Mike gave some practical real-life examples of bad user experience and showed us how they translate into our domain. He talked about feature creep, unnecessary branding and meaningless version naming schemes. This talk left me excited about the rest of the day and thinking about various incidents where I was guilty of letting slip in some of the user experience issues Mike talked about.
In the day's second session, a better-rested and well-dressed Jeff LaMarche introduced us to OpenGL ES on the iPhone. He talked about differences between OpenGL and OpenGL ES (i.e. direct mode), differences between OpenGL ES 1.1 and 2.0, when to use OpenGL ES, the Cartesian coordinate system and its different uses (y-up vs. z-up). He gave a good overview and some pointers concerning data types and function naming schemes and general performance considerations, such as Thumb optimation for ARM6 and ARM7 CPUs. That's when the talk got a little more into the deep technical stuff, but was still very easy to follow, which I was a novice in terms of OpenGL ES really appreciated. We learned about triangles and the winding rule, viewports, orthographic code and geometry. Shortly before the end of the talk, Jeff also touched the topic of lighting and introduced its different aspects (ambient/diffuse/specular).
Right before the lunch break, we got to hear Marcus Zarra talk about his absolute favourite topic, Core Data. Marcus introduced a framework that he has written called ZSync which allows for easy synchronisation of data between Macs and iPhones. Previously, this wasn't as easy to do due to the lack of Sync Services on the iPhone. The framework is still under development and will be rolled out in 3 phases, leading up to cloud sync at one point. Like BNRPersistence, feedback and contribution by developers is welcome. I could tell from the Q&A that people were genuinely excited about this technology and are looking forward to using it in their own products.
The second-to-last presentation of the day was about developing a game using Core Animation, presented by Drew McCormack who must have been exhausted after his workshop on Sunday and his talk on the first day of the conference. Drew explained how he created the whole game using Core Animation rather than OpenGL ES and why this probably is a bad idea, but worked out for him anyway. He presented various animation inside the game and showed us, based on his source code, how they were implemented. I was really surprised to see how easily many things can be done using Core Animation and a free game programming library (for physics), such as cocos2d.
The conference's final session saw Jeff LaMarche's third appearance, and by now he could hear the beer calling for him all the way from the bar. Ignoring those calls, Jeff gave us a good overview of GameKit and quite a bit of example code and even provided some methods for working around GameKit's lack of an online play API, for which we still have to use low-level CFNetwork ourselves. He provides sample code for his implementation, but it's not a large-scale open source library like BNRPersistence or ZSync.
As an iPhone developer, especially the final 2 sessions made an impression with me, mostly because they covered APIs which I hadn't yet used. However, they got me really excited about writing a Core-Animation-based game using GameKit for local multiplayer. In combination with the upcoming iPad, I think there's an opportunity around the corner which I may have to explore.
NSConference 2010 in the UK was a great conference and even managed to be better than last year's conference. I felt the focus of the talks was a little different, with lots of frameworks being introduced and discussed. However, almost one week later, I still don't see any of it as advertising. I rather regret not having had the time to have used any of the great technologies introduced by these talented developers.
I took a lot of practical advise from the conference, but also various general tips and tricks about user experience and life as an engineer. Maybe that's because of all the smoke breaks with Mike Lee, but it certainly helped my thought process in so many ways.
In general, it showed once more that NSConference's focus is community. One thing I constantly heard from various random attendees is that it is so much easier to get in contact with people at NSConference compared to other conferences. And this is one thing I wouldn't want to miss for the world.
Thanks to Scotty, Tim, Dave and everyone else involved for putting together such a great conference for us to enjoy and get together.
I took some pictured during the event and a selection of those is available on Flickr: http://www.flickr.com/photos/alexrepty/sets/72157623253034969/
UIView's +beginAnimations:context: method, I decided to quickly search the web for some information on how other developers approached this problem.UIWindow to find the one containing an instance of UIKeyboard, a private class that isn't even documented in the iPhone SDK. Those hacks then proceeded to modify the dimensions of the view that contains the keyboard and adding the UIToolbar instance as a subview, so it would animate into the key window right along with the keyboard.NSOperation objects, feed them to an NSOperationQueue and get the results fed back to the caller via delegation.initWithContentsOfURL: (or similar)? The main reason here is asynchronous networking. If you're going to just fetch network data, such as strings, images or whole XML documents from remote servers, you are going to see some latency, especially if you're developing for the iPhone and running on an EDGE or 3G network.NSOperation and NSOperationQueue a while back (in Mac OS X 10.5 Leopard).NSOperation and override the -main method to do your bidding. This is where the heavy lifting should take place and all your network latency will not matter anymore. I have written a sample application that uses an NSOperation subclass to fetch an image via HTTP and return it to the controller using a delegate protocol that I have written specifically for this task. My -main method look like this:
- (void)main {
NSImage *image = nil;
NSError *error = nil;
NS_DURING
if ([self isCancelled]) {
NS_VOIDRETURN;
}
NSData *data = [NSData dataWithContentsOfURL:_url options:NSDataReadingUncached error:&error];
if (nil != error) {
[(NSObject *)_delegate performSelectorOnMainThread:@selector(errorOccurred:) withObject:error waitUntilDone:NO];
NS_VOIDRETURN;
}
image = [[NSImage alloc] initWithData:data];
NS_HANDLER
NS_ENDHANDLER
sleep(2); // for illustration purposes
[(NSObject *)_delegate performSelectorOnMainThread:@selector(didReceiveImage:) withObject:image waitUntilDone:NO];
}
_url and _delegate are instance variables that were filled during initialization). The delegate implements the selectors defined in my protocol, errorOccurred: and didReceiveImage:.NSOperationQueue, which provides a method to queue NSOperation subclasses for execution. In my application controller's -awakeFromNib method, I instantiate my NSOperation subclass and add it to the NSOperationQueue like this:
- (void)awakeFromNib {
[_progressIndicator startAnimation:self];
NSURL *url = [NSURL URLWithString:@"http://alexrepty.com/other/kiwi.jpg"];
ImageFetchOperation *operation = [[[ImageFetchOperation alloc] initWithURL:url delegate:self] autorelease];
[_queue addOperation:operation];
}
Latest Comments
Thu, 05.05.2011 21:12
Very kind of you to share this , Alexander. A couple of minor corrections, if I may: In your addObservers:... me [...]
Mon, 02.05.2011 01:15
blog.proculo.de site is cool . Bookmarked !!! [url=http ://betonufc.info]ufc betting[/ url]
Tue, 05.04.2011 21:10
You may find it interesting to note that I have now decided to return the Android phone I bought and go back to an [...]
Tue, 05.04.2011 18:10
I have an Android device and f or me, it's not the UX of the OS that's the problem. Thanks to the dedicated keys, a [...]
Tue, 05.04.2011 17:41
Matthew, note that I never said Mark shouldn't have switc hed to an Android phone. If th at is his choice, and he [...]