Objective-C Typ Inference
-
21-09-2019 - |
Frage
Okay, ich habe das Gefühl, dass Sie schnell guys'll der Lage sein, darauf hinzuweisen, warum ich darüber so verwirrt, aber ich habe eine Frage, warum die folgenden führt nicht zu einem Compiler-Fehler oder Warnung:
NSString * intValue = [ NSString stringWithFormat:@"int = %i", [ [ self.selectedObject valueForKey:name ] integerValue ] ];
selectedObject
ist ein NSObject
und name
geschieht der Name eines @property
vom Typ int
sein.
Was mich verwirrt ist, warum der Compiler durchaus bereit ist anzunehmen, dass das Rückergebnis von [ self.selectedObject valueForKey:name ]
vom Typ NSNumber *
ist (ohne es zu typecasting), um Kette die Nachricht mit einem Aufruf an integerValue
.
Offensichtlich KVC hüllt Nicht-Objekt „Nummer“ Typen in NSNumber
, aber es gibt keine Möglichkeit für den Compiler, dass -valueForKey:
zu wissen, wird ein NSNumber *
in diesem speziellen Fall zurück.
Warum funktioniert dieses Ergebnis in einer Compiler-Warnung entlang der Linien von „id
kann nicht reagieren auf‚-integerValue
‘“?
Lösung
Ich hoffe, dass ich es richtig: Das liegt daran, id
ist „special“. Objekte des id
Typ kann jede gewünschte Nachricht gesendet werden, gibt es keine Überprüfung durch den Compiler und alles wird geprüft, im laufenden Betrieb geschehen ist. Oder, mit anderen Worten, die id
Art ist die „dynamische Typisierung“ Teil von Objective-C, während alle anderen Arten (wie NSObject
) die „statische Typisierung“ Teil sind.
Auf diese Weise können Sie wählen, wo Sie statische Typisierung verwenden wollen, und wo Sie dynamische Eingabe verwenden möchten. Es ist völlig legal, so etwas zu tun:
id str1 = @"Hello";
id str2 = [str1 stringByAppendingString:@", world"];
Aber man in der Regel die Saiten Typ „fest“, wie NSString
s, weil Sie die Bequemlichkeit der Kompilierung-statische Typprüfung erhalten, und nur auf dynamische Typisierung zurückgreifen, wo die statische in die Quere kommen würde, wie in der valueForKey
Situation.
Andere Tipps
Die Zeit ist vergangen und wir haben eine bessere Typinferenz jetzt dank der __auto_type
da Xcode verfügbar 8. So, jetzt können Sie tun,
#define let __auto_type const
#define var __auto_type
let a = @[@"pew pew"];
var b = 2;
b = a; //compiler warning "Incompatible pointer to integer conversion assigning to 'int' from 'NSArray *__strong const'"
und viel mehr
In der Tat, ich mochte das so sehr, ich dies als pod für Bequemlichkeit gemacht.
pod 'SwiftyObjC'