in xcode6 gold master, using objc_msgSend now throws a syntax error saying the number of arguments is wrong
See just a few lines above you referred.
/*
* ...
*
* These functions must be cast to an appropriate function pointer type
* before being called.
*/
You can call it like:
#import <objc/runtime.h>
#import <objc/message.h>
id<MyProtocol> topLayoutGuideObj = ((id (*)(id, SEL))objc_msgSend)(viewController, @selector(myselector));
OR
id (*typed_msgSend)(id, SEL) = (void *)objc_msgSend;
id<MyProtocol> topLayoutGuideObj = typed_msgSend(viewController, @selector(myselector));
Type of self and delegate for casting to fix objc_msgSend wrong number of arguments error?
void (*my_objc_msgSend)(id, SEL, id, id, id, id) = (__typeof(my_objc_msgSend))objc_msgSend;
my_objc_msgSend(theDelegate, @selector(splitViewController:willHideViewController:withBarButtonItem:forPopoverController:), self, master, button, popover);
in objc, id
is a point of struct. any object (which class inherit from NSObject
) can use id
instead.
please post the log if still crash.
After iOS 9, splitViewController:willHideViewController:withBarButtonItem:forPopoverController:
is deprecated, you should use splitViewController:willChangeToDisplayMode:
instead.
Too many arguments to function call, expected 0, have 2
Note: The code below has not been executed as it is just a fragment, however it has been compiled by Xcode 10 & 11. There may be mistakes or other issues.
In Xcode right-click on objc_super
and objc_msgSendSuper
and select "Jump to Definition" which will open the system files containing the definitions. This will show two things:
- Both field names and types of
objc_super
have changed since your code was written, some of this is documented in the comments. - The prototype for
objc_msgSendSuper
has also changed to justvoid objc_msgSendSuper(void)
, the previous prototype is also thereid _Nullable
. Using the previous prototype the call to this function in the code could be made without a cast, with this new prototype a cast is needed.
objc_msgSendSuper(struct objc_super * _Nonnull super, SEL _Nonnull op, ...)
Making the changes indicated to the code gives:
// A typedef for objc_msgSendSuper which takes only the required (first two) arguments
typedef void *(*NoAdditionalArgMsgSendSuper)(struct objc_super *super_class, SEL selector);
void* callSuper0(id self, Class superClass, SEL _cmd)
{
struct objc_super super;
// .receiver is now defined as "__unsafe_unretained _Nonnull id" so no bridge cast required
super.receiver = self;
// .super_class is new name for .class
super.super_class = superClass != NULL ? superClass : class_getSuperclass(object_getClass(self));
// cast objc_msgSendSuper to the correct type and then call
return ((NoAdditionalArgMsgSendSuper)objc_msgSendSuper)(&super, preprocessSEL(_cmd));
}
HTH
Addendum
Following on from your comment and code post as another answer.
In your code you write:
void* (*objc_msgSendSuperTyped)(id self, SEL _cmd) = (void*)objc_msgSendSuper;
return objc_msgSendSuperTyped((id) &super, preprocessSEL(_cmd));
Making a typed copy of the function pointer, rather than just casting on use as our earlier code, is fine. However your code should produce an error from Xcode as you are trying to case a non-retained type (&super
- a struct pointer) to a retained one (id
) – which requires a bridge cast.
The solution here is to give objc_msgSendSuperTyped
the correct type, its first argument should be a struct pointer:
void* (*objc_msgSendSuperTyped)(struct objc_super *self, SEL _cmd) = (void*)objc_msgSendSuper;
return objc_msgSendSuperTyped(&super, preprocessSEL(_cmd));
From your comment:
I had to change super.super_class to super.class for it to work, it now throws other errors unrelated.
This suggests you've some unusual settings, in the declaration of objc_super
we find:
#if !defined(__cplusplus) && !__OBJC2__
/* For compatibility with old objc-runtime.h header */
__unsafe_unretained _Nonnull Class class;
#else
__unsafe_unretained _Nonnull Class super_class;
#endif
__OBJC2__
is defined by default in Xcode 11 (and plenty of earlier versions) for .m
and .mm
files, __cplusplus
is defined for .mm
files only. So the condition !defined(__cplusplus) && !__OBJC2__
is false
and the field is therefore named super_class
...
You might wish to determine why __OBJC2__
is apparently not defined for the source you are trying to convert...
Can't set String to URLWithString
I believe you are missing the correct NSString method
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"fb://profile/%g",self.currentVriend.fbid]];
Related Topics
Dynamic Uiimageview Size Within Uitableview
View at the Bottom in a Uiscrollview, with Autolayout
Uitextfield - Capture Return Button Event
How to Delete App Build in New Itunes Connect Site
How to Add Textfield in Uialertcontroller
Sendasynchronousrequest Was Deprecated in iOS 9, How to Alter Code to Fix
How to Subclass Uitableviewcontroller in Swift
How to Populate Uitableview from the Bottom Upwards
Avplayer Resuming After Incoming Call
Allow Uiscrollview and Its Subviews to Both Respond to a Touch
How to Downscale a Uiimage in iOS by the Data Size
How to Compare Ssl Certificates Using Afnetworking
How to Find the Purple Port for the Front Most Application in iOS 5 and Above
Avqueueplayer Playback Without Gap and Freeze
How to Create and Send the JSON Data to Server Using Swift Language
Application Sticks on Osspinlocklockslow
Location Update Even When App Is Killed/Terminated
Sudzc Arc Version - Objc_Msgsend Call Causes Exc_Bad_Access Using 64-Bit Architecture