Objective-C Language
Tipi di dati di base
Ricerca…
Sintassi
- BOOL havePlutonium = YES; // Assunzioni dirette
- BOOL fastEnough = (car.speedInMPH> = 88); // Espressione di confronto
- BOOL fluxCapacitorActive = (havePlutonium && fastEnough); // Espressione booleana
- id somethingWicked = [witchesCupboard lastObject]; // Recupera oggetto non tipizzato
- id powder = prepareWickedIngredient (somethingWicked); // Passa e ritorna
- if ([ingredient isKindOfClass: [Toad class]]) {// Prova il tipo di runtime
BOOL
Il tipo BOOL
è usato per i valori booleani in Objective-C. Ha due valori, YES
e NO
, in contrasto con il più comune "vero" e "falso".
Il suo comportamento è semplice e identico a quello del linguaggio C.
BOOL areEqual = (1 == 1); // areEqual is YES
BOOL areNotEqual = !areEqual // areNotEqual is NO
NSCAssert(areEqual, "Mathematics is a lie"); // Assertion passes
BOOL shouldFlatterReader = YES;
if (shouldFlatterReader) {
NSLog(@"Only the very smartest programmers read this kind of material.");
}
Un BOOL
è un primitivo e quindi non può essere memorizzato direttamente in una raccolta di Foundation. Deve essere racchiuso in un NSNumber
. Clang fornisce una sintassi speciale per questo:
NSNumber * yes = @YES; // Equivalent to [NSNumber numberWithBool:YES]
NSNumber * no = @NO; // Equivalent to [NSNumber numberWithBool:NO]
L'implementazione BOOL
è basata direttamente su C, in quanto è un typedef del tipo standard C99 bool
. I valori YES
e NO
sono definiti rispettivamente su __objc_yes
e __objc_no
. Questi valori speciali sono compilatori di compilatori introdotti da Clang, che sono tradotti in (BOOL)1
e (BOOL)0
. Se non sono disponibili, YES
e NO
vengono definiti direttamente come modulo integrale. Le definizioni si trovano nell'intestazione del runtime Objective-C objc.h
id
id
è il puntatore di oggetto generico, un tipo Objective-C che rappresenta "qualsiasi oggetto". Un'istanza di qualsiasi classe Objective-C può essere archiviata in una variabile id
. Un id
e qualsiasi altro tipo di classe possono essere assegnati avanti e indietro senza casting:
id anonymousSurname = @"Doe";
NSString * surname = anonymousSurname;
id anonymousFullName = [NSString stringWithFormat:@"%@, John", surname];
Questo diventa rilevante quando si recuperano oggetti da una raccolta. I tipi di metodi di objectAtIndex:
come objectAtIndex:
sono id
esattamente per questo motivo.
DataRecord * record = [records objectAtIndex:anIndex];
Significa anche che un parametro di metodo o funzione digitato come id
può accettare qualsiasi oggetto.
Quando un oggetto viene digitato come id
, qualsiasi messaggio conosciuto può essere passato ad esso: l'invio del metodo non dipende dal tipo in fase di compilazione.
NSString * extinctBirdMaybe =
[anonymousSurname stringByAppendingString:anonymousSurname];
Ovviamente, un messaggio a cui l'oggetto non risponde effettivamente causerà comunque un'eccezione in fase di runtime.
NSDate * nope = [anonymousSurname addTimeInterval:10];
// Raises "Does not respond to selector" exception
Protezione contro l'eccezione.
NSDate * nope;
if([anonymousSurname isKindOfClass:[NSDate class]]){
nope = [anonymousSurname addTimeInterval:10];
}
Il tipo id
è definito in objc.h
typedef struct objc_object {
Class isa;
} *id;
SEL
I selettori sono usati come identificativi del metodo in Objective-C.
Nell'esempio seguente, ci sono due selettori. new
e setName:
Person* customer = [Person new];
[customer setName:@"John Doe"];
Ogni coppia di parentesi corrisponde a un messaggio di invio. Sulla prima riga inviamo un messaggio contenente il new
selettore alla classe Person
e sulla seconda riga inviamo un messaggio contenente setName:
selector e una stringa. Il destinatario di questi messaggi utilizza il selettore per cercare l'azione corretta da eseguire.
La maggior parte delle volte, il messaggio che passa usando la sintassi della parentesi è sufficiente, ma occasionalmente è necessario lavorare con il selettore stesso. In questi casi, il tipo SEL
può essere utilizzato per contenere un riferimento al selettore.
Se il selettore è disponibile in fase di compilazione, puoi usare @selector()
per ottenere un riferimento.
SEL s = @selector(setName:);
E se hai bisogno di trovare il selettore in fase di esecuzione, usa NSSelectorFromString.
SEL s NSSelectorFromString(@"setName:");
Quando si utilizza NSSelectorFromString, assicurarsi di avvolgere il nome del selettore in una NSString.
Viene comunemente utilizzato per verificare se un delegato implementa un metodo facoltativo.
if ([self.myDelegate respondsToSelector:@selector(doSomething)]) {
[self.myDelegate doSomething];
}
IMP (puntatore di implementazione)
IMP è un tipo C che si riferisce all'attuazione di un metodo, noto anche come puntatore all'implementazione. È un puntatore all'inizio di un'implementazione del metodo.
Sintassi:
id (*IMP)(id, SEL, …)
IMP è definito da:
typedef id (*IMP)(id self,SEL _cmd,…);
Per accedere a questo IMP, è possibile utilizzare il messaggio "methodForSelector" .
Esempio 1:
IMP ImpDoSomething = [myObject methodForSelector:@selector(doSomething)];
Il metodo indicato dall'IMP può essere chiamato dereferenziando l'IMP.
ImpDoSomething(myObject, @selector(doSomething));
Quindi queste chiamate sono uguali:
myImpDoSomething(myObject, @selector(doSomething));
[myObject doSomething]
[myObject performSelector:mySelector]
[myObject performSelector:@selector(doSomething)]
[myObject performSelector:NSSelectorFromString(@"doSomething")];
Esempio: 2:
SEL otherWaySelector = NSSelectorFromString(@“methodWithFirst:andSecond:andThird:");
IMP methodImplementation = [self methodForSelector:otherWaySelector];
result = methodImplementation( self,
betterWaySelector,
first,
second,
third );
NSLog(@"methodForSelector : %@", result);
Qui, chiamiamo [NSObject methodForSelector che ci restituisce un puntatore alla funzione C che implementa effettivamente il metodo, che possiamo successivamente chiamare direttamente.
NSInteger e NSUInteger
NSInteger è solo un typedef per un int o un long a seconda dell'architettura. Lo stesso vale per un NSUInteger che è un typedef per le varianti senza segno. Se controlli NSInteger vedrai quanto segue:
#if __LP64__ || (TARGET_OS_EMBEDDED && !TARGET_OS_IPHONE) || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64
typedef long NSInteger;
typedef unsigned long NSUInteger;
#else
typedef int NSInteger;
typedef unsigned int NSUInteger;
#endif
La differenza tra un int firmato o un unsigned o long è che un int signed o long può contenere valori negativi. L'intervallo di int è -2 147 483 648 a 2 147 483 647 mentre l'int unsigned ha un intervallo da 0 a 4 294 967 295. Il valore è raddoppiato perché il primo bit non è più usato per dire che il valore è negativo o no. Per un lungo e NSInteger su architetture a 64 bit, l'intervallo è molto più ampio.
La maggior parte dei metodi forniti da Apple restituiscono un intero NS (U) rispetto al normale int. Avrai un avvertimento se proverai a lanciarlo su un normale int perché perdi precisione se stai eseguendo un'architettura a 64 bit. Non che ciò sia importante nella maggior parte dei casi, ma è più facile usare NS (U) Integer. Ad esempio, il metodo count su una matrice restituirà un NSUInteger.
NSNumber *iAmNumber = @0;
NSInteger iAmSigned = [iAmNumber integerValue];
NSUInteger iAmUnsigned = [iAmNumber unsignedIntegerValue];
NSLog(@"%ld", iAmSigned); // The way to print a NSInteger.
NSLog(@"%lu", iAmUnsigned); // The way to print a NSUInteger.
Proprio come un BOOL, l'intero NS (U) è un tipo di dati primitivo, quindi a volte è necessario racchiuderlo in un NSNumber, è possibile utilizzare @ prima del numero intero per eseguirlo come sopra e recuperarlo utilizzando i metodi seguenti. Ma per trasmettere a NSNumber, puoi anche usare i seguenti metodi:
[NSNumber numberWithInteger:0];
[NSNumber numberWithUnsignedInteger:0];