Objective-C Programming/Getting Started

Objective C files

edit

In objective C, files normally use the extension .h for interface files and the extension .m for implementation files.

These objective C files are text files that contain instructions on how to write a program. For example, this is a minimal hello world program

#import <stdio.h>

int main (void)
{
	printf ("Hello world!\n");
}

The #import <stdio.h> is a preprocessor directive that will cause the compiler to import the contents of the file stdio.h, just as if it was in the file. A C programmer may immediately see a slight difference in this directive, which is that C uses the #include directive instead. Objective-C programmers usually use the #import directive, which includes the specified header file but, unlike #include, #import is only done once.

Apple's XCode IDE

edit

Objective-C is most commonly used to develop software for the Apple products Mac OS X and iOS (iPodTouch, iPhone, iPad-Mini, and iPad). It's also used in the GNUStep environment on Linux. If you're developing on a Mac, you can use Apple's nice graphical user interface (GUI) called XCode, which is free.

There is documentation , but don't expect a python tutorial. There is a tutorial on ios programming for instance, that half is for learning how to use the IDE, and half to make a simple phone app that reads from an input field, and outputs a message in a label when a button is pressed.

The basic steps for the IOS tutorial are:

  1. create a project from the main menu bar, select the project type single view and controller.
  2. Make sure the project summary in the left top of the project page says compiling to a phone simulator, if the UI being designed is on a phone.
  3. Open the main storyboard file the device (phone) you are working on, and use drag-and-drop to design a form.
  4. using the buttons on the top left, switch to assistant editor, and put the storyboard in one pane and a source view of the interface file for generated view controller.
  5. graphically make connections between the storyboard objects ( fields, buttons ) and interface file, by pressing control and dragging from the user interface design page to source code of the interface file.
  6. On control dragging graphical elements to the interface file of the view controller, there will be prompts showing choices. The easy common case is to make them "outlets" which give reference to the readable or writeable graphical elements on the user interface designer; for button elements, create an action connection and fill in the method name. The actions for button is usually where code needs to start.
  7. There is also a concept called delegate, and in this example, the delegate is for giving up focus when the return key is pressed on the keyboard during entry for the text field entry widget (UITextField). A delegate is just a handler that can implement one or more methods from a set of method signatures defined as a protocol , in this case , UITextFieldDelegate protocol. The delegate method called when the return button is pressed is not "returnButtonPressed", but "textFieldShouldReturn", and this will be found in the protocol documentation.. Inside the textFieldShouldReturn, the textField's "resignFirstResponder" method should be called to allow the keyboard to hide, as a response to the return button being pressed.
  8. the tutorial implements the action button's action of copying the entry text to the label with a few unnecessary but illustrative steps . e.g. copying the textfield's text NSString property to your view controller's NSString property , which was created as an exercise; then creating a local scope NSString variable using alloc and "initWithFormat" so that the name typed in the textfield is concatenated with a hello message. Then assigning the local NSString variable to the label's text property, which has an elided alloc-initCopy semantic. Shorter, but equal , is " self.label.text = [[NSString alloc] initWithFormat:@"Hello %s!", self.textField.text] ;"

After this, more complicated learning examples could be attempted e.g.

example 1
edit
  • make a calculator, where the formula is entered in the textField and the formula is parsed and the result returned in the label.

- this can be done by creating a parser-lexer class that has the responsibility of top-down parsing with a 1 character lookahead into a given string. The parser has a recursive grammar, and methods can represent non-terminal symbols in the grammar, with a lexer method used for converting a terminal string of characters to a number. If the initial symbol of a valid calculation is 'L', then L -> E , is the initial line of the grammar, represented by a call to the a method E ( e.g. [ self E ]; ). An expression is made of one or more terms separated by + or - , and can be expressed recursively as

E -> T |   T + E | T - E

So E can be one of 3 cases, T , or T + E if the symbol after T is +, or T - E , if the symbol after T is -. A start for the E method , could be:-

-(void) E {
  [self T];
  char ch = [self lookahead];
  if (  ch == '+' ) {
     [self nextchar];
     [self E];
     [self plus];
  } else if ( ch == '-') {
     [self next char];
     [self E];
     [self minus];
  }
}

The reason 'plus' and 'minus' are called at the end is that normal arithmetic grammar can be converted to reverse polish notation , where operands can be loaded onto a stack , and operations operate on the 2 last operands pushed onto the stack, and an alternative implementation could be to translate a given input string from normal notation to a string in reverse polish notation , which is then traversed to push/pop/operate in order. Otherwise, in this implementation , 'plus' might look like:

// stack is a NSMutableArray* initialised in -(id)init
-(void) plus {
  NSDecimalNumber* n2 = [stack  lastObject];
  [stack deleteLastObject];
  NSDecimalNumber* n1 = [stack  lastObject];
  [stack deleteLastObject];
  NSDecimalNumber *res = [[NSDecimalNumber alloc] initWithDouble: ( [n1 doubleValue] + [n2 doubleValue] ) ];
  [stack addObject:res];
}

Another implementation of plus, is that there is a second instance of a mutableArray that stores NSString tokens , and 'plus' simply pushes a '+' NSString token onto this second array. When parsing is complete, this array is traversed , and a third mutable array is used to process each token in order, pushing number tokens, and popping numbers for operations and pushing results.

A third implementation could eliminate the use of a stack by having operations return numbers which are the result of applying operations or converting a number lexeme. This relies on the program stack to use recursion not only to provide the ordering for the grammar rules , but to do depth first processing so that intermediate results are stored on the stack in the callers' program stack frames. e.g. if the function expr is returning [self term] + [self term] , the first term call's return value is being held in a register and pushed on the cpu stack before the second call to term .

The rest of the grammar is something like

  1. a term is a factor , a factor multiplied by a term, or a factor divided by a term, and
  2. a factor is a parenthesised expression or a entity , and
  3. the only current entity is a constant.

The constant is a parse of a lexeme which consists of (whitespace ignored) initial + or - , a string of numbers and/or decimal point occurring once. An exercise is to write out the grammar, and then devise the other methods of the grammar, as well as the constant tokenizer.

  • division doesn't work as expected if T -> F | F * T | F / T, since the T after * or / will recurse until T -> F, and then the operation evaluates from the last F back, so 3/3/3 = .333 would be 3/(3/3) = 3 which is not correct. The solution is to reimplement the grammar to eliminate the right sided evaluation. T is always F followed by * T , / T, or nothing, and this can be called T' or Tdash , so T -> F T' , and T' -> * F T' | / F T' | e . The ideas is to move the terminating parse F to the left by wrapping the optional recursive part after the first F with a third symbol T' which always is optionally 'e' or an empty parse. This technique also helps for solving some ambiguity in grammars, such as if-then-statement-(optional)-else-statement -or- if-then-statement-(optional)-else...
  • a parsing bug exists if the expression grammar rule isn't likewise made left-wise resolving.

Once the parser implementation is tested to work on test cases, the action button implementation for the "hello world" app can create a parser to parse the textField's text and output the resulting final number as the label's text, giving a calculator. Other widgets , like a UISegmentedControl can later be used to implement calculator buttons.

example 2
edit
  • have 2 more textFields, and make the button action sending email to an address with a subject and body;

GCC Command-Line Tools

edit

If you're developing for platforms other than the Mac, you can use GCC from the command-line. GCC is a collection of various GNU compilers. GCC has an Objective-C package which works from the command-line. If GCC is installed properly, you should be able to link against the objective-C runtime library; otherwise, you will have to consult your package system.

To build programs under GCC, you need to specify at least one input file and link your program against the Objective-C library:

gcc hello.m -lobjc

You might want to use additional flags to let the compiler point out common mistakes and suppress warnings about the #import keyword:

gcc -std=c99 -pedantic -Wall -Wextra -Wno-import -lobjc -o hello hello.m

Any additional files or libraries required for the program will need to be added to the command line. In addition, gcc allows compiling Objective-C files into intermediate files, which can then be linked into an output binary:

gcc -c hello.m -o hello.o
gcc hello.o -o hello

To use the object-oriented features of objective-C, you need to place the following code at the top of the file:

#import <objc/Object.h>

Other compilers

edit

In general, the compiler name used is objc unless specified otherwise by your compiler.

In a general case, you need to have the following at the top to support objects:

#import <Object.h>