In Xcode6 Gold Master, Using Objc_Msgsend Now Throws a Syntax Error Saying the Number of Arguments Is Wrong

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:

  1. Both field names and types of objc_super have changed since your code was written, some of this is documented in the comments.
  2. The prototype for objc_msgSendSuper has also changed to just void objc_msgSendSuper(void), the previous prototype is also there id _Nullable
    objc_msgSendSuper(struct objc_super * _Nonnull super, SEL _Nonnull op, ...)
    . 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.

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



Leave a reply



Submit