czwartek, 27 listopada 2014

iOS, a co to jest - odcinek pierwszy: Objective-C

Przychodzi czas, kiedy muzyk rockowy nasyci się muzyką rock  i zaczyna sięgać po interpretacje klasyków czy choćby utworów z lat pięćdziesiątych ubiegłego wieku, na które wcześniej nawet by nie spojrzał.  W żadnym razie nie chodzi o porzucenie głównego nurtu, który go zasadniczo wyraża, ale o poszerzenie horyzontów, poszukiwanie nowych form, które również mogą wpłynąć inspiracyjnie na zasadniczo grany gatunek muzyczny.  Nie wiem ile takich przypadków zdarza się w IT, ale spotyka się czasami osoby, które potrafią wyjść poza swoje ortodoksyjne czasami wręcz religie. Inna jeszcze sprawa że również trendy światowe w ostatnich latach mają pewne zakręty, daje się niewątpliwie odczuć pewien przesyt wysokopoziomowych rozwiązań .NET czy Java, mamy renesans znanych od dawna technologii Web, w których dostrzeżono platformę do budowania całych aplikacji.  Kolejnym zakrętem jest niewątpliwie rozwijanie Visual Studio w kierunku wspierania narzędzi i rozwiązań Open Source czy wszystkich platform mobilnych, zamiast wyłącznie własnej.  iOS to jak jeden z ostatnich niepoznanych lądów, do którego chciałem dopłynąć już jakiś czas temu, by dopełnić pojęcia o platformach mobilnych, porównać rozwiązania Apple z Windows/Windows Phone oraz Android. Owszem mamy takie rzeczy jak Apache Cordova czy Xamarin, ale dziś i przez najbliższy czas cofnę się do “lat pięćdziesiątych”, bo taką mam ochotę. Niech będzie trochę hardcoru z tamtych lat! Czy będzie to tylko przeszłość?  Objective-C zyskał co prawda następcę w postaci Swift, ale miejscami nawiązuje on czasami do niego, od czegoś trzeba zacząć, a rozwiązania natywne zawsze będą najlepiej wyrażały user experience danej platformy i będą najbardziej wydajne.  Xamarin ma pełne pokrycie w API, ale czasami dobrze znać tam natywny interfejs użytkownika, a Cordova jest nowoczesna, ale nadal rozwiązania Web wciąż mogą ustępować rozwiązaniom natywnym (chociaż je gonią z roku na rok i stają się coraz wydajniejsze) i nie są kompletne (wymagają pisania natywnych wtyczek, przy tworzeniu własnych znajomość danej natywnej platformy jest niewątpliwie potrzebna)

Dziś tylko krótko spisałem sobie podstawy podstaw samego języka Objective-C, jeszcze bez iOS.  Byłem nastawiony na hardcore połączony z rozwiązywaniem łamigłówek. Na razie mogę powiedzieć, że owszem składnia jest momentami zupełnie inna od C#, VB, C++, Java, JavaScript, ale… może się podobać, po zapoznaniu się z nią jest całkiem – przynajmniej jak na razie – zrozumiała. Mamy odpowiedniki przynajmniej podstawowych konstrukcji z C++, C# czy Java, język wydaje się…  przyjaźniejszy od czystego JavaScript ECMA 5.  Ma klasy, interfejsy, dziedziczenie które dopiero teraz zaczynają wchodzić w JavaScript. Objective-C ma też pewną dynamiczność, którą wprowadzono do C# w 2010 roku. Archaizmem jest może - jak na razie - tylko ręczne alokowanie pamięci czy niszczenie obiektów oraz brak typu enum (używamy makra #define) oraz typu bool (jest predefiniowane makro dla int).  To na razie początki, zobaczymy co będzie dalej.

 

Historia

  • 1980 - powstanie, kompatybilny z C i zorientowany obiektowo, inspiracja Smalltalk
  • 1988 - NeXT
  • 1996 - Apple

Ogólne właściwości

  • nadzbiór C
  • oparty o wiadomości  (odpowiednik metod jak w SmallTalk)
  • separacja interfejsu od implementacji (dwa pliki *.h i *.m lub dwie sekcje)
  • dynamiczne typowanie
  • mixiny
  • wskaźniki
  • zarządzanie pamięcią

XCode

Hello World

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])

{

         @autoreleasepool {

                   NSLog(@”Hello, World!”);   //@ – string

          }

          return 0;

}

 

Zmienne i operatory

Zmienne

Wszystkie posiadają typ

4 podstawowe typy:

  • int
  • float
  • double
  • char

Rozmiary zależą od systemu operacyjnego

Nie ma typu boolean, jest makro BOOL (inna nazwa dla FALSE = 0 i TRUE = 1)

kwalifikatory:

  • long
  • long long
  • short
  • unsigned
  • signed

Typ id

  • dowolny typ
  • umożliwia polimorfizm i dynamiczny binding

NSString

int x = 41;

int x = TRUE;

x = (1 == 4);

NSLog(@”Ala ma kota nr %i”, x);

%i - int

%f - float, double   (zmienna float 78.6 zostanie wypisana jako 78.599998 !  double dokładnie)

char c = ‘a’;

%c - char

Odczyt z linii komend:

scanf(%i”, &x);

NSString *name = @”Marcin”;

NSLog(@”Na imię mam %@”, name);

Zakresy:

definicja jest brana z lokalnego bloku, jak nie ma definicji to brana jest z bloku nadrzędnego itd.

Operatory

  • -
  • *
  • /
  • +
  • %

Przypisanie

  • =
  • +=
  • -=
  • *=
  • /=
  • %=
  • ++
  • --

Porównanie

  • ==
  • >
  • >=
  • <
  • <=
  • !=
  • &&
  • ||
  • !

Kompletny zbiór operatorów z C

Stałe

extern const int COUNT;

const int COUNT = 5;

lub

#define COUNT 5

 

Klasy

Interfejs

  • definiuje dane
  • opisuje metody
  • inny niż interfejs w Javie lub C#
  • plik .h

Implementacja

  • definicja metod
  • plik .m

Obiekty

  • tworzenie
    • Alloc - alokacja pamięci
    • Init - inicjalizacja, jak konstruktor
  • niszczenie
    • Release - zwolnienie pamięci
    • Dealloc - wywołanie na obiekcie, który nie ma już referencji, jak destruktor

Metody i wiadomości

Klasy mają metody i wysyłają wiadomości

Klasa może odpowiedzieć na wiadomość, nawet jeśli nie definiuje metody

//deklaracja

//- object, + klasa;  typ zwracany; nazwa metody; typ I parametru; nazwa I parametru; nazwa drugiego parametru, typ drugiego parametru, zmienna, do której trafia drugi parametr

//nazwa II parametru,

-(int) add: (int) first and: (int) second; 

//użycie

[myClass  add:1  and:2]

Przykładowa klasa:

plik S.h

@interface S:  NSObject

{

         int size;

}

-(void)x:  (int)s;

-(int)getY;

@end

      

plik  S.m

@implementation S

-(void)x: (int)s

{

         size = s;

}

-(int) getY

{

        return size * size;

}

@end

 

użycie

@autoreleasepool

{

         S *s = [[S alloc] init];   //alokacja i domyślna inicjalizacja

         [s x:3];  //wysłanie wiadomości

         int a = [s getY];

}

 

własny inicjalizator

@interface S: NSObject

{

         …

}

-(id)initWithS: (int)s;

@end

 

@implementation S

-(id)initWithS: (int)s

{

         self = [super init];

         if (self)

         {

                  [self setY:s];

         }

         return self;

}

@end

 

S *s = [[S alloc] initWithS:10];

 

propercje

@interface S: NSObject

{

}

@property int x;

@end

 

@implementation S

@synthesize x;

 

       S *s = [[S alloc] initWithS:10];

       int b = s.x;

      

Kontrola

Warunki

@interface Sc : NSObject

-(S *) bigger: (S *) s1  and: (S *) s2;

@end

 

@implementation Sc

-(S *) bigger: (S *) s1  and: (S *)s2

{

         if([s1 getY] > [s2 getY])

         {

                  return s1;

         }

         else

         {

                  return s2;

         }

}

@end

“Wyliczenie”

#define GREEN 1

#define BLUE 2

#define RED3

 

-(NSString *)printC

{

           switch(c)

           {      

                    case  GREEN :

                           return @”Green”;

                           //break;

                    default:

                           return @””;

                           //break;

           }

}

Iteracje

Pętla for

for (int i = 0;  i < 5; i++) 

{

}

Pętla while

int i = 1;

while (i < 5)

{

          if (i == 4)

                  break;  //continue;

          i++;

}

Wyrzucenie wyjątku

@throw [NSException exceptionWithName: @”Invalid …”  reason: @”…”  userInfo: nil ];

Łapanie:

@try {

}

@catch  (NSException *exception)  {

}

@finally {

}

 

Dziedziczenie i polimorfizm

Dziedziczenie

  • wszystkie klasy dziedziczą po NSObject
  • pojedyncze
  • deklarowane w interfejsie

@interface S : NSObject

-(int) getA;

@end

 

@implementation S

-(int)getA

{

         return -1;

}

@end

 

@interface T: S

@end

 

@implementation T

-(int)getA

{

         return 41;

}

@end

Polimorfizm

  • inny niż w wielu językach
  • może używać id do reprezentowania każdego typu
  • każda wiadomość może być przekazana do każdego obiektu

id object = [[T alloc] init];

NSLog(@”%i”, [object getA]);   //dynamiczne wywołanie

Można skompilować kod z wywołaniem wiadomości, która nie jest zdefiniowana w typie obiektu. Sprawdzanie następuje w runtime, jak coś jest w rzeczywistym typie obiektu to zostanie wywołane, jak nie ma poleci wyjątek.

Brak komentarzy: