Tuesday, June 19, 2012

WWDC 2012 Videos Available Now

Today I got news about WWDC 2012 Videos available from Apple's Development site from Weibo. I will be busy to watch all those training videos. The following is the snapshot of iTunes.

Today I only downloaded the first section: Developer Tools with total 28 tracks (14 videos and 14 PDF  slides). HDs are nice but they take too much space and download bandwidth. I only got SD instead, good enough for my, and much quick and less space.



Saturday, June 09, 2012

iOS 6 coming in WWDC 2012

According to the news from AppleInsider, iOS will be announced at WWDC 2012. This is really a welcome news. I have witnessed the evolution of iOS from it start. iOS was really good change with many improvements. For example, I like the storyboard very much. The storyboard makes the development much easy in terms of overall UI layout and workflow.

I guess there will be many great new changes in iOS 6.0. What I want the most is the generic template. It seems to me that I cannot define a generic protocol with generic in iOS or Objective-C, something like:

@protocol myAbstractInterface : NSObject <T>
- (void) methodA<T1>:(T1*) parameter1;

where myAbstractInterface is a template, T and T1 are a generic data types.

Currently, I have use concrete class types for T and T1. I hope Apple would make this feature available so that it makes true OO design much easier. Apple iOS architecture designers may have their own reason not to implement generics in this way, or they may introduce generics with difference strategies, or more efficient and elegant framework.

I'll keep close eye on the coming WWDC in just about 2 days.



Thursday, June 07, 2012

Change iOS Navigation App to Tab and Nav App

I have an app with UINavigationController as start view. Later on, I wanted to to change the start view with both navigation bar on the top and a group of tab bars on the bottom. There are many apps like this style, however, there is no template for this type of app in XCODE.

This is a frequently asked question on web for iOS development. There are some information available, but most of them are iOS 4.0 or early with xib based interface. For iOS 5.0+, Apple introduced storyboard. I struggled for a while, but finally I figured it out. The fact is that it much easier in iOS storyboard than the previous IB(Interface builder).  Here is the summary of what did.

Add Tab Bar Controller as Start View

My app was designed with XCODE Navigation template.  In the storyboard, the first view of my app's workflow is a Navigation Controller:

I want to change my app's first view with both navigation on top and tab bars on bottom respectively. The first thing I changed was to add a Tab Bar Controller, which is available from storyboard's library (inspector view on the bottom in XCODE). Just drag and drop the Tab bar controller to my storyboard.  Here is what Tab Bar Controller looks like in the storyboard.

Notice that there are three view items being placed in.  The first one is the root or master view: Tab Bar Controller, and other two are normal View Controllers, each with one Tab Bar Item on the bottom in its view. For the later two view controller items, the image and text can be changed from inspector. In addition to views, there are two segues, relationship segue type, being used to link the master Tab Bar Controller to other tab items.

Now it is time to make changes. First, I need to change the master, Tab Bar Controller, to my app's start point. This can be done by checking inspector's property: Is initial view Controller:

Notice that an arrow is added to the Tab Bar Controller on the left.

Then, control+drag Tab Bar Controller on the bottom of the view (right icon) to an existing Navigation Controller. A pop up menu is displayed.  Choose Relationship segue from the pop up menu. That's it! The app is changed to an app with both navigation and tab bars in the first view.

To change the position of tabs, just drag a tab icon and move it around.

Based on this practice, it is very easy to add more view controllers to the tab bar controller: use the relationship segue to link the tab bar controller and other view controllers. All those can be done by just dragging and dropping.

Add Navigation Controllers

To add navigation controller to the start view, simple drag and drop relationship segues so that the existing or the newly added navigation controllers as the next controller after tab bar controller, before other view controllers

Two controllers in a sequence in this way, as a result, will make the start view showing both navigation bar on the top and tab bars on the bottom.

iOS' storyboard makes the change so easy. I really like the improvement of iOS 5. The following sections are additional information about those controllers and my experience of using them.

iOS Controllers: Tab Bar and Navigation

It is important to know that both Tab Bar Controller and Navigation Controllers are only a view component. They are not View Controllers. In other words, they are part of view or window on iPhone or iPad.

Initially, I tried to create customized class based on tab bar controller with navigation delegate.  However, I could not associate my customized class with view controllers. Soon I realized that my customized class is NOT VIEW CONTROLER. In storyboard, the class for Tab Bar Controller or Navigation Controller is Controller, but not View Controller (for example, UITabBarController and UITableViewController).

Both controllers are visible in view controller class, where they are part of view and they direct view flow. For example, the following codes are some examples in a view controller to access to either Tab Bar Controller or Navigation Controller, as well as navigation item.

NSInteger row = [self.tabBarController selectedIndex];
[self.navigationController popToRootViewControllerAnimated:YES];
self.navigationItem.rightBarButtonItem = self.editButtonItem;
self.navigationItem.leftBarButtonItem = nil;

Access to Tab Bar Controller and Tab Bar Item

If you set view's title with a string, the tab bar item's title will be changed, as same as the view's title. Normally, I prefer the tab bar item's title shorter than view's title since tab bat item has limited space. Here is a tip to set tab bar item's tile with a short string and set the view's title with a long string:

self.navigationItem.title = @"Edit entities";
self.navigationController.tabBarItem.title = @"Edit";

Within the storyboard, a tab bar item has a tag property.  This tag's data type is integer. Many developers use the tag value as an identifier for a tab bar.

One thing I realize is that a tab bar item cannot be set as an outlet in a view controller class. The reason is very simple, the "view" class that the tab bar item resides is a controller but view controller. Therefore, you cannot control-drag a tab bar to a view controller as an outlet.

However, it is possible to define a customized class based on UITabBarController and then control+dragging the tab bar item to the customized class as an outlet.  Here is an example I tried:

// my customized class for UITabBarController
@interface NavigationWithTabBarController : UINavigationController

@property (weak, nonatomic) IBOutlet UITabBarItem *myTabBarItem;


// In my view controller .m class
UITabBarItem* tb = [self.navigationController

if (tb.tag == 1) ...

Later, I found out that actually, I don't need to define my customized class at all. The tab bar item is accessible from view controller's navigation controller:

// In my view controller .m class
UITabBarItem* tb = self.navigationController.tabBarItem;

if (tb.tag == 1) ...

Even though, I make this note on this experience. There may be cases where a customized class is needed.

Another tip is about disabling tab bars or making tab bar controller on the bottom invisible. With both tab and navigation bars as start view, the tab bar will  always be displayed along navigation. In some cases, you may want to make tab bars invisible. To do that, just  overwrite the following method in your view controller class like this, making tab bars invisible:

#pragma mark - UINavigationController methods overwrites

- (BOOL) hidesBottomBarWhenPushed {
   return YES;

To disable tab bar items, for example, to prevent switching to other tabs while editing table view cells, use the following method:

- (void) setTabBarItemsWhileEditing:(BOOL)editing {
   for (UITabBarItem* tabBarItem in [self.tabBarController.tabBar items]) {
       [tabBarItem setEnabled:!editing];

This method is also used to enable them when not in editing mode.


Saturday, June 02, 2012

CSS Style and HTML PRE tag

I have been puzzled by my recent posts with source codes. I realized that the horizontal scroll bar does not appear in my source code blocks. The only thing I changed was to change the background color from white to black. I have not figured it out why until today.

The technique I used in my Blogger CSS is to define a class with this attribute:

white-space: nowrap

This should be able to let text in a block (div) auto flow horizontally. Today, I examined my previous posts and recent posts, and find nothing wrong with my updated CSS. My div class have the attribute. After looking at context of my code blocks. I saw that I use pre HTML tag to around my codes. In Safari's inspector, the attribute has been overwritten:

white-space: pre;

That's it! Then I tried to bring my white-space back to nowrap like this:

.nowrap > pre:first-child { ## class nowrap then next first child pre selector
 white-space: nowrap ## no wrap

This resolves the issue, however, all the codes are in one line. The line breaks within pre blocks are all ignored. Actually, pre HTML tag means to preserve all the format of text within the block. It seems I cannot resolve the issue with both white-space as nowrap with pre HTML tag.

The solution is to add line break tags <br /> within codes and not using pre HTML tag.