Yesterday I worked on new a Lab for my upcoming iPhone course and the topic was how to prevent user input while the application is gathering data from a server. Normally that is not a big issue when you just obtain data but that can be a big issue when you send data because then it could corrupt the server side.
So far I just created an UIView that was semi-transparent on top of the entire view preventing the user to click on anything below. But that did not work properly in every case because as it turned out the user input is not consumed but queued and handled as soon as the main thread becomes available. Therefore if I don’t disable the button or alike the code is executed again. This is the original code:
self.connection = [[[NSURLConnection alloc] initWithRequest:request delegate:self] autorelease]; // Now show an animation UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; UIView *window = [[UIApplication sharedApplication] keyWindow]; UIView *shield = [[UIView alloc] initWithFrame:window.bounds]; shield.backgroundColor = [UIColor blackColor]; shield.alpha = 0.5f; [window addSubview:shield]; spinner.center = shield.center; [shield addSubview:spinner]; spinner.hidden = NO; [spinner startAnimating]; // Block the further execution until all data is received CFRunLoopRun(); [spinner stopAnimating]; [spinner removeFromSuperview]; [spinner release]; [shield removeFromSuperview]; [shield release];
Soon I got the feeling that I block the main UI thread and so the input is not consumed until the system can execute it. After looking for a good solution I was more or less told that I should not use CFRunLoopRun() but let the main thread run its course and deal with the result when it comes in.
That said the transition was not easy but eventually I got all the callbacks in place and the thing worked fine except that the call was to short to test is properly. Thus I added a sleep inside the callback to give myself time to click multiple times but that did not solve the issue. Through debugging I then saw that when data are returned back from the server that it is still done in the main thread and so preventing the view to consume the user input.
This is the code afterwards:
// 1. When the call comes in and we start the loading self.spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; [self.spinner release]; UIView *window = [[UIApplication sharedApplication] keyWindow]; self.shield = [[UIView alloc] initWithFrame:window.bounds]; [self.shield release]; shield.backgroundColor = [UIColor blackColor]; shield.alpha = 0.5f; [window addSubview:shield]; spinner.center = shield.center; [shield addSubview:spinner]; spinner.hidden = NO; [spinner startAnimating]; // Now execute the call to the web service self.connection = [[[NSURLConnection alloc] initWithRequest:request delegate:self] autorelease]; // 2. When the all the data is received we do: [spinner stopAnimating]; [spinner removeFromSuperview]; [shield removeFromSuperview]; // Call back to the service that we received the data [self.depotService handleResult:root];
Finally I went to the backend web service and made sure that handling of the call is delayed. Then I was able to test it and voila it worked like a charm. I could click multiple times on the button and when the shielding view went away the user input was consumed and did not cause more calls to the server.
There is still some stuff I have to learn how things are done in iOS in contrast to backend Java as I am used to. On the other hand it forces me to understand the underlying concept in details which will be a great asset when given the class.
Today I battled an issue with iOS that nearly drove me crazy. What I wanted to do is to call a Apache Sling WebService and retrieve a list of data. I tested it with Curl do make sure it works before dealing with the iOS.
Because I am lazy I did copy some existing code that I knew was working into my project, adjust it and started to test it. But whatever I did I got this error:
Error Domain=kCFErrorDomainCFNetwork Code=303 “The operation couldn’t be completed. (kCFErrorDomainCFNetwork error 303.)”
Can you guess what caused it?
Well, when I ran out of options I just started to take out code until I either ran into other issues or until it fixes it. Eventually I got it working and it turned out that there was a slight change between Sling (very RESTful centric) and the way we did the project which I borrowed the code from. In Sling you need a GET in order to obtain data and in the previous project everything was a POST. But that wasn’t the issue. What was is that I by default gave a payload to the request even if that one was empty. And that is what caused the error. As soon as I took out the payload everything was back to normal. I have to admit that this error code / description was very helpful.
So with Sling I have to make sure that I pay more attention to what HTTP method is used and make the appropriate checks on when certain features can be used.
Finally after several months of thinking about it and preparing my iPhone App Development Course is on-line. It took that long because I wanted to make sure that I have at least one iPhone App published on iTunes before giving the classes so that I have the experience to have gone through the registration and approval process as well as being able to ensure my attendees that I know what I am talking about. As a twist of life it wasn’t the App I initially planned but an App called Stadiyum that was designed and developed in just 4 weeks so that it is approved in time.
This course will be different that the ones I saw posted all over the Internet because this course will use one Example throughout all labs. This way the attendees will see how an application grows and what is involved in getting the application up and running. Luckily for me as well as the class Apple has released XCode4 which is a much better development environment that the old XCode3. XCode4 is much more integrated and all editors are contained in one window.
And even though the class is geared towards business applications there will be some fun activities like doing animations, slide-on views and dialogs, displaying movies and draw custom components. Beside that we will deal with asynchronous image loading, JSon based RESTful web service calls and a framework to easily manage your settings.
Since I started as a professional software developer a long time ago I gave presentations and courses but this course is different in many aspects. First I am fairly new to iOS and so I can relate to the issues of beginners much more than when I talk about Java etc. On the other hand developing on the iOS platform is quite different because it is so user-centric and the developers need to address this from the beginning in order to be successful. There are many books available to help start developing but there is a big step from reading a book to actually writing an application from start to finish and that is why I wanted to convey that through a single example rather than a collection of examples that are only geared towards the current topic.
Hope to see you there soon – Andy Schaefer
Yesterday was the first day I took my new telephoto zoom lens (Canon EF 70-200mm f/4 L IS USM) out for a spin at the San Diego Wild Animal Park in Escondido. Especially when taking pictures of animals there is nothing that can substitute for a zoom lens. That said using a zoom is not as easy to use as a regular lens. First it is much heavier and so harding to keep still. That is where the mechanical image stabilizer (IS) comes handy. Then it is much harder to focus and even the auto focus can be slightly off or even fully off if it focuses on the wrong piece. Quite often I end up focusing manually to make sure that I get the right focus when I need it rather than being late because the AF is not ready or the focus is off. But then MF can be difficult as well foremost when the subject has not much contrast (an all white bird).
Even when mastered these problems some pictures can yield funny and unexpected results. Here I took a picture of two parrots on a tree branch against a dark background – at least that is what I saw. When I downloaded the pictures to my computer I got quite a surprise when the background was quite bright and vivid:
Even though it gives the picture some special character it distracts from the parrots. Here is another picture where the background is very nervous and also where the focus within the bird is a problem:
All in all the telephoto zoom is really great but I need some more experience especially in low light environments which I did not encounter so far. There is definitively a need to do everything on MF because the AF is even more error prone and takes way too long. That said the year-end performances in my older boys school is a good venue for that.
BTW if you want to see the pictures in a bigger resolution or other pictures from that day please check it out on my MobileMe gallery.
Yesterday Apple released XCode4, the IDE (integrated development environment) to develop iOS and Mac OS X Applications. After more than 1 year (as far as I can remember) this finally will make developing iOS apps much easier and I think much faster and definitively more fun.
Beforehand in XCode3 the Interface Builder was separated from XCode and created many windows which were hard to track and especially harder to close. Just opening a few XIBs and the screen was cluttered with windows all over the place. The only way to managed them was to close the IB from time to time. Now in XCode4 the IB is integrated into XCode and is part of its UI. Due to the fact that XCode is now a single window application there are no more floating windows around. The only other windows one might see are other applications or the Organizer window which contains the help pages, source control systems, devices, projects and archives.
But that is not everything. Because IB is part of it one can have the UI on the left hand editor and display the related View Controller header class file on the right hand editor. This way it is easy to add new IBOutlet properties and IBAction methods without having to leave the UI editor. This works the same way as when I open the implementation class (.m) and have set the right editor to be on counterpart then it will display the header class (.h) or vice versa. The right window can also be used to display the differences in the versions of one file.
The right sidebar is used to display the File Inspector and Quick Help and if an XIB is opened it displays the Identity, Attribute, Size and Connection Inspectors as well.
Beside that the Editor itself has improved dramatically with better code completion, error highlighting as well as code snippets. This improves the overall quality of the code written.
The bottom bar is used to display the log files when the app is running as well as the debugger controls. This way I don’t have to search for the Output and it can be easily viewed while the app is running.
Having used IntelliJ IDEA for a long time the XCode is coming close to it making developing Apps much easier and prevents me from juggling a million windows. I have used XCode4 since more than half a year and so I am very happy to see it get publicly released.
That said there is a ton of more functionality that I did not encountered yet or have not used it so I am looking forward to use it even more and share my thoughts with others.
This week was pretty exciting even though I am not going to buy an iPad2 or join into the frenzies.
First Apple release XCode4 which is really great news because now I can develop iPhone Apps on it without having to worry about issues or that it is not fully supported by Apple. This also makes it possible to talk about it publicly and I can use screenshots to discuss issues.
Then I started to work on my iPhone class that I intend to give this year if I find people willing to listen to me. My class is different in many ways but foremost I will use a single example throughout the class. On one hand this is a challenge because there is more to code or to fill in to make it a smooth progress but it also means that I have to develop the class around the labs.
Finally there is another book out there from Matt Drance and Paul Warren from the Pragmatic Bookshelf called iOS Recipes. From the few pages I read so far this books is quite nice and gives beginners and intermediate iOS developers a way to see how other developers do it.