ReflectionCzęść NR.6Prawdopodobnie ostatni wpis z tego cyklu. Uczę się Objective-C od dwóch tygodni po godzinach, ale tempo nauki musi zostać jeszcze bardziej zwiększone.
Chociaż być może jeszcze napiszę o rzutowaniu. Podstawy refleksji przydają się na codziennie w programowaniu. Jak więc refleksja wygląda w Objective-C.
Zanim przejdziemy do przykładów oto kod klas z Objective-C użytych w przykładach.
Klasy użyte w przykładach
Objective-C. Interfejsy dwóch klas.
#import <Foundation/Foundation.h>
@class MyOtherObject;
@interface MyObject : NSObject
@property(nonatomic,weak)id delegate;
@property(nonatomic,retain)MyOtherObject* obj;
@end
#import "MyObject.h"
#import "MyOtherObject.h"
@implementation MyObject
-(id)init
{
self = [super self];
if (self)
{
self.obj = [[MyOtherObject alloc]init];
}
return self;
}
A teraz ich implementacja.
#import <Foundation/Foundation.h>
#import "MyObject.h"
@interface MyOtherObject : NSObject
-(void) DoSomething;
@property(nonatomic,retain)MyObject* obj;
@end
#import "MyOtherObject.h"
@implementation MyOtherObject
-(void)DoSomething {
NSLog(@"Log");
}
@end
A oto tworzenie ich instancji.
MyObject* myObject = [[MyObject alloc]init];
MyOtherObject* myOtherObject = myObject.obj;
Type of
TypeOf jest bardzo użytecznym słowem kluczowym. Jak sama nazwa wskazuje zwraca on typ danej klasy.
Type t = typeof(MyClass);
Class c = [MyObject class];
W Objective-C używamy słowa kluczowego “class” zamiast Type. Uzyskujemy dostęp także do statycznej metody tej właśnie klasy.
Type t = myObj.GetType();
Class c2 = myObject.class;
Ponownie nie widać tutaj wielkiej różnicy. W Objective-C odwołaliśmy się do właściwości “class” .
Oto jak wygląda odpowiednik słowa kluczowego “is” w objective-C
bool chceck = myObj is MyClass;
Class c = [MyObject class];
Class c2 = myObject.class;
BOOL yy = [myObject isKindOfClass:c2];
BOOL yyy = [myOtherObject isKindOfClass:[myOtherObject class]];
NSLog(@"1: %s \n2: %s",yy ? "true" : "false",yyy ? "true" : "false");
A jak sprawdzić czy dana klas implementuje dany protokół? Rozwiązanie zagadki poniżej.
bool chceck2 = myObj is IEnumerable<string>;
BOOL hasProtcol = [myObject conformsToProtocol:@protocol(MyDelegate)];
Przejdźmy do bardziej złożonych przykładów.
Wszystkie właściwości danego obiektu
PropertyInfo[] props = myObj.GetType().GetProperties();
foreach(PropertyInfo pi in props)
{
string actualName = pi.name;
}
unsigned int outCount;
objc_property_t *properties = class_copyPropertyList([myObject class],&outCount);
for(int i = 0; i < outCount;i++)
{
objc_property_t prop = properties[i];
const char* name = property_getName(prop);
NSString* realName = [NSString stringWithUTF8String:name];
NSLog(realName);
}
Uzyskanie wartości właściwość znając jej nazwę
object val = myObj.GetType().GetProperty("PropertyName").GetValue(myObj, null);
id val = [myObject valueForKey:@"obj"];
Wywołanie metody bez parametrów znając jej nazwę
myObj.GetType().GetMethod("Method").Invoke(myObj);
SEL method = NSSelectorFromString(@"DoSomething");
[myOtherObject performSelector:method];
Wywołanie metody w taki sposób jest trochę niebezpieczne. Warto zauważyć, że metoda “DoSomething” nic nie zwraca a ja jak idiota chciałem wynik tej metody przypisać do zmiennej. Niestety, ale wyjątki w Objective-C nie są tak jasne, jak w C# więc trzeba definitywnie myśleć i uważać.