الهدف-C نوع الاستدلال
-
21-09-2019 - |
سؤال
حسنًا ، لدي شعور بأنكم ستتمكنون من الإشارة بسرعة إلى السبب في أنني في حيرة من أمري بشأن هذا ، لكن لدي سؤال حول سبب عدم وجود خطأ في المترجم أو تحذير:
NSString * intValue = [ NSString stringWithFormat:@"int = %i", [ [ self.selectedObject valueForKey:name ] integerValue ] ];
selectedObject
هو NSObject
, ، و name
يحدث أن يكون اسم أ @property
من النوع int
.
ما يحيرني هو السبب في أن المترجم مستعد تمامًا لافتراض أن نتيجة العودة [ self.selectedObject valueForKey:name ]
من النوع NSNumber *
(بدون تكوينه) من أجل ربط الرسالة باستخدام مكالمة إلى integerValue
.
من الواضح أن KVC يختتم أنواع "الأرقام" غير الكائن NSNumber
, ، ولكن لا توجد وسيلة حتى يعرف المترجم ذلك -valueForKey:
سيعود NSNumber *
في هذه الحالة بالذات.
لماذا لا يؤدي هذا إلى تحذير مترجم على غرار ""id
قد لا ترد على '-integerValue
'"?
المحلول
آمل أن أحصل عليها بشكل صحيح: هذا بسبب id
إنه خاص". كائنات id
يمكن إرسال النوع أي رسالة تريدها ، ولا يوجد فحص من قبل المترجم وسيتم فحص كل شيء في وقت التشغيل. أو ، وبعبارة أخرى ، id
النوع هو جزء "الكتابة الديناميكية" من الهدف-C ، في حين أن جميع الأنواع الأخرى (مثل NSObject
) هي جزء "الكتابة الثابتة".
وبهذه الطريقة ، يمكنك اختيار المكان الذي تريد استخدامه في الكتابة الثابتة ، وأين تريد استخدام الكتابة الديناميكية. من القانوني تمامًا أن تفعل شيئًا كهذا:
id str1 = @"Hello";
id str2 = [str1 stringByAppendingString:@", world"];
ولكن عادة تكتب الأوتار "بإحكام" NSString
S ، لأنك تحصل على راحة فحص النوع الثابت في وقت الترجمة ، واللجوء فقط إلى الكتابة الديناميكية حيث يمكن أن يعترض الساكنة ، كما في valueForKey
قارة.
نصائح أخرى
تم تمرير الوقت ولدينا أفضل للاستدلال الآن بفضل __auto_type
متوفر منذ Xcode 8. لذا يمكنك الآن القيام بذلك
#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'"
في الواقع ، لقد أحببت هذا كثيرًا ، لذا قمت بذلك كجنة للراحة.
pod 'SwiftyObjC'