Friday, September 28, 2012

Open Excel File by Double Click

Recently I had experience a problem at work. I cannot open Excel files by double click them. I tried to open from Excel Open menu and it works fine. I have no problems to open other files such as word or txt files.

I checked my other colleagues and they don't have the issue. One of my friend recommended me to find solution from web by googling. Soon I found a solution. This is something related to Excel registry settings. Since the complexity of Windows registry, it is not recommended to directly edit or change settings there. I found that there is file association from File Explorer. Here is what I did.

First, open File Type from Tools menu, locate the XLS (notice the upper case):



Click Advanced button, the following dialog is displayed.



Select Open in Action list. Click on Edit button:



Make sure to clear Use DDE, then click OK. Apply changes. This will be double click on Excel default behavior back.

Reference


Read More...

Tuesday, September 11, 2012

iOS and New iPhone in Tomorrow's Special Event

Apple has been doing special event to release news about devices and software in past years. I have been kept close look at those events since I got my first iMac in 2007. Tomorrow, September 12, 2012, will be another special event.

A lots of rumors are focused on new iPhone or new hardware devices. What I am actually interested in is the formal release date of iOS 6. I have been waiting XCODE update with iOS 6 support this Fall. I have watched WWDC 2012 videos about iOS 6. I really like the new features in iOS 6, both in Objective-C and new UI components. My next app will use some of those new features.

I'll update this blog after all the news will be released in tomorrow's Apple special event. This will determine how I'll be back working on my apps.

Today, September 12, 2012, Apple made a long list of announcements. iPhone 5 looks gorgeous. The most interesting news for me is the iOS 6 release date. It will be available in one week time, next Wednesday, September 19, 2012, before iPhone 5 release (on September 21, 2012). Not sure when the XCODE update will be available.

I am still watching today's Keynote speech, 1 hour 53 minutes. First time in almost 2 hours. I think my internet has some problems, or the Apple site streaming may have issues. I had several times frozen during AirPlay Mirroring. When I went back to my iMac, I still has similar issue. The reason I suspect internet provider issue is that my QQ app lost connections several times. Anyway, I am going to back to the speech.

Read More...

Sunday, September 09, 2012

Get Caller Class Context and Caller Method Names

In my MyLog class, I prefer to print class name and method name in my log messages. What I did before was to use hard coded strings. This practice makes the maintenance difficult, specially when class or method names are changed.

Later I found two nice Cocoa C-Functions to achieve the same result, without any hard-coded strings. Those functions are great way to get context class and method names. Therefore, I added them to MyClass as convenient macros:


#define CALLER_SELECTOR_NAME NSStringFromSelector(_cmd)
#define CALLER_CONTEXT       NSStringFromClass([self class])

Here are examples to use CALLER_CONEXT to initialize MyLog instance and use CALLER_SELECTOR_NAME to get method name:

// ExampleClass1.m
#import "MyLogger.h"
...
@property (strong, nonatomic) MyLogger* logger;
...
@implementation ExampleClass1
...
@synthesize logger;
- (MyLogger *) logger {
   if (!_logger) {
       _logger = [[MyLogger alloc] initWithContext:CALLER_CONTEXT];
   }
   return _logger;
}
...
- (void) viewWillAppear:(BOOL)animated {
   [super viewWillAppear:animated];

   [self.logger debug:
    ^{
        return [NSString stringWithFormat:@"'%@' is called!",
               CALLER_SELECTOR_NAME];
     }
   ];
...
}
...
@end

Here is the result in the debug console:

2012-09-09 14:23:44.990 TapToCount[5260:c07] [DEBUG] ExampleClass1 - 'viewWillAppear:' is called!

Reference

Read More...

Monday, September 03, 2012

Update: MyLog with Block

I wrote a utility class to log messages in Objective-C long time ago. I updated the class with block early this year, which is similar as delegate in C#. The reason I like to use blocks is that I think, it will improve my app performance.

Here is what I did before, taking info as an example:

- (MyLogger*) info:(NSString*)messageFormat, ...;

A message string is passed to info method by using a list of dynamic string parameters. No matter if I enabled info logging level or not, the message string would be built on call.

By using a block, the string is built within a dynamic block of codes. The bock is actually a pointer to a function. The block of codes may not be executed at all if the logging level is not enabled. Therefore, I think this strategy would improve app performance.

typedef NSString* (^MessageBuildBlock_t)();
...
- (MyLogger*) info:(NSString* (^)(void))msgBuildBlock;

The block is defined as a function returning a string. Then the block is used as a parameter for info method.

Reference

Read More...

Sunday, August 26, 2012

Objective-C: Using Swapping to Mock Method Impelmentaion

Recently I read an interest blog on Unit test in Objective-C. A customized class is defined as method-swizzling helper. With this helper class, two methods in two difference class can be easily swapped at runtime. Therefore, by using this strategy, you can easily mock method calls avoid calling to database or making HTTP requests.

The key points for this helper class is based on Objective-C runtime functions.

class_getClassMethod(...)
method_exchangeImplementations(...)

The first method is used to get a class method as a data type Method. The original and swapped methods can be obtained by this function call. Then the second method is used to make an exchange of method implementation.

The blog has an example of this usage. It looks very easy to make a mock of a method implementation, which is a key practice in unit tests.

Reference


Read More...

Saturday, August 18, 2012

Scrollbar in Mac OS

Since 2007, my interest has been shift to iOS and Mac. One thing interesting UI is scroll bar. Apple has changed the behaviour of scrollbar in iOS. The purpose of this change is to utilize the maximum territory space in a scrollable view. The scrollbar will disappear after the view stays static within seconds. To bring it back, you can user touch gestures to swipe the view. All these are handled by OS. This has been in iOS devices for long time.

Since Lion OS,  Apple introduced the similar support in Mac OS. It is a very interesting design. Here is my understanding. The scrollbars (horizontal and vertical ones) are two UI components. When they are visible, they are UI elements with two main purpose:

  1. They provide visual vision of positions of its content, and
  2. They respond to user interaction, moving or scroll to a position when they are clicked or dragged.
When scrollbars are invisible, not only cannot users see content positions or if content is scrollable, users also have no way to interact with scrollbars. In iOS and Mac native applications, this normally does not present any issue. Users can user touch like swipe to check or move content positions.

However, I had a case recently that invisible scrollbars do cause me some trouble. I use web based RDC to connect to Windows. The RDC window was developed in Java, which is based on Java UI component. It does not support swipe gesture. When I saw a blue window, I had no way to scroll its contents even I knew the Start menu there on the bottom behind the window.


What I found there are two solutions to resolve the issue. The first method method is limit to Mountain Lion OS. Windows in ML are resizable by dragging any boarders. By dragging boarders, the scrollbar will appear for a short period of time. With that period, just quickly touch the scrollbar to make a move.


The second solution is to make scrollbars always visible. This can be set in System Preference | General.



Actually, the scrollbar-always-visible looks really ugly after I am getting used to the new-and-clearn views. However, this solution is the only solution when a window is not sizable.

Read More...

Saturday, August 11, 2012

DataGrid and Object Binding

Last week, one of my good friends asked me some questions about using DataGrid in Windows Form app. I looked at his codes. My first reaction, after I saw his codes, was to recommend him using object or class as data source binding instead of SQL or LINQ binding. I have experience using ASP.Net DataGrid with object binding in my previous work proejcts. I like this strategy very much. By using class as data source, as a developer, I have total control of how data being pumped into DataGrid. The comlicated SQL data structure should be left at SQL server side. The .Net project should forcuse on data and UI.

I quickedly showed him an example. First I added an example class MyData as a data object template. Then I added a DataGrid control on a Windows form. I used data source wizard from the form's DataGrid to set up its object data source to MyData. That was very quick and easy, based on my ASP.Net experience. However, the wizard does not provide a way to let me to tell which method the DataGrid to get data. It seems that DataGrid for Window Form is very different from the one for ASP.Net.

After that meeting, one day, I created an example project and tried to figure it out. Now I got the solution. Basically, in the case of Windows Form application, the data source for DataGrid should a be collection, not an object class. It is very different from the case of ASP.Net DataGrid. Since the data source is a collection, the data binding to DataGrid has to be manually added from DataGrid UI wizard. That's very easy to do: adding column header text and data binding property of DataPropertyName.

Here is the simple Windows Form application. I added a DataGrid to Form1.



DataGrid has a designer wizard. Leave the Data Source as default (none). Click on Add Column... to  define data grid columns. For this demo, add two columns: Name and Age, with column header names as: Column Name, Column Age.




In order to bind data to DataGrid, I need to edit columns from Edit Columns... in DataGrid designer. From there, change DataPropertyName to Name and Age.





With above DataGrid settings, I add a simple class of MyData, which will be used as objects to be displayed on the DataGrid with only two properties: Name and Age. I added another static method to return a collection of MyData objects. Here are my simplified codes:

Public Class MyData
 Private m_name As String
 Private m_age As Integer

 Public Sub New(ByVal nameValue As String, _
     ByVal ageValue As Integer)
   m_name = nameValue
   m_age = ageValue
 End Sub

 Public Property Name() As String
   Get
     Return m_name
   End Get
   Set (ByVal value As String)
     m_name = value
   End Set
 End Property

 Public Property Age() As Integer
   Get
     Return m_age
   End Get
   Set (ByVal value As Integer)
     m_age = value
   End Set
 End Property

 Public Shared Function GetObjects() As List(Of MyData)
  Dim list As List(Of MyData)
  list = New List(Of MyData)
  list.Add(New MyData("John", 12))
  list.Add(New MyData("Mike", 21))
  Return list
 End Function
End Class

In reality, this method (GetObjects) should contain codes to get data from database, or to call data bridge to get mapped data from database.

For the Form, the codes are very simple:

Public Class Form1
...
 Private Sub Button1_Click(ByVal sender As System.Object, _
   ByVal e As System.EventArgs) Handles Button1.Click
   Me.DataGridView1.DataSource = MyData.GetObjects()
 End Sub
...
End Class

The basic concept of this strategy is to make the app as simple as possible: only two element in the Windows Form application:

  • a Form with DataGrid as UI; and 
  • MyData as data source template.

In this way, the focuse can be placed on UI, to provide convenient and nice format for client. The data bridge part, which provides data, can be placed in another class, library, or SQL server.

Here is the result of the application:

Read More...

Friday, August 03, 2012

Finished Watching WWDC2012 Videos

Today I finished watching all available WWDC 2012 videos. There 111 video talk shows. I downloaded them in SD format, which are good enough. To view outlines, I found that I can go to HD area to get PDF files. In this way, I can separate videos from PDF files.

WWDC 2012 shows in iTunes grouped in serials. I started from 400 serial, Developer Tools, with 14 shows. Then 700 serial, Core OS, has 14 shows. 200 serial has 42 shows, which is the largest group. Next is 500, with 24 shows in Graphics , Media and Games. 300 serial is for App services, with 11 shows. The last serial, 600, has 6 shows.

I took some notes in Chinese for the first two serials. I cannot keep taking notes for all of the shows.

Reference


Read More...

Tuesday, July 31, 2012

Blogger Challenge

Recently, I have been puzzled by one challenge: update my blogger with a new view. I have been put image as an indicator of the topic in my blog post for long time. What I would like is to place the icon image off the main column just beside my post title, so that it would be much easy to see the topic for each topic, instead of reading title text. It seems simple task, however, with the limitation of Blogger I just cannot make it happen.

Here are what I tried. Starting from blogger template. I found a place to add a div just right before my post title. The div  has a margin like this style:

....
marin:0 -150%;
....

It does show on the left side of my post title. However, within the div, I could not find a way to change image, the icon for my post.

The icon image is defined in my post. It seems that there is no way to set a reference to a blog post element, such as image's src attribute value. There is a variable in blogger's template, but the values are defined within the template.

I might be possible by using Javascript codes. The difficult point is that how I can define a unique DOM element so that I can retrieve element's attribute value? In addition to that, the Javascript codes have to be trigger on Windows load to update out-fly icon images  from posts.

By the time being, I still could not resolve this puzzle. Any suggestions?

Read More...

Sunday, July 15, 2012

Stackoverflow Flaire is added to my blog

Today I finally fulfill my promise to add SO flair to my blog. I found this promise when I searched my blog for "stackoverflow" to see my previous blog on this web service. I soon found my promise on Feb 18, 2011.

To add this section of HTML codes to my blog template should be easy. However, I spent about half hour to do it. For my record, here is what I did.

First open my blog template and edit it. The place I can add is at almost end of the template:

....
<div id='sidebar-wrapper'>
 <b:section class='sidebar' id='sidebar' preferred='yes'>
   <b:widget id='AdSense1' locked='false' title='' type='AdSense'/>
   ....
 </b:section>
 
 <!-- David Chu added this StackOverflow claire here -->
 <br/>
 <p/>
 <p>David Chu&#39;s programming Q&amp;A at stack<b>overflow</b>:</p>
 <a href='http://stackoverflow.com/users/62776/david-chu-ca'>
   <img alt='SO profile for David.Chu.ca'
   src='http://stackoverflow.com/users/flair/62776.png'
   title='SO profile for David.Chu.ca'
   width='208'/>
 </a>
</div>
....

Now the above section of HTML appears at the end of this blog.

By the way, my SO reached to 4k on July 6, 2012. Actually, I have done almost nothing in the past month. It is the time and effort I invested in the past years, the contribution which programmers recognized, to bring my SO this milestone. My reputation points continues to grow, up to 4054 at the time I am writing this blog.

Read More...

Sunday, July 08, 2012

Animation Views

Navigation and Tab Bar controls provide a way to change views. This kind of change looks like one view being completely replaced with another view, or with animation from one view to another view. Sometimes, you may want to both views visible, with one view in transparent mode on the top of another view. This can be done by using UIView animation methods.

Here are some experience when I tried to use technique.

The basic animation method I use is:

[UIView transitionFromView:fromView
                   toView:toView
                 duration:default_animation_duration
                  options:animationTransiationMode
               completion:completion];

I had one issue with this practice with storyboard (iOS 5.0). The view (toView) being on the top of fromView was positioned with an offset from the top.



The above example shows a gap between the navigation bar and the toView (fromView is on the background). As a result, the bottom bar buttons are not visible because it is out of the screen.

This problem can be easily resolved in storyboard. In the storyboard, select the View Controller first. From the right inspector panel, UNCHECK the property: Resize the view from NIB.



With this fix, the result view is displayed as expected.



Reference

Read More...

Monday, July 02, 2012

Reset SQL Server sa Password

Recently I had a request to reset SQl server sa password. The sa was set up long time ago, but it was not documented. SQL as log in was required to set up administration configurations. This kind of case is very common at work. The following are my notes about this experience.

I soon found a solution to resolve the issue. Basically, you need to restart SQL server in single mode first. Then log in to the server machine by using user with Administrative privilege. The steps are very straight forward, however, I was caught for a while with one mistake. You have to put "-m;" in start up parameter at the beginning with no space afterwards.

The following is the screen snapshot of the property page within SQL server configuration tool. By adding "-m;" right at the beginning line of Startup Parameters, the SQL server will be in single mode in the next start up.



Although I was able to reset sa password by using SQL management studio after  SQL server was restarted, I could not log in to SQL server by sa afterwards. It was interesting that the sa Log was set to blocked. I had to unblock it with single mode on second try.  The following was my snapshot of correct setting. Note: the check box of "Login is blocked out" was set when I reset sa password first time.



Reference


Read More...

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.

Reference


Read More...

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;
@end

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.

References


Read More...

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;

@end

// In my view controller .m class
UITabBarItem* tb = [self.navigationController
 performSelector:@selector(myTabBarItem)];

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.

Read More...

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.

Read More...

Wednesday, May 23, 2012

Sync Data Changes Between Views

Sometimes you may want to sync data source between two views. For example, one view is for displaying data and another for editing. If these two views are associated with tab bar controller, any changes in the edit view should be reflected on the display view. Right?

Here is the tip: make sure the data source context in both views are the same one. The data source context behaviors like a cache for holding all the source source objects. Any changes in the context will be magically refreshed in both views. To do that, simply create one class with singleton object of UIManagedDocument.

// in .h file
@interface MyAppDBManager : NSObject

+ (UIManagedDocument*) database;
@end

// .m file
@implementation MyAppDBManager

+ (UIManagedDocument* ) database {
 static UIManagedDocument* db = nil;

 if (!db) {
   NSURL *url = [[[[NSFileManager defaultManager]
     URLsForDirectory:NSDocumentDirectory
            inDomains:NSUserDomainMask]
            lastObject]
            URLByAppendingPathComponent:@"My database"];
   NSURL*
   db = [[UIManagedDocument alloc] initWithFileURL:url];
 }

 return db;
}

@end

The following is an example to use the database in a table view:

#implementation
@synthesize myDatabase;
@synthesize fetchResultController;
...

- (void)setup {
  NSFetchRequest* fecchRequest = ...

  self.fetchResultController = [
    [NSFetchRequest alloc]
    initWithFetchRequest:fetchRequest
           managedObject:self.myDatabaese.managedObjectContext
      sectionNameKeyPath:...
               cachename:...];
  ...
}

- (void) viewWillAppear:(BOOL)animated {
  [super viewWillAppear:animated];
 ...
  self.myDatabase = [MyAppDBeManager database];
 ...
}

Since the instance of myDatabase is singleton object, its managedObjectConext is only one as well. So that any other views will share the same context as long as the database is from MyDBManager class.

One thing the data source you need to reload is the case of tab bar view controller. Tab bar view controller provides a way to switch among several views. When they are loaded, I found that there is no magical to refresh changes. What I did is to add the reload in a view controller's will appear event:


- (void) viewWillAppear:(BOOL)animated {
 [supper viewWillApear:animated];
 ...
 [self.tableView reloadData];
 ...
}

Read More...

Monday, May 07, 2012

Use VIM for Objective-C Syntax Highlighting

In my previous blog, I mentioned about using VIM for code editing. One of VIM feature is to provide syntax highlighting. I think that I added object-c syntax highlighting to my VIM long time ago. However, when I tried to edit a .m file, I did not see the colorful syntax.

I checked my ~/.vim folder and I found some plugin files for cocoa there. I must have done the objective-c syntax stuff. The file type for objective-c is not .m or ft=m. The file type should be something else.

Quickly I found the file type. Here is the command to enable syntax for objective-c file content:

:set ft=objc

Reference




Read More...

Wednesday, May 02, 2012

Set Image Programmatically

In my iOS project, I have a button. I want to add image to its view in codes. The reason I want to do it is that I have another class with API to provide image. The class uses database entity. If the entity contains a property of imagePath, the image will be loaded from the path; otherwise, the image will be from the app as default image.

I tried to use the following codes to load the image:

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.imageButton.imageView.image =
      [MyImageManager imageForEntity:self.entity]
}

The above codes do not set image at all. I checked my image and there are loaded from my API.

After googling for a while, I found the reason. There is setImage message for button's image with additional parameters. I have to explicitly call this message to set image.  Here is my updated codes:

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.imageButton setImage:
      [MyImageManager imageForEntity:self.entity]
                            forState:UIControlStateNormal];
}

There are more states available to set images for a button:

enum {
    UIControlStateNormal       = 0,
    // used when UIControl isHighlighted is set
    UIControlStateHighlighted  = 1 << 0,
    UIControlStateDisabled     = 1 << 1,
    // flag usable by app (see below)
    UIControlStateSelected     = 1 << 2,
    // additional flags available for application use
    UIControlStateApplication  = 0x00FF0000,
    // flags reserved for internal framework use
    UIControlStateReserved     = 0xFF000000
};
typedef NSUInteger UIControlState;

Read More...

Configure git as XCODE Repository

There is one lecture, Xcode and Source Code Management (October 7, 2011), in the open course of Developing Apps for iOS 2011, by Paul at Stanford University.

Paul demonstrated how to use git as a repository for XCODE source code management. To set up a repository, first, quit XCODE completely, and use Terminal command to set it up.

Set up git Repository


There is one file in XCODE project which saves XCODE UI information. Paul recommended not to check it in. This is a file like xxx.xcuserstate.  To find this filename, change the directory to the project path, and user find command to get the file:

$ cd ~/myprojectpath
$ find . |grep "xcuserstate"

This will find a file name with "xcuserstate". Use the following command to exclude the file:

$ echo xxx.xcuserstate > .gitignore

Then initialize the git and add the source codes (assume the source codes are in the current folder):

$ git init
$ git add .

Use the commit command to seal the change:

$ git commit -m "This is my source code repository with first check-in"

Now the repository is set up. The lecture shows more about how to use the repository to check in changes, comparing changes, and creating branches.

Reset git Repository


In about two days, I have experience fatal error to checking my codes. My case was caused in core data module. I added one to my project, and later on I renamed it. After several files changed, I got fatal error when I tried to check in my codes. The problem is that my renamed data module file cannot be found.

I could uncheck this missing files from commit folder detail on the left panel. However, I cannot ignore or remove this change. Since I have a project with not much changes in repository, I decided to reset my repository.

What I did is to exit XCODE first. From the terminal, local the .git folder and remove it:

$ rm -r .git

This will remove all the files in the repository. There may be a lots of prompt to confirm deleting since files within the folder are read-only. I had to press 'y' to remove all of them.

After removing the repository, I repeated the above steps to get a fresh repository. There may be a way to leave the repository there and create a new one in different repository. I'll update this information when I find the way.

References


Read More...

Monday, April 23, 2012

git Configuration

I have not used git for my source code repository on my Mac. Today, I realized that git is not available in my Terminal. Actually, after googling, I found that git is in my Mac, but not in my PATH.

The git sits in my /usr/local/git folder.  The binary tool is at bin there. So I need to add git to my PATH. This can be done by vim editor:

vim ~/.profile

Add or update the following line:

export PATH="$PATH:/usr/local/git/bin:"

Save the change and exit VIM.

Run the following command to load the path from .profile:

source ~/.profile

Now the git is available in Terminal!

Read More...

Friday, April 13, 2012

VIM Tip: Not Containing Pattern (3)

I find out that Lookaround zero width assertions are very powerful and useful. The more I use it the more I like it. Think this search strategy as match a pattern with addition zero width or hidden pattern together.  This can filter some parts out, which cannot be done just by matching a pattern.

I have used this technique resolving many of finding and replacing issues. Normally, I use search first to make sure the results meeting my expectations. Then I use replacement to substitute the results with my expected contents. Here are some examples. As you can see that it is very productive. For sure, it does require a lots of brain energy to think and to try hard. However, this will sharp you brains. I really enjoy learning and using VIM.

Examples


Let take pseudo codes I used in my previous blog as example. A simple search is to find character 's', and the next character is 't' as zero width, look ahead.  The search command is:

/st\@=

This tells that first token is 's'. The search engine searches for the token as a pattern. When it is found, the engine stops at the found position in the string. Then, the engine looks for the next token 't'. The look-ahead tells the engine to construct the next search for the second token from the substring afterward the first token.  The engine continues to search for the second token as an immediate match. If there is a match, the complete pattern is found. The first token 's' is a matched result as return; if there is no match, the match is failed.



The next simple example is look-behind zero width assertion command:

/\(s\)\@<=t

The pattern to be matched is 't', which is also the first token. The second token is a group of characters 's'. When the first token is found, the search engine stops. The look-behind tells the search engine to take the substring behind as the next search from this position.  If the match (second token) is found right behind the position, a complete match successes, and the first matched token is returned as a result. The following snapshot shows three results of 'ring's:



More Complexed Examples


The following text are some blocks of foo...bar:

foo
  test baz
  something for you
  gave me your beer
bar

foo
  test ba
  something for you
  gave me your beer
bar

foo
  test bae
  foo
  something for you
    gave me your beer
  bar
bar

Here is a command of searching for foo...bar block containing 'baz':

/foo\(\_.\{-}baz\)\@=\_.\{-}bar

Notice that the text within the foo...bar block may contain multiple lines of text. Here \_. is for multi-lines of text. \{-} is none-greedy match, which means matches 0 or more of the preceding atom, as few as possible.  The above search can be described as searching for:

'foo' as start, next zero width pattern: 0 or multiple lines of text till 'baz', then 0 or multiple lines of text till hit 'bar'



You may verify the command by break the search command into two parts, the first part is:

/foo\(\_.\{-}baz\)\@=



The command of searching for foo...bar loop not containing 'baz':

/foo\(\_.\{-}baz\)\@!\_.\{-}bar



Search for the most inner foo...bar block command:

/foo\(\_.\{-}foo\_.\{-}bar\)\@!\_.\{-}bar



Sometimes, I want to add line break tags to the end of a line, but not to the empty lines.  This command can be used to add <br /><br /> to the end of any none-empty lines:

:%s:.\@<=$:<br/><br/>:g



The next example is a very useful one. I often use VIM convert program codes into HTML format. Some times, I need to convert a group of spaces into &nbsp;s, except the first space. This is an excellent case to use lookahead zero width assertion. I figure it out and it becomes my favorite the search and replace commands.

/\(\s\)\@<=\(\s\)\+



After examining the results, I use the following replacement command to do the conversion:

:%s:\s\@<=\s:\&nbsp;:g



Reference


Read More...