Pages

Friday, April 30, 2010

Steve Jobs about Flash

You can find the newest letter "Thoughts on Flash" from Steve Jobs on Apple Hot News.
I like this letter because of the last sentence:
Perhaps Adobe should focus more on creating great HTML5 tools for the future, and less on criticizing Apple for leaving the past behind

My Blog on EE

New featue on EE - Blogging. here is my blog:
http://www.experts-exchange.com/blogs/pgnatyuk/

Sunday, April 25, 2010

Saturday, April 24, 2010

Cocoa. Simple Controller

I hope, finally, I do understand all this story with the GUI controller in Cocoa applications. The story is short, but in the beginning, this all was complicated for me to connect my GUI controls with my code in the Interface Builder.
The scenario is simple:
1. Add new Objective-C class (everything as usual, by default it is derived from NSObject).



2. Add IBAction, as many as you need, for example, doButton, doSlider, DoMenu, etc, whatever you have in your GUI.

#import <Cocoa/Cocoa.h>


@interface MyNSController : NSObject {

}

- (IBAction)doSlider:(id)sender;
- (IBAction)doButton:(id)sender;
- (IBAction)doMenu:(id)sender;

@end




Add an implementation:
#import "MyNSController.h"


@implementation MyNSController

- (IBAction)doSlider:(id)sender
{
float value = [sender floatValue];
NSLog(@"Do Slider. Value = %f", value);
}

- (IBAction)doButton:(id)sender
{
NSLog(@"Do Button");
}

- (IBAction)doMenu:(id)sender
{
NSLog(@"Do Menu");
}

@end

3. Launch Interface Builder (double-click on MainMenu.xib file).
4. Add GUI controls (button, slider, menu, etc.)

5. in the Library choose Classes tab, find your class in the list and drag it to the MainMenu.xib document.

6. The class appears in the Inspector. You see all actions you added. Connect them with the controls.

7. Build and Run your application.

Friday, April 23, 2010

Cocoa. Button/Menu Controller.

I've not understood how I can use it, it happened occasionally - I made a new button class (a kind of a command button) and an application that use this class.
1. Create new Cocoa application.
2. Add new Objective-C class (DoButton). By default, the class is derived from NSObject. Change it - NSButtonCell.
3. Modify the class interface and implementation as it is shown below.

DoButton.h file:

@interface DoButton : NSButtonCell {

}

- (IBAction)DoSomething:(id)sender;

@end

DoButton.m file:

#import "DoButton.h"


@implementation DoButton

- (IBAction)DoSomething:(id)sender
{
NSLog(@"Hello");
}

@end

3. Save the project file and switch to Interface Builder (double-click on the MainMenu.xib file).
4. In Interface Builder, add Round Rect Button to the application window.
5. In the Library find your class (DoButton), choose it by the mouse click and bring to the MainMenu.xib document.

6. Select the Round Rect Button in the window. In the Inspector, on the Class Identity tab, choose DoButton from the combo box as the class name.
7. Select the Round Rect Button in the window and connect it with DoButton object in the MainMenu.xib document:

8. Save changes in the Interface Builder and switch back to the application code.
9. Build and Debug the application.
In the console you see:

Running…
2010-04-23 22:52:57.626 ButtonApp[21939:a0f] Hello
2010-04-23 22:52:59.387 ButtonApp[21939:a0f] Hello


Same can be done with NSMenu. In this case the first Objective-C class should derive from NSMenu. All other things are absolutely the same.

Wednesday, April 14, 2010

Objective-C. Execute code before main

Interesting for me Objective-C run-time feature - execute code before the main:
Objective-C class may have two special class methods:
+ (void)load;
+ (void)initialize;

Here is a simple program demonstrating this language feature:
#import <Foundation/Foundation.h>

@interface First : NSObject
{
int x;
}

- (void)printX;
- (void)setX:(int)value;

@end

@implementation First

+ (void)load
{
NSLog(@"First +load");
}

+ (void)initialize
{
NSLog(@"First. +initialize");
}

- (void)printX
{
NSLog(@"First -printX");
NSLog(@"x=%i", x);
}

- (void)setX:(int)value
{
NSLog(@"First -setX");
x = value;
}

@end

@interface Second : NSObject
{

}

@end

@implementation Second

+ (void)load
{
NSLog(@"Second +load");
}

+ (void)initialize
{
NSLog(@"Second initialize");
}

@end



int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

NSLog(@"Program starts");
First *first = [First new];
[first printX];
[first setX: 123];
[first printX];
[first release];
[pool drain];
return 0;
}
Here is the program output:

You see text "First +load" before "Program starts". It means that the class method load was called before I instantiated first object. Then, you see text "First +initialize" - the class method initialize was called when the class receives a first message. You also see text "Second +load". I do not create any object of Second class, but the method load was called anyway.

Reference:
Max OS X Reference Library. 7.1 +load: Executing code before main

Monday, April 12, 2010

Objective-C.History

SmallTalk was an elegant untyped object-oriented language. C is a strong, extremely portable procedural language. In early 80s Brad Cox and Tome Love invented new language - Objective-C. They started with C and added classes and message-sending mechanism from SmallTalk. The goal was to create a simpler language than C++. In fact, they got a C preprocessor and a library. 

In 1985, Steve Jobs founded NeXT, Inc. His goal was to create powerful affordable workstations. NeXT chose Unix as its operation system and Objective-C as its native programming language -  in 1988 NeXT licensed Objective-C from Stepstone, the owner of the Objective-C trademark at that time, the company of Brad Cox and Tome Love. NextSTEP, a powerful user interface toolkit from NeXT, was developed in Objective-C.  NeXT together with Sun Microsystems created a standardized version of NextSTEP called OPENstep. It was adopted by Free Software Foundation as GNUStep development environment. A Linux version, which also includes the Linux kernel and the GNUStep development environment, is called LinuxSTEP.

In 1996, when Apple acquired NeXT. NextSTEP was renamed to Cocoa. Coupled with Xcode and such development tools as Interface Builder, Apple created a powerful development environment for application development on Mac OS X.

In 2007, Apple released an update to Objective-C language and labeled it Objective-C 2.0.


Reference:
History Of Objective-C.

Saturday, April 3, 2010

Key-Value Coding (KVC) in Cocoa

Key-Value Coding - directly set or get a property of an object by the property name - the key.
#import <Foundation/Foundation.h>

@interface Person : NSObject
{
NSString* firstName;
NSString* lastName;
}

@end

@implementation Person

- (id)init
{
[super init];
firstName = [[NSString alloc] init];
lastName = [[NSString alloc] init];
return self;
}

- (void)dealloc
{
[firstName release];
[lastName release];
[super dealloc];
}

@end

int main()
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

Person* person = [[Person alloc] init];

[person setValue:@"Pavel" forKey:@"firstName"];
[person setValue:@"Gnatyuk" forKey:@"lastName"];

NSLog(@"Name: %@", [person valueForKey:@"firstName"]);
NSLog(@"Last Name: %@", [person valueForKey:@"lastName"]);

[person release];
[pool drain];
return 0;
}
Mac OS X Reference Library. Key-Value Coding Fundamentals
Cocoa with Love. 5 key-value coding approaches in Cocoa
The Unix Geek. An Introduction to Key-Value Coding in Cocoa.
Thecacao. Key-Value Coding (KVC) and Generic Programming.

I think KVC is the same as the properties in C#. It is easy to understand how it's implemented. For example:
CodeProject. Implementing Properties in C++.

I think the same can be implemented much easier:
#include <iostream>
using namespace std;

class CPerson
{
char* firstName;
char* lastName;

void setValue(char*& var, const char* value)
{
if (var)
{
free(var);
var = NULL;
}
if (value == NULL)
return;
var = strdup(value);
}

public:
CPerson() : firstName(NULL), lastName(NULL) {}
~CPerson()
{
if (firstName)
free(firstName);
if (lastName)
free(lastName);
}

const char* get(const char* key)
{
if (strcmp(key, "firstName") == 0)
return firstName;
if (strcmp(key, "lastName") == 0)
return lastName;
return NULL;
}

void set(const char* key, const char* value)
{
if (strcmp(key, "firstName") == 0)
return setValue(firstName, value);

if (strcmp(key, "lastName") == 0)
return setValue(lastName, value);
return;
}

};

int main (int argc, char * const argv[])
{
CPerson person;
person.set("firstName", "Pavel");
person.set("lastName", "Gnatyuk");
cout << "Name: " << person.get("firstName") << endl;
cout << "LastName: " << person.get("lastName") << endl;
return 0;
}
It is a very simple way. I've never seen NSKeyCodingValue protocol implementation in Cocoa. Of course, it is a really generic and more complicated solution.