Alex the Ukrainian
Alex the Ukrainian

Reputation: 4558

Too many arguments to function call, expected 0, have 3

This compiles/works fine with Xcode 5, but causes a compile error with Xcode 6 Beta 4:

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

This is a 3rd-party component, so while I have the source code, it's not really my code and I'm hesitant to change it much (despite my personal opinion of 'wtf why are they using objc_msgSend??').

Image with possibly useful detail (error in error browser): enter image description here

Upvotes: 62

Views: 35581

Answers (12)

Senthelazy
Senthelazy

Reputation: 1

((void(*)(id,SEL,id))objc_msgSend)(target, sel, newValue);

Change the code like above, after Xcode 12, simply setting Setting Enable strict checking of objc_msgSend Calls to NO does not help. modify the (id,SEL,id) for your need, for example(id,SEL) for two arguments, etc

Upvotes: 0

arunjos007
arunjos007

Reputation: 4355

Setting Enable strict checking of objc_msgSend Calls to NO, solved my issue. Below is the screenshot

enter image description here

Upvotes: 15

Borzh
Borzh

Reputation: 5195

This block of code reproduces the error:

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

Guess where error is? Of course, what_is_this is not declared, but somehow magically it shows another error. In other words looks like if you have block, you can put any parameters when calling it, even non existent variables.

Upvotes: -1

#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);
}

Upvotes: 3

You can also disable this with a post install hook:

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

Upvotes: 6

Al Lelopath
Al Lelopath

Reputation: 6778

I was getting this error with QuickDialog. Following on to james_alvarez's answer but for AppCode, go to Project Settings, then click on QuickDialog under Project/Shared Settings, scroll down to ENABLE_STRICT_OBJC_MSGSEND and enter NO for Debug and Release.

Upvotes: 6

Munim
Munim

Reputation: 2768

Following the accepted answer- to find the answer in the given codebase might be cumbersome for few, so here's the quick snap that should solve this problem.

I edited the code in ActionSheetPicker in my project, which was causing me the same problem, like this -

- (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);
}

So look at the change that objc_msgSend portion has, compared to your current code. The idea is to include the type of the parameters you are passing to objc_msgSend

Upvotes: 0

Sahil Kapoor
Sahil Kapoor

Reputation: 11773

Maciej Swic is right.This is caused in Pods after updating Cocoapods to 0.36.beta.2. I found a simple workaround by type casting objc_msgSend:

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

Upvotes: 9

Maciej Swic
Maciej Swic

Reputation: 11359

This could also be caused by running pod install using Cocoapods 0.36.beta.2. I have reported the issue to CocoaPods. "Workaround" by using CocoaPods 0.35

Upvotes: 20

James Alvarez
James Alvarez

Reputation: 7219

If you think having to do this is annoying and pointless you can disable the check in the build settings by setting 'Enable strict checking of objc_msgSend Calls' to no

Upvotes: 124

Vlad Grigorov
Vlad Grigorov

Reputation: 11378

Just to spare watching a WWDC video, the answer is you need to strong type objc_msgSend for the compiler to build it:

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

Here is another sample when calling instance methods directly, like this:

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

Use strong type for methodInstance to make LLVM compiler happy:

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

Do not forget to set send_type's return and argument types according to your specific needs.

Upvotes: 26

Alex the Ukrainian
Alex the Ukrainian

Reputation: 4558

I found the answer, and it's in Session 417 from 2014 WWDC "What's New in LLVM". If you find this code in a 3rd party library, such as Apsalar, updating to the latest version fixes it (probably because it's not distributed as a lib, ha). For an example of casting of these calls, see THObserversAndBinders library - I'm using it and noticed that the author updated the code, such as here:

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

Upvotes: 23

Related Questions