Reputation: 4558
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):
Upvotes: 62
Views: 35581
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
Reputation: 4355
Setting Enable strict checking of objc_msgSend Calls
to NO
, solved my issue. Below is the screenshot
Upvotes: 15
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
Reputation: 299
#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
Reputation: 5225
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
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
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
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
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
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
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
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