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;

// .m file
@implementation MyAppDBManager

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

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

 return db;


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

@synthesize myDatabase;
@synthesize fetchResultController;

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

  self.fetchResultController = [
    [NSFetchRequest alloc]

- (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];


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



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]

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;


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 .

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.