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.



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.

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
www.corywiles.com | twitter.com/kwylez

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.

Creating Custom Glossy Gradient Buttons Programmatically

As my experience, and hopefully skill, in iPhone development has matured over the past year and half I am in the constant search for the best techniques for my apps to run better, faster, and consequently more efficient.  Of the top developers that I follow they all make references to the importance of utilizing subclasses of UIViews and the underlying subsets of views in general.

I love the UI elements that are used on the phone. I didn't realize the awesome power of CoreAnimation and the flexibility that it gives you to manipulate and create graphics as such a granular level.  I set out to see if I could recreate a common iPhone UI element completely programmatically: a glossy gradient button that still responds to touch events.

The end result was a success and a great learning experience.  I still need to add in more testing to make sure that interacting with all these views is more efficient than interacting with standard pngs.

This biggest issue that I ran into was "re-enable" the button actions.

Simply subclassing UIButton did create a problem when dealing with the UIControlEventTouchUpInside/UIControlEventTouchUpOutside methods that you associate with buttons.

I was able to overcome this issue by implementing the touchesBegan and touchesEnded methods.  Remember...UIButton inherits from UIControl, which in-turn inherits from UIView.

Problem solved.

Download Project

UIViews with Rounded Corners and Animations

One of the best iPhone reference books on the market today is iPhone SDK Development by Bill Dudney and Chris Adamson, published by Pragmatic Programmers.  The examples are real-world, easy to follow and cover just about any area of development that one needs.  In my earlier projects and example code I tended to use a lot of graphics for buttons and backgrounds because I need something with rounded corners and/or a gradient.  However, in my latest project I have wanted to get away from that and utilize CoreAnimation and more UIView drawing techniques and the results have been outstanding.  Load time on my views are much faster because all the drawing and rendering are done on the compiled view level and not from the rendering of an image.

 I created a sample project that loads a three different views onto the controller and animates them.  There is nothing overly complex about the code at all and can be customized to be more configurable, but is written to show the power and flexibility of creating custom views and animations.

The rounded corner drawing in the project was sample code from the iPhone SDK Development Book.  Credit where  credit is due to Bill and Chris.

As always I encourage anyone who downloads the project to make any modifications and/or enhancements.  For example, you could add in the functionality of firing of the animation based upon text field values or randomizing the speed of the animation.