Posterous theme by Cory Watilo

Filed under: ios

UITabBarController Subview Gotcha

By far the most view blog article that I have, and subsequent Github project, is my Universal iOS App Template.  Unfortunately, it has been a tad bit neglected. There were some memory leaks, still supported 3.2 and not iOS5 compatible.  Now that I am working from home I have dedicated part of my day to personal projects and the first order of business is to get the app template up-to-date.  Most of the work was just cleanup and minor tweaks.  One of the branches however required a little bit more work. The template that comes with TabBarController support. A few months ago I added in the feature of having a “Tweetie” style indicator slider.  In 3.2 - 4.x iOS everything worked fine.  In iOS5 the indicator was not initially centered in relation to the first TabBarItem, but the entire TabBar.  When you selected another TabBarItem the indicator would move, but not in the correct position either.

The number of subviews are different between the iOS4 and iOS5.

--- iOS5
2011-11-17 09:14:54.290 UniversalExample[8989:f803] view frame: {{0, 0}, {768, 1024}}
2011-11-17 09:14:54.293 UniversalExample[8989:f803] view frame: {{181, 1}, {76, 48}}
2011-11-17 09:14:54.294 UniversalExample[8989:f803] view frame: {{291, 1}, {76, 48}}
2011-11-17 09:14:54.296 UniversalExample[8989:f803] view frame: {{401, 1}, {76, 48}}
2011-11-17 09:14:54.297 UniversalExample[8989:f803] view frame: {{511, 1}, {76, 48}}

--- iOS4
2011-11-17 09:16:06.751 UniversalExample[9033:b303] view frame: {{181, 1}, {76, 48}}
2011-11-17 09:16:06.754 UniversalExample[9033:b303] view frame: {{291, 1}, {76, 48}}
2011-11-17 09:16:06.754 UniversalExample[9033:b303] view frame: {{401, 1}, {76, 48}}
2011-11-17 09:16:06.755 UniversalExample[9033:b303] view frame: {{511, 1}, {76, 48}}

I now confirmed that there indeed was a difference in how the center position was being calculated. In iOS5 the first subview is the entire frame of the view.  However, I didn’t know which view(sub or super) that it might be referring to.

The best uiview debugging tool for situations like this is the recursiveDescription method.  If you haven’t heard or used it before I suggest/encourage you read Oliver Drobnik’s blog on it. In summary it is a private method to iterate over a views hierarchy.

After calling this method on the subviews in both iOS versions I saw the culprit. The first subview of a UITabBarController is an UITabBarBackgroundView, which obviously is going to extended the entire length of the tab bar.

iOS4

4

iOS5

5

Why did Apple add this subview you might ask? They added it because of welcome changes to UIKit.  Since iOS 2.0 developers have needed the ability to customize many of the UI elements, but unfortunately there wasn’t a straight forward way to accomplish this. The categories and hacks that people came up with are pretty cool, but not maintainable. With iOS5, and updates to UIKit, you can customize background images, tint color, selected images, etc. to your heart’s desire.


In order to fix the iOS5 bug in my template I just had to add a quick runtime check on the OS version and increment the index by 1.

All is right with the world.

Dynamic Model Update and Using Google App Engine

A few weeks ago I presented at the Mobile Technology for Teaching & Learning.  My talk was how to leverage service-oriented-architecture and objective-c runtime functionality in your enterprise applications.  In my demo app I had two json files to use as my datasource so that I wouldn't have to rely on an internet connection.

*I was glad that I did because I had lots of problems with it.

After that talk was over I pushed all the code to github with the goal of modifying the project to use an actual web service to show a real world example of how it works. In order to do that I needed to first create the web service.  Up to this point in my development career I have been using PHP for the service layer with CouchDB as the datastore.  With this particular project I wanted to take things in a different direction.  A few years ago I started tinkering with Python and have really grown to love the language. Unfortunately, I haven't been in a situation to were I could use it in any project beyond a few helper scripts (mainly because of me being a novice and my tight time constraints). I wasn't bound by these restrictions for this project.  What I wasn't looking forward to was doing the server side, "infrastructure" setup to get things going.  I wanted to focus on the development.

Enter Google App Engine to the rescue!  Setting up an account and application with GAE is out of the scope of this post, but Google makes it very easy to do…especially if you are focusing on Python.  I knew that scaling wouldn't be an issue nor would the data integrity. Google is somewhat good at both of those.

I was able to hack out a basic web service within a day.

My biggest roadblock came with handling class instances into JSON.  The awesome community of stackoverflow.com had it covered.

The demo app is modified to use these endpoints for data via GCD.  I also added a class extension for NSDictionary that simplifies the JSON parsing logic, thus removing a lot of the boilerplate code that I had in there originally.

I will be adding in some more enhancements and abstracting the code over the next few weeks.  As always, if you have any comments or suggestions please don't hesitate to contact me

Fun Times with Objective-C Runtime

Good reusable solutions to problems usually come out of necessity rather than luck or leisure.  Over the past 18 months I was always faced with problems of how to simplify the data integrity, security, and aggregation of multiple datasources, usually in big organizations that would then be fed in an iOS app.

The first solution to this issue is to create the "man in the middle".  Essentially a proxy/web services layer that acts as the gateway to all the necessary model objects.  Utilizing tools such as Gearman, CouchDB, MySQL, PHP, Python, Memcache and a little bit of Apache to make everything complete I was able to deploy a lightweight standard response to the iOS app.  As requests from various business groups would come in I found myself taking more and more out of the app and putting that logic into the services layer. Instead of having to rely on the app to handle security, data integrity, computational analysis, image manipulation, etc. I pushed that onto a light weight stack server side that could be scaled easily and mainainted without having to revision the app for basic model object changes.  The added benefits that I saw later on were that I could adapt the response based upon the request…(Android, iOS, mobile web, desktop browser, etc.)

Now that I was concentrating more on feature sets, bug fixes and UI enhancements I was still stuck with having to manage various model classes within the app.  This was a serious pain point to me. I wanted to be able to consolidate the various list and detail controllers that I had down to one instance of each.

Objective-C runtime to the rescue.

Let me be very clear that objective-c runtime is VERY powerful and not for the faint of heart, but when used effectively can be quite useful.  The approach that I took was as follow. 

Use the existing "standard" json format from a web services layer and restructure the "responseObject" so that it gave meta information about the model name, properties for class, which properties should be displayed on the list page and detail page.  By structuring the json  (xml, plist, etc) play load this way I now can push changes to model object and display anytime I want.

In the github project I use an "Employee" object as the example. The app should be able to show a list of employees (title and subtitle) and then a detail page for each employee that would display up to 3 properties.

I have included another json file for "Events" just so that I can show the flexibility. The same list/detail view controllers are now reused for two different objects.

The (current) limitations.
  1. There is an assumption that your list view will use the subtitle uitableviewcell enum type.
  2. Parsing and creation of classes doesn't take into account types other than nsstrings. I have an idea to remedy this, just haven't implemented yet.
  3. What about images?  Most list views have an image associated with it.  What I am thinking about it having a flag set in the properties specifically for images so that they can be loaded asynchronously.
I will be adding in these features.  I am still getting my head wrapped around some of the advanced features of runtime. Below are the links to resources that I used in my research.

Posted on slideshare is the presentation that I gave. It details the philosophical and practical importance of having an SOA that is similar to what I described.  It was heavily inspired by the presentation written on the subject of NPR's SOA.

Presentation References:

Solving Linker Error with New SimpleGeo Framework

One of the tasks that I had set for the upcoming 1.2 release of Stiqrd was to upgrade the SimpleGeo framework to their latest major release 2.0.  I was very excited about this because of the added features and bug fixes that include, but not limited to: simplifying model objects for places and block based logic and callbacks.
After some updates to my gitmodules file and a little bit of refactoring I was ready to go and test the compile of the project.
Unfortunately, I received the following linker error message.
Error
As to not bore you too much with the technical details as why the error was occurring I'll get to the point.  With previous versions of the SimpleGeo, and most network operation based libraries, there was a ASIHTTPRequest library dependency which I had in my Xcode project.  What I had not paid attention to was the fact that the devs at SimpleGeo had include a version already of the ASIHTTPRequest library, but change the namespace changed to SGASIHTTPRequest.
This was an easy fix. Just do a quick find and replace all "ASIHTTPRequest" with "SGASIHTTPRequest". Then add the following import: <SimpleGeo/SGASIHTTPRequest.h>. Finally delete old ASIHTTPRequest that was in my project.
Recompile and off to the races.
If you are using SimpleGeo's iOS framework then I highly recommend upgrading your project to the latest.  I can definitely tell an increase in speed with the new library and the code management is much easier.

Fixing Blurry Text in iOS

Quick Pro Tip:

It never fails that no matter what project, simple or complex, I always run into a unique scenario that makes me scratch my head.  With the latest project I am working on the UI is almost 100% custom.  The views have custom CAGradientLayers, the views are positioned dynamically, special touch events, custom UI date pickers, etc.  Like most developers after staring at the screen for long periods of time text starts to look blurry.  After I looked closer I noticed that all my label text was actually blurry.  As far as I can tell it only occurs when the UILabels were added as a subview for a subclass for a UIView.  Though I am not 100% sure why this is occurring I am pretty confident that the blurriness is caused by frame calculation from the superview has a non-zero fractional component.

In order to remedy this situation, and future proof the app, I round the label's frame and center.

Everything is now all crisp and clear.

Please Enter Your Password Gesture

The more and more that I develop apps the more I try to challenge myself to come with creative ways for users to use the apps. Really trying exploit the power of multi-touch. As mentioned in a previous post, this trend is becoming more and more mainstream. Unfortunately, when it comes to authentication, we are still stuck using the old attage of a PIN and/or using biometrics, which never really caught on with the masses. I personally think that has to do with implementation of it not the mechanism.

In order to try and contribute, to a hopefully better way to authenticate, I started working on a password gesture framework. Though password gestures aren't new what I think differentiates mine, at least conceptually, is how it deals with resetting it. My first thought was to just stick with the same old "email me my password", however email isn't always relaible and the "gesture" password isn't stored on a server, but on the device. In addition, I didn't want to have to rely on a separate server or component. Lastly, by doing that I am relying on an outdated "desktop" thought process of handling lost/forgotten passwords. So how do I give a user a usable and easy way to reset their password without having a server dependency or leaving the app?

My solution is that during the password setting process is to present the user a list of pictures and have them choose N out of X. If they need to reset their password they will be presented with the "reset" picture screen and select the correct ones. If the correct set of pictures are choosen then reset occurs. If not then fail. Due to my extremely busy schedule I haven't had the opportunity to really dedicate the time I want to. I am hoping that posting this to github that the iOS community will take it and make suggestions or fork and implement it with ideas and features that I haven't thought of.

I have started the project as a sample app, but once it reaches a stable point I will make it a static library that can be dropped into any project.

It goes without saying that I am really looking for feedback on this. All comments and suggestions are welcome.

Password Gestures on Github

(download)

Using CAAnimationGroup for View Animations

Lately I have been pushing myself to increase my knowledge and understanding of more advanced animation techniques. The more that I
dig into the lower level
core graphics framework and core animation the more impressed I become with their power. I also have a greater 
respect for those developers who can leverage their power in creative ways.

For most use cases leveraging uiview basic animations with blocks will do exactly what you need. However, in my particular case I wanted to
accomplish the following. Scale, rotate and change center point of subview "A" to subview "B" all at the same time.

Taking my own advise I first started down the path of using basic uiview animations. I want to make sure that each different piece of
the animation would perform the way I wanted them to. Separately, they did exactly what I wanted. Unfortunately, grouping these together was
not going to happen with uiview animations.

When I ran the process all the animations executed, but the transition to subview b's center point was very jerky. To make sure that I didn't
miscalculate any of the individual animations I went back and tested each one separately. Each animation ran smoothly. When I ran the group within the block
I had the jerkiness problem of animation the center point.

After going back and reviewing Apple documentation I found what my problem was. Imagine that. To do the rotation I apply a transform on
the view's layer. However, the transform performs it's animation based upon the views center point. Since I was trying to apply an
animation on the center point as well the group animation had to reposition subview A's center point first before it could apply any of
the other animations. Hence the jerkiness.

I pushed all my animations to a CAAnimationGroup and all the transitions were performed.


-- 
Cory D. Wiles
kwylez@gmail.com
www.corywiles.com | twitter.com/kwylez

Ordered Results using DirectoryIterator

No matter if you are beginner or expert one of the most command tasks that you  will do is writing some class/script/snippet of directory iteration.

"Get a list of files/directories and display"

With PHP there are about baker's dozen different ways of accomplishing this.  In the beginning there was functional verbose way:

It gets the job done, but not very extensive and it seems VERY verbose.  Being that my development background started with OOP I was never a fan.  Fastforward a little bit and PHP introduced "dir", which returns an instance of the Directory class.

Not to bad, but still verbose and God forbid that you have to do recursion.

With PHP5 came the SPL. Standard PHP Library, which still to this day I don't know why it isn't prompted more. Pure object-oriented and has the flexibility to accomplish the basic tasks set before them, as well as, the strength to be a customizable as the developer wants.

The class which most use for directory iteration is…hold your breathe: DirectoryIterator.  In my use case I need to server up image path and meta information in an HTTP request so that an iPhone app could parse the response and grab the appropriate images for display.

Basic usage:

See how easy that was.  OOP at it's best except for one little thing.  The images were not coming back in the correct order.  They are named on the filesystem: "00.png", "01.png", "02.png", etc., but the return was random.  While I can appreciate DirectoryIterator being a more "abstract" enumator and not really having a "natural" sort order I still was frustrated.  Remember, what I said earlier though about the SPL being customizable and OO.  You can subclass the DirectoryIterator and supply your own comparator, which by design, is best practice for a large system.  I, however, was looking  for the shortest line between two points and creating a subclass seemed overkill.

*I really wish PHP had categories like Objective-C or method swizzling

Not a problem though.  I can just pass a callback function to the usort function and call it a day.  H.O.P.  This logic does work, but the array that I wanted to sort is associative so the key that should be sorted is "name". The callback function for usort ONLY accepts two arguments which it compares.  I had to bake in the key which isn't flexible.  I would rather reuse the functionality by being able to pass in the key to sort on. PHP isn't the only language that has this result.  If you look at the behavior of an NS(Mutable)Dictionary in objective-c which makes copies of keys, so the objects in the key array will be different. Objective-C offers the ability to pass in a comparator when iterating over the dictionary so that the sort order is defined by the developer not by the hash.

In a perfect world I would be able to do the following:

Here is the example script for my use case. (changed some path names for security reasons)

 

Custom UIActionSheet Using Core Animation

About four months I posted a blog and project that showed how to customize the buttons of a UIActionSheet.  In the disclaimer I stated that because of the use of the private api's if you attempted to submit your app with this technique to the App Store it will get rejected.

This time around a created a simple, yet effective customized, mock UIActionSheet.  Essentially it is just a custom UIView with three buttons that animates and dismisses just let an UIActionSheet.  All you have to do is assign a method to each of the buttons.

If I have time then I'll try and make it even more extensible by creating a custom delegate to make the classes even more reusable.