objective-c - ObjC 内部结构。为什么我的鸭子打字尝试失败了?

标签 objective-c

我尝试使用 id 在 Objective-C 中创建鸭子类型。这个概念在理论上看起来不错,但在实践中却失败了。我无法在我的方法中使用任何参数。方法已调用,但参数错误。我得到了对象的 BAD_ACESS 和基元的随机值。我在下面附上了一个简单的示例。

问题: 有谁知道为什么方法参数错误? Objective-c 的底层发生了什么?

注意:我对细节感兴趣。我知道如何使下面的示例起作用。

示例: 我创建了一个简单的类 Test,它使用属性 id test 传递给其他类。

@implementation Test
- (void) aSampleMethodWithFloat:(float) f andInt: (int) i {
    NSLog(@"Parameters: %f, %i\n", f, i);
}
@end

然后在类中执行以下循环:

for (int i=0; i < 10; ++i) {
    float f=i*0.1f;
    [tst aSampleMethodWithFloat:f andInt:i]; // warning no method found.
}

这是我得到的输出。正如您所看到的,该方法被调用,但参数错误。

Parameters: 0.000000, 0
Parameters: -0.000000, 1069128089
Parameters: -0.000000, 1070176665
Parameters: 2.000000, 1070805811
Parameters: -0.000000, 1071225241
Parameters: 0.000000, 1071644672
Parameters: 2.000000, 1071854387
Parameters: 36893488147419103232.000000, 1072064102
Parameters: -0.000000, 1072273817
Parameters: -36893488147419103232.000000, 1072483532

更新:

我偶然发现,当我使用 for 循环向类添加 aSampleMethodWith... 声明时,警告消失并且测试中的方法消失类被正确调用。

更新 2: 正如 JeremyP 所指出的,问题的直接原因是 float 被视为 double 。但有人知道为什么吗? (遵循 5why 原则:))。

根据 @eman 的说法,该调用被转换为简单的 C 函数调用和编译器指令以获取 SEL。所以@selector 会感到困惑。但为什么?编译器在第一个方法调用中拥有所有必需的类型信息。有谁知道有关 Objective-C 内部结构的良好信息来源吗?我搜索过 Objective-C 编程语言,但没有找到答案。

最佳答案

默认情况下,浮点值作为 double 而不是 float 传递。编译器不知道,在 [tst aSampleMethodWithFloat:f andInt:i]; 发生时,它只应该传递一个浮点型,因此它将 f 提升为 double 型。这意味着,在该方法中,当编译器知道它正在处理浮点型时,f 是由传递给该方法的 double 的前四个字节形成的浮点型,而 i 是由传递给该方法的 double 形成的 int 型从传递的 double 的后四个字节开始。

您可以通过以下任一方式解决此问题

  • 将 aSampleMethodWithFloat:andInt: 的第一个参数更改为 double
  • 将 Test 的接口(interface)声明导入到您使用它的文件中。

注意,在 C 中使用 float 时,除了占用少量空间外,没有任何好处。您还不如在任何地方使用 double 。

关于objective-c - ObjC 内部结构。为什么我的鸭子打字尝试失败了?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2709383/

相关文章:

ios - 使用 NSLocalNotification 的 userInfo 字典传递 NSManagedObject

objective-c - 我们应该在 viewDidLoad 还是 viewDidAppear 中调用广告?

ios - 将 UILabel 设置为 Null 值导致异常

objective-c - 理解弱引用

ios - 在 didSelectRowAtIndexPath Parse.com 中选择收件人时 PFUser objectId 错误

ios - UINavigationController 包含、iOS7 和状态栏。漏洞?

iphone - 更改 UIView 的位置不起作用

iphone - Objective-C 属性 - 使用 [self myProperty] 或 self.myProperty 是否比 myProperty 慢?

ios - 在特定时间间隔后更改 UICollectionView 中的图像

iphone - 如何在表格 View 中的两个单元格之间留出空间?