【问题标题】:Too many arguments to function call, expected 0, have 3函数调用的参数太多,预期为 0,有 3
【发布时间】:2014-09-15 08:54:24
【问题描述】:

这可以在 Xcode 5 中正常编译/工作,但在 Xcode 6 Beta 4 中会导致编译错误:

objc_msgSend(anItem.callback_object,
NSSelectorFromString(anItem.selector), dict);

这是一个第 3 方组件,所以虽然我有源代码,但它并不是我真正的代码,我很犹豫是否要更改它(尽管我个人认为 'wtf why are他们使用objc_msgSend??')。

带有可能有用细节的图片(错误浏览器中的错误):

【问题讨论】:

标签: xcode


【解决方案1】:

我找到了答案,它在 2014 年 WWDC“LLVM 中的新功能”的第 417 节会议中。如果您在 3rd 方库(例如 Apsalar)中找到此代码,则更新到最新版本可以修复它(可能是因为它不是作为 lib 分发的,哈哈)。有关这些调用的转换示例,请参阅 THObserversAndBinders 库 - 我正在使用它并注意到作者更新了代码,例如这里:

https://github.com/th-in-gs/THObserversAndBinders/blob/master/THObserversAndBinders/THObserver.m

【讨论】:

  • 很好的答案。它解决了我的轮播问题。我刚刚从 github 下载了新的 FXImageView。是的,它有效谢谢@Alex the Ukranian
【解决方案2】:

只是为了看一个 WWDC 视频,答案是你需要强类型 objc_msgSend 让编译器来构建它:

typedef void (*send_type)(void*, SEL, void*);
send_type func = (send_type)objc_msgSend;
func(anItem.callback_object, NSSelectorFromString(anItem.selector), dict);

下面是另一个直接调用实例方法的示例,如下所示:

IMP methodInstance = [SomeClass instanceMethodForSelector:someSelector];
methodInstance(self, someSelector, someArgument);

对 methodInstance 使用强类型让 LLVM 编译器满意:

typedef void (*send_type)(void*, SEL, void*);
send_type methodInstance = (send_type)[SomeClass instanceMethodForSelector:someSelector];
methodInstance(self, someSelector, someArgument);

不要忘记根据您的具体需要设置 send_type 的返回和参数类型。

【讨论】:

  • Swift 很烂,因为它没有隐式类型转换。您甚至必须将每个 int 转换为 float/double。现在看来,Apple 强迫所有开发人员这样做以使 swift 更受欢迎。
  • 好在 swift 迫使我们强制转换所有这些类型,这与 C 不同,否则我们很容易会遇到大量与数学相关的错误,而且人们不会那么容易知道它们来自哪里。正是由于隐式类型转换,在 C 语言中,您很容易陷入溢出、舍入错误等问题。这样的例子不胜枚举。而且它们很难调试。
【解决方案3】:

如果您认为必须这样做很烦人且毫无意义,您可以通过将“启用对 objc_msgSend 调用的严格检查”设置为 no 来禁用构建设置中的检查

【讨论】:

  • 早上好。非常感谢!
  • Pfiouuuu... 很高兴我找到了你的答案!
  • 如果错误源自可可豆荚,我认为这不是一个选项。
  • 这是 cocoapod 的一个选项,但您必须滚动到工作区中的“Pods”项目(在我的情况下,滚动到实际的目标 pod)
  • 不错的答案,即时解决方案
【解决方案4】:

这也可能是由使用 Cocoapods 0.36.beta.2 运行 pod install 引起的。我已经向 CocoaPods 报告了这个问题。使用 CocoaPods 的“解决方法”0.35

【讨论】:

  • 对我来说,Cocoapods 0.36.1 中仍然存在问题
  • 要降级,使用两个命令:sudo gem uninstall cocoapods 后跟sudo gem install cocoapods -v 0.35.0
  • 问题仍然存在于 0.37.0 必须恢复到 0.35.0 才能正常工作!谢谢@Maciej Swic
  • 如果你有多个版本的 cocoapods 你应该删除高于 0.35.0 的版本来解决这个问题。
【解决方案5】:

Maciej Swic 是对的。这是在将 Cocoapods 更新到 0.36.beta.2 后在 Pods 中引起的。 我通过类型转换 objc_msgSend 找到了一个简单的解决方法:

id (*typed_msgSend)(id, SEL) = (void *)objc_msgSend;
id<MyProtocol> obJ = typed_msgSend(controller, @selector(myselector));

【讨论】:

    【解决方案6】:

    按照公认的答案 - 在给定的代码库中找到答案可能对少数人来说很麻烦,所以这里是应该解决这个问题的快速快照。

    我在我的项目中编辑了 ActionSheetPicker 中的代码,这导致了同样的问题,就像这样 -

    - (void)notifyTarget:(id)target didSucceedWithAction:(SEL)action origin:(id)origin {
        if ([target respondsToSelector:action]) {
            ((id (*)(id, SEL, NSDate *, id))objc_msgSend)(target, action, self.selectedDate, origin);
            return;
        } else if (nil != self.onActionSheetDone) {
            self.onActionSheetDone(self, self.selectedDate, origin);
            return;
        }
    
        NSAssert(NO, @"Invalid target/action ( %s / %s ) combination used for ActionSheetPicker", object_getClassName(target), (char *)action);
    }
    

    因此,请查看 objc_msgSend 部分与您当前代码相比的变化。 这个想法是包含您传递给objc_msgSend的参数类型

    【讨论】:

      【解决方案7】:

      我在使用 QuickDialog 时遇到了这个错误。按照 james_alvarez 的回答,但对于 AppCode,转到 Project Settings,然后单击 Project/Shared Settings 下的 QuickDialog,向下滚动到 ENABLE_STRICT_OBJC_MSGSEND 并输入 NO 进行调试和发布。

      【讨论】:

        【解决方案8】:

        您也可以使用安装后挂钩禁用此功能:

        post_install do |installer|
            installer.pods_project.targets.each do |target|
                target.build_configurations.each do |config|
                    config.build_settings['ENABLE_STRICT_OBJC_MSGSEND'] = 'NO'
                end
            end
        end
        

        【讨论】:

        • 你可以写在你的pod文件底部
        【解决方案9】:
        #include <objc/message.h>
        
        void foo(void *object) {
          typedef void (*send_type)(void *, SEL, int);
          send_type func = (send_type)objc_msgSend;
          func(object, sel_getUid("foo:"), 5);
        }
        

        【讨论】:

        • 好的答案解释并提供代码。考虑更新您的答案,以包含有关此代码如何工作以及为什么它是最佳选择的说明。
        【解决方案10】:

        这段代码重现了错误:

        - (void)reportSuccess:(void(^)(void))success
        {
            success(what_is_this);
        }
        

        猜猜错误在哪里?当然,what_is_this 没有被声明,但不知何故神奇地显示了另一个错误。换句话说看起来如果你有块,你可以在调用它的时候放任何参数,甚至是不存在的变量。

        【讨论】:

          【解决方案11】:

          Enable strict checking of objc_msgSend Calls 设置为NO,解决了我的问题。下面是截图

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-11-03
            • 2019-07-27
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多