"

Posts Tagged ‘Xcode’

Format Your Code With Crustify

Thursday, May 6, 2010 @ 07:05 PM
posted by josealobato

The problem

Don’t you love your code? I mean, it is our product as developers. In the same way that a baker knows how to do and create delicious bread, we create source code…. beautiful source code. The code has to do its duty right and efficiently but it also has to be beautiful. There is nothing better that see your code after some time and feel that this is your code with the correct style.

There is another think to take into account. When we review a piece of code, if the code is not formatted in the way we expected we are adding lot of brain stress due to a non expecting format, avoiding we to focus properly on the most important, what the code does.

As you go coding you will make your way to the right format, because you will see tones of code on books, Apple examples, articles and more. But, there are tools that can help upfront.

Crustify

Yes, yes, I know you can format using XCode itself, but it is somehow limited. You can control some indexing and others, but if you want more, you can have a look to Crustify.

With a bit of initial effort, Crustify will give you full control on the code format with more than 400 settings to adjust. Here I will guide you throw the steps to set it up so you can tell by yourself.

Download and install it

So, lets focus. Go and download the source code from the Crustify site. There you will find our friend GIT, do not panic, use:

1
git clone git://github.com/bengardner/uncrustify.git

This will create a folder with all the code inside. The next step is to build it. Like the old days use:

1
2
./configure
make

On the “src” folder you will have the “crustify” executable. Move it to your “/usr/local/bin”, and you are done. You can test on the terminal somewhere with the command “crustify -h”.

Include in XCode

I can show how to run it on the command line, but I’m sure you want to go to the point and include it in XCode. Here we deal with Objective-C so first lets take the basic configuration that comes with the source code. Take the file “etc/objc.cfg” and save it where ever you think is right (your configurations folder maybe!). It contains a default configuration good enough to start with.

This configuration file though is loosely documented so it is mandatory you to read the 70 lines file “documentation/htdocs/configuration.txt” to understand some of its simple enough syntax.

If you want to explore further the effect of every setting in your code you can download the UniversalIndentGUI. There, select Crustify and you will be able to, graphically, play with the setting so you get the best of the tool.

Better if you go adjusting your configuration as you go, so let’s set up and easy way to run Crustify from XCode. I borrow the small script from Scott from HackerToys

1
2
3
4
#!/bin/sh
echo -n "%%%{PBXSelection}%%%"
/path/to/uncrustify -q -c /path/to/defaults.cfg
echo -n "%%%{PBXSelection}%%%"

The only thing we need to do is add a new user script in XCode as shown on the picture (use you own path).

Edit User Scripts.png

You may assign a shortcut if you use it very often. Now you are done. Just open any file and run the script using the script menu of XCode.

Enjoy your coding!

I need to say this again, the code is your product so… make it shine!!

Post to Twitter Post to Facebook

During the different SDK releases, Apple has changed many things. Now, developers can build their own applications using different approaches, but I personally believe that an intensive use of Interface Builder is a good strategy to set up in few minutes a project and easily maintain it.

During my trainings, I collected the request of my students and most of the time, they wish to use more and more Interface Builder, because it is more intuitive and easier to use than simply typing code.

In this post, I want to explain how to build the infrastructure for the UINavigationController using Interface Builder. I think this is the best, cleanest and quickest way to build an app. If you just repeat this exercise a couple of times to understand the concept, you will be able to build a navigation controller-based app in few minutes.

To better understand what we do, I will start from an window-based project without taking advantage of the view-based template prepared by Apple. So, open Xcode and create a new project. Select a Window-based Application template and name it MyNav. We could have chosen the View-based Application template and Xcode would have setup the whole infrastructure for us, but then you loose all the magic behind it. So, I prefer you build it from the scratch, so that you will learn how it works and you can easily modify it to create more complex functionalities.

Give a look at the created project. It contains three files: MyNavAppDelegate.h, MyNavAppDelegate.m and MainWindow.xib. We need to modify these three files to go on, but let us start with some design.

Suppose you want to navigate 3 views: view1, view2 and view3. The view1 is the view appearing as soon as the app finishes launching. This is called the main view. Since it is the first view in the sequence, view1 is also called the root view. Root view and main View do not always coincide. For example, in the Contacts app, the main view is the All Contacts list, while the Root View is the Groups view.

Each view of our project will be a UIViewController and the Navigation Controller will be responsible to push or pop the next or the previous view onto the screen as they were in a stack. So, let us start.

Modify the MyNavAppDelegate.h file, so that it looks as follows:

1
2
3
4
5
6
7
8
9
10
11
#import <UIKit/UIKit.h>

@interface MyNavAppDelegate : NSObject
{
 IBOutlet UIWindow *window;
 IBOutlet UINavigationController *myNavController;
}
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UINavigationController *myNavController;

@end

Now, let us modify the implementation file. Edit the MyNavAppDelegate.m file like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#import "MyNavAppDelegate.h"

@implementation MyNavAppDelegate
@synthesize window;
@synthesize myNavController;

- (void)applicationDidFinishLaunching:(UIApplication *)application
{
 [window addSubview:myNavController.view];
 [window makeKeyAndVisible];
}
- (void)dealloc
{
 [myNavController release];
 [window release];
 [super dealloc];
}
@end

Now, fire up Interface Builder, double-clicking the MainWindow.xib file. From the Library drag a Navigation Controller and drop it in the MainWindow.xib.

Control-click the My Nav App Delegate object in the MainWindow.xib window and, when the HUD window opens, connect the myNavController outlet with the recently added Navigation Controller.
So, what have we done in the last part? It is very simple: we declared in the @interface of the MyNavAppDelegate a UINavigationController outlet. In the @implementation, we should have allocated and initialized this UINavigationController, but to avoid this, we added a Navigation Controller object with Interface Builder to our project. In this way, the XIB file contains the Navigation Controller. When we launch the app, the MainWindow.xib file, containing the Navigation Controller, is automatically loaded. Since this is a generic object to let Xcode understand that we are referring to the same Navigation Controller defined in the @interface, we need to connect the outlet of the App Delegate to the UINavigationController.

Now, we need to add the 3 UIViewController(s) to manage each view in the stack. The use of the UIViewController instead of simple UIView is requested by the fact that a UIViewController is a controller and thus, it is able to manage complex functionalities, such as screen rotations, that maybe you will use later.

The approach to setup a UIViewController and its XIB file is the same for each view, so I show you how to do it only for one of them. Then, you simply repeat the following steps:

  • Right-click the Classes group in the project window of Xcode and select Add->New File…
  • Select the UIViewController subclass template from the Cocoa Touch Classes and click Next.
  • Name the view FirstViewController (make sure that the Also Created flag is selected) and click Finish. You get two files (FirstViewController.h and FirstViewController.m).
  • Right-click again the Classes group and choose Add -> New File… This time, select View XIB template from the User Interface under iPhone.
  • Click Next and name the file FirstViewController.xib.
  • Click Finish.

Repeat the last paragraph for the second and third view (name them SeconViewController and ThirdViewController).

When you have the three controllers, double click the FirstViewController.xib. The MainWindow.xib window contains 3 objects: File’s Owner, First Responder and View. The File’s Owner is a Proxy Object: it simply represents in IB an object that you have created somewhere else (coding or using IB). We need to specify which object is exactly. To do this, select the File’s Owner and the Identity pane in the Interface Builder Inspector (Tools -> Identity Inspector). Choose as Class name FirstViewController. Repeat this step for the SecondViewController and for the ThirdViewController. When done, you have clearly associated each class to its XIB file.

Now, our File’s Owner represents the FirstViewController object. Right-click it and connect the view outlet with the View object. Open the View object (double-click it) and select the Attributes pane in the Inspector (Tools -> Attributes Inspector). Click on the Background color picker and change the color to red, so that we can distinguish it from the other views we are going to set up.
Now, we have to tell the Navigation Controller that the FirstViewController is the first view we want to load (the Main View, remember?) and use it as root view. Here, there is a small trick. Open again the MainWindow.xib file and double click the Navigation Controller. Click in the window of the Navigation Controller and select the Identity Inspector.
Select as class name FirstViewController. Then, select the Attributes Pane and select FirstViewController as NIB Name. The Navigation Controller should show now a link to the FirstViewController.xib as shown here on the right-hand side. Before you can Build and Run, choose the Detailed View of the MainWindow.xib. Click on the triangle close to the UINavigationController. Inside it, there is UIViewController. You need to make sure that this is is the right one. Select it and set its class name to FirstViewController in the Identity Inspector. In the same way, set to FirstViewController, the XIB Name to FirstViewController in the Attributes Inspector. If you miss these steps, your app will not work. It should look like in the following picture.

You can now Build and Run. You will get a window with a NavigationBar and red view. Let’s go back to the project.
So, we have set our root view. Now, we have to inform each view about the next view of the desired view sequence. You will see that many functionalities are for free and the code we are going to write is represented by few lines.
Edit the FirstViewController.h so that it looks like this:

1
2
3
4
5
6
7
8
9
10
11
#import <UIKit/UIKit.h>

@class SecondViewController;

@interface FirstViewController : UIViewController
{
 IBOutlet SecondViewController *mySecondViewController;
}
@property (nonatomic, retain) IBOutlet SecondViewController *mySecondViewController;

@end

Remember to synthesize the property and add the following header #import “SecondViewController.h” in the FirstViewController.m file.

Now, open the FirstViewController.xib and add a UIViewController to the MainWindow.xib FirstViewController.xib window. Select this view controller and set its class name to SecondViewController in the Identity Inspector. Then, set also to SecondViewController the XIB Name in the Attributes Inspector. Now, finally, connect the File’s Owner outlet mySecondViewController to the view controller.

We do the same for the second view controller. Before that, open the SecondViewController.xib file and add a UIViewController object to the MainWindow.xib SecondViewController.xib window. Select this view controller and set its class to the ThirdViewController in the Identity Inspector and set its XIB Name to ThirdViewController in the Attributes Inspector.
Now, open the SecondViewController.h file and modify it as follows:

1
2
3
4
5
6
7
8
9
10
#import <UIKit/UIKit.h>

@class ThirdViewController;

@interface SecondViewController : UIViewController
{
 IBOutlet ThirdViewController *myThirdViewController;
}
@property (nonatomic, retain) IBOutlet ThirdViewController *myThirdViewController;
@end

Remember to synthesize the property and add the following header #import “ThirdViewController.h” in the SecondViewController.m file.

Now, build and run it. You don’t see any difference with the previous run. The infrastructure is already set up, but we need to add some way to push the next view to the screen. We can do it in different way. We choose the simplest one, using a push button in the center of the current view.
Add a button to the first and second view controllers. For each of them, add the following action in the header file of the corresponding class:

1
- (IBAction)bringNextView:(id)sender;

In the implementation, add the following:

1
2
3
4
- (IBAction)bringNextView:(id)sender
{
 [[self navigationController] pushViewController:mySecondViewController animated:YES];
}

Repeat the previous code for the second view controller. Don’t forget to connect the button to the IBAction of the File’s Owner. I attach the project MyNav.zip. I only add small things to make it to like nicer. If you have any question, simply contact me.

Have a nice coding!!!

Post to Twitter Post to Facebook

Undo and Redo

Wednesday, June 17, 2009 @ 09:06 AM
posted by Geppy

This topic is quite difficult to digest, but after few exercises you should be able to manage it.
When you work with an application, it usually happens that, after applying some edits to your data, you realize that the final result is not what you were expecting. So, you wish to go back and remove what you have done. I believe you are familiar with the Undo and Redo items in the Edit menu of your Mac. But, how can you implement these functionalities in your application?
Cocoa and Cocoa Touch use an intelligent approach to manage this. To understand it, I have to introduce the concept of NSInvocation. An NSInvocation is an object containing all the elements of an Objective-C message: a target, a selector, some arguments, and the return value. Each of these elements can be set directly and the return value is set automatically when the NSInvocation object is dispatched. NSInvocation works together with the NSUndoManager to make the Undo/Redo mechanism possible.
When you apply an edit onto your data and you want to be able to undo that edit, you need to prepare (coding) the inverse operation corresponding to that particular edit. Then, you pack this inverse message (including selector, arguments and return value) in an NSInvocation object and forward it to the NSUndoManager. This will store this object in a stack and wait for the user action.
Indeed, there are two stacks: the Undo Stack and the Redo Stack and their scope is very similar. The management of the two stacks is assigned to NSUndoManager and you don’t need to take care of it. When you undo some operation, NSUndoManager removes from the Undo Stack that operation and adds it to the Redo Stack. If you redo that operation, this time the NSUndoManager removes it from the Redo Stack and adds it to the Undo Stack.
Let’s look at the details and how to code it. Suppose you are writing a simple calculator with a plus and minus operations:

1
2
- (NSNumber *)add:(NSNumber *)aNumber to:(NSNumber *)anotherNumber;
- (NSNumber *)subtract:(NSNumber *)aNumber from:(NSNumber *)anotherNumber;

You want to be able to undo and redo each of these operations after you apply them to your data. When you start your application, an NSUndoManager object is created for you with no costs. In reality, if you are writing a document-based application in Cocoa, an NSUndoManager is created automatically. In the other cases (iPhone included), you have to create it explicitly.
You usually need only an NSUndoManager for each application. To register the above two methods to the NSUndoManager mechanism, you do the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
- (NSNumber *)add:(NSNumber *)aNumber to:(NSNumber *)anotherNumber
{
    NSUndoManager *undo = [self undoManager];
    [[undo prepareWithInvocation] subtract:aNumber from:anothernumber];

    float F1 = [aNumber floatValue];
    float F2 = [anotherNumber floatValue];
    F1 += F2;
    return [NSNumber numberWithFloat];
}

- (NSNumber *)subtract:(NSNumber *)aNumber from:(NSNumber *)anotherNumber
{
    NSUndoManager *undo = [self undoManager];
    [[undo prepareWithInvocation] add:aNumber to:anotherNumber];

    float F1 = [aNumber floatValue];
    float F2 = [anotherNumber floatValue];
    F1 -= F2;
    return [NSNumber numberWithFloat];
}

The undoManger method (lines 3 and 4) is defined in the NSDocument, NSResponder, NSManagedObjectContext and WebView classes. Please, refer to the documentation of these classes for details.
The trick is at the lines 4 and 15. There, you register to the Undo/Redo mechanism the opposite operation to your current edit.
You can also change the label of the Undo and Redo operation using the

1
- (void)setActionName:(NSString *)actionName;

So, you can add this line after line 4:

1
[undo setActionName:@"Add"];

Once implemented, you will have in the edit menu “Undo Add”.

Post to Twitter Post to Facebook