Napotkano na dziwne zachowanie podczas używania funkcji [NSMethodSignature getArgumentTypeAtIndex]. Zwraca mi znak "@" typu BOOL, który w złym zgodnie z celem-c type encodings. Jeśli korzystam z biblioteki objc \ runtime.h metoda method_getTypeEncoding Typ BOOL jest poprawnie reprezentowany jako "B", jednak nie rozumiem, dlaczego nie działa z warstwą wyższego poziomu NSMethodSignature. Poniższy kod demonstruje problem:Kodowanie BOOL jest nieprawidłowe od NSMethodSignature
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
NSInvocation* inv = [NSInvocation invocationWithMethodSignature:[self methodSignatureForSelector:@selector(viewDidAppear:)]];
const char* encFromGetArgument = [[inv methodSignature] getArgumentTypeAtIndex:2];
const char* encFromMethodSignature = method_getTypeEncoding(class_getInstanceMethod([self class], @selector(viewDidAppear:)));;
const char* methodEncodingPure = [[[[NSString stringWithUTF8String:encFromMethodSignature] componentsSeparatedByCharactersInSet:[NSCharacterSet decimalDigitCharacterSet]] componentsJoinedByString:@""] UTF8String];//remove stack sizes
NSLog(@"BOOL arg from NSMethodSignature: %s", encFromGetArgument);
NSLog(@"BOOL arg from objc/runtime.h: %c", methodEncodingPure[3]);//first type is for return, second is target, third is selector
}
Powyższy niespodziewanie (przynajmniej dla mężczyzn) drukuje następujące:
BOOL arg z NSMethodSignature: @
BOOL arg z objc/runtime.h : B
Używam obecnie własnej implementacji, aby uniknąć tego dziwnego zachowania, ale chcę wiedzieć, czy czegoś brakuje lub jest j. ust błąd. Moją jedyną wskazówką jest to, że BOOL jest prymitywny i tak nie może być użyty bezpośrednio podczas wywoływania metod obiektywnych-c. Jednak gdy spróbuję to sprawdzić [obiekt isKingOfClass: [NSNumber class]] zwraca NO.
UPDATE
Ok Mam XCode aktualizacji do najnowszej wersji (6.1) i 6A1052d sytuacji znacznie się poprawia. Jednak moim problemem jest teraz odróżnienie kodowania znaków bez znaku od prawdziwego kodowania Bool. Wiem, że w starych wersjach BOOL jest typedef jako char, ale w jaki sposób mogę dokonać prawdziwego kodowania BOOL? Teraz moje wyniki są następujące:
Dla Simulator iPhone6 a rzeczywistym urządzeniu iPhone6 dostałam:
argument 2: -------- -------- -------- --------
type encoding (B) 'B'
flags {}
BOOL arg from NSMethodSignature: B
BOOL arg from objc/runtime.h: B
co jest niesamowite, jednak dla symulator iphone4s, a prawdziwe urządzenie iPhone5 jestem otrzymywanie:
argument 2: -------- -------- -------- --------
type encoding (c) 'c'
flags {isSigned}
BOOL arg from NSMethodSignature: c
BOOL arg from objc/runtime.h: c
Jestem prawie pewien, że jeśli sprawdzę iPhone5s to Otrzymam takie samo wyjście jak iPhone6 (ponieważ myślę, że to wszystko dotyczy architektury 64-bitowej). Więc moim pytaniem jest teraz, jak właściwie obejść starsze urządzenia, jak odróżnić dla nich BOOL z BOOL? Czy powinienem po prostu założyć, że jeśli kodowanie to "c", a argument jest równy "1", mamy TAK, a dla "0" mamy NIE?
nie mogę odpowiedzieć, że pytanie, jednak nie jestem pewien, co ARC zrobi z obiektu zwróconego przez '[inw methodSignature]', z którego można dostać od ' const char * 'from. Oczywiście, że bufor znajduje się w domenie obiektów (pod jego zarządzaniem), więc wyobrażam sobie, że nie powinieneś tworzyć tymczasowego obiektu i usuwać go w ten sposób. – Droppy
Ponieważ methodSignature to klasa ObjectiveC, jestem pewien, że będzie działał poprawnie w ARC. Główną kwestią jest to, dlaczego zwraca nieprawidłowe wartości. –
Możliwe, że przyczyną problemu jest użycie tymczasowego obiektu. Wypróbuj za pomocą zmiennych, które nie są tymczasowe. – Droppy