sobota, 1 grudnia 2012

Lekcja 2 - Objective C, deklaracja zmiennych

Objective C - o historii tego języka można poczytać naprawdę wiele... ale nie o tym dzisiaj bede pisał. W punktach zajmiemy się tym co najważniejsze żeby sprawnie zacząć kodowanie. Niestety w tym przypadku ważna bedzie znajomość, umiejętność kodowania w jakimś innym języku gdyż nie bede tutaj prowadził bardzo szczegółowych opisów w tej materii. 

Zanim zaczniemy zwykle pojawia się pytanie .... co oznacza "NS" jako prefix dla każdej klasy standardowo zawartej w SDK.  Polecam lekture postu : "what-does-the-ns-prefix-mean"


1. Deklaracja zmiennych.

Tutaj możemy spotkać się z wieloma metodami deklaracji. Która jest poprawna? jaką stosować? 

Możemy tutaj skorzystać z środowiska XCode i eksperymentować w pliku nagłówkowym ViewController.h oraz ViewController.m. 
Zacznijmy od ViewController.h

- deklaracja zmiennych - przykład



#import <UIKit/UIKit.h>

@interface ViewController : UIViewController
{
    int _primitiveIntegerValue;
    NSInteger _samePrimitiveIntegerValue;
    NSString *_string;
    NSNumber *_numberObject;
}
@end




Rozpocznijmy analizę tego co zostało napisane. Na pierwszy rzut oka interface. 

@interface "class name" : "parent class"* parent class - tutaj domyślnie jest NSObject ( najwazniejsza klasa po której dziedziczą wszystkie klasy).  
* w srodku znajdują się deklaracje zmiennych domyślnie z widocznością public, ale... możemy również stosować:
  • @privite
  • @protected
  • @public
Przykładowe zastosowanie z użyciem powyższego kodu:

@interface ViewController : UIViewController
{
    @private
    int _primitiveIntegerValue;

    @protected
    NSInteger _samePrimitiveIntegerValue;

    @public
    NSString *_string;
    NSNumber *_numberObject;
}
@end

Kolejne pytanie może się pojawić dlaczego raz używam int a drugim razem NSInteger. Jezeli spojrzymy w definicję NSInteger, zauważymy że możemy stosować to zamiennie. Oczywiście dla przejrzystości kodu powinno się stosować NSInteger. 

typedef int NSInteger;

Przyjrzyjmy się teraz temu samemu przykłądowi ale wzbogaconemu o słowo kluczowe @property.


@interface ViewController : UIViewController
{
    int _primitiveIntegerValue;
    NSInteger _samePrimitiveIntegerValue;
    NSString *_string;
    NSNumber *_numberObject;
}
@property(nonatomicassignint primitiveIntegerValue;
@property(nonatomicassignNSInteger samePrimitiveIntegerValue;
@property(nonatomicstrongNSString *string;
@property(nonatomicstrongNSNumber *numberObject;
@end


Samo słowo kluczowe property zapewnia nam za "friko" metod typu get value (object) i set value (object). Po więcej informacji odsyłam do dokumentacji technicznej.

http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/objectivec/chapters/ocproperties.html


Prawidłowa konstrukcja wygląda następująco 


@property (atrybuty) typ_zmiennej nazwa_zmiennej

Jak widać na przykładzie mamy różne rodzaje atrybutów, stosujemy je w zależności od potrzeby. Opis poszczególnych atrybutów poniżej wedle przyporządkowanych kategorii, przeniesiony w orginale z dokumentacji technicznej. 






Na tą chwile mozemy z czystym sumieniem zamknąć plik nagłówkowy z rozszerzeniem "h". 
Otwórzmy nastepnie plik ViewController.m. 


#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController
@synthesize primitiveIntegerValue = _primitiveIntegerValue;
@synthesize samePrimitiveIntegerValue = _samePrimitiveIntegerValue;
@synthesize string = _string;
@synthesize numberObject = _numberObject;


- (void) test{
    self.string = @"My First text";
    [self setString:@"My First text"];
    NSString *getPreviousString = self.string;
    NSString *getPreviousStringInAnotherWay = [self string];
    _string = @"My First text";
}

- (void)viewDidLoad
{
    [super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

Używamy dyrektywy @synthesize po to aby kompilator wiedział, że należy utworzyć akcesory (get i set). Oczywiście używamy tego dla zmiennych dla których uwzględnione zostało @property. Utworzyłem również metode test, aby pokazać zastosowanie akcesorów dostepu. W pierwszym 2 liniach kodu, które są ekwiwalentne wykorzystujemy modetode "set", w dwóch kolejnych metody "get". 

Ostatni linia również jest przypisana, ale nie obowiązują ją atrybuty, które są przypisane za pomocą @property, tutaj odwołanie nastepuje bezpośrendio poprzez wskażnik. 

Dobrą szkołą jest dlatego stosowanie podkreślnika przed nazwą zmiennej w pliku "h" 

NSString *_string;

A nastepnie analognie tworzenie property 
@property(nonatomicstrongNSString *string;

Łączymy te dwie zmienne za pomocą słówa kluczowego synthesize


@synthesize string = _string;




---------------------------------------------------------------------------------------------------------------------------------
Tips and Tricks

Często można spotkać się z uproszczonym zapisem. 

UIViewController.h


#import <UIKit/UIKit.h>

@interface ViewController : UIViewController
{
}
@property(nonatomic, assign) int primitiveIntegerValue;
@property(nonatomic, assign) NSInteger samePrimitiveIntegerValue;
@property(nonatomic, strong) NSString *string;
@property(nonatomic, strong) NSNumber *numberObject;
@end

UIViewController.m


#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController
@synthesize primitiveIntegerValue = _primitiveIntegerValue;
@synthesize samePrimitiveIntegerValue = _samePrimitiveIntegerValue;
@synthesize string = _string;
@synthesize numberObject = _numberObject;


Możemy również zastosować @property i @synthesize w jednym pliku:

#import "ViewController.h"

@interface ViewController ()
@property(nonatomic, assign) int primitiveIntegerValue;
@property(nonatomic, assign) NSInteger samePrimitiveIntegerValue;
@property(nonatomic, strong) NSString *string;
@property(nonatomic, strong) NSNumber *numberObject;
@end

@implementation ViewController
@synthesize primitiveIntegerValue = _primitiveIntegerValue;
@synthesize samePrimitiveIntegerValue = _samePrimitiveIntegerValue;
@synthesize string = _string;
@synthesize numberObject = _numberObject;


- (void) test{
    self.string = @"My First text";
    [self setString:@"My First text"];
    NSString *getPreviousString = self.string;
    NSString *getPreviousStringInAnotherWay = [self string];
    _string = @"My First text";
}

- (void)viewDidLoad
{
    [super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end


Należy pamiętać o tym, że jeżeli używamy @property w pliku nagłówkowym jednocześnie musimy zdawać sobie sprawę z tego, że metody typu get i set będą public, tak samo jak inne metody deklarowane w tym pliku. 

Proponuje zapoznać się dokładnie z możliwościami atrybutów dla @property, ich "moc" :) naprawdę bardzo często upraszcza życie. 

Jeżeli macie jakieś problemy, śmiało czekam na komentarze/pytania.

Pozdrawiam

0 komentarze:

Prześlij komentarz