To give a bit of context of why I\'m asking this: basically I would like to change the location of the myLocationButton
of the google map on iOS. So I first fet
this did it.. i'm not sure if this counts as an actual answer since i just got around the problem by simply calling [self layoutIfNeeded]
instead of [self layoutSubviews]
void _autolayout_replacementLayoutSubviews(id self, SEL _cmd)
{
// calling super
struct objc_super superTarget;
superTarget.receiver = self;
superTarget.super_class = class_getSuperclass(object_getClass(self));
objc_msgSendSuper(&superTarget, @selector(layoutSubviews));
// to get around calling layoutSubviews and having
// a recursive call
[self layoutIfNeeded];
objc_msgSendSuper(&superTarget, @selector(layoutSubviews));
}
- (void)replaceGMSUISettingsViewImplementation
{
class_addMethod(NSClassFromString(@"GMSUISettingsView"), @selector(_autolayout_replacementLayoutSubviews), (IMP)_autolayout_replacementLayoutSubviews, "v@:");
Method existing = class_getInstanceMethod(NSClassFromString(@"GMSUISettingsView"), @selector(layoutSubviews));
Method new = class_getInstanceMethod(NSClassFromString(@"GMSUISettingsView"), @selector(_autolayout_replacementLayoutSubviews));
method_exchangeImplementations(existing, new);
}
UPDATE
If you want to preserve original implementation you can get it and call it inside the blockImp. Then after that call [[aClass superclass] layoutSubviews] or call it with function pointer. Note that all this code need some error check and exception prevents.
//get method encoding
const char * encoding = method_getTypeEncoding(class_getInstanceMethod(NSClassFromString(@"GMSUISettingsView"), @selector(layoutSubviews)));
void(^oldImplementation)(id aClass, SEL aSelector) = imp_getBlock(method_getImplementation(class_getInstanceMethod(NSClassFromString(@"GMSUISettingsView"), @selector(layoutSubviews))));
id blockImp = ^void(id aClass, SEL aSelector)
{
//old imlpementation
oldImplementation(aClass, aSelector);
//calling [super layoutSubviews]
IMP aImp = [[aClass superclass] methodForSelector:@selector(layoutSubviews)];
id (*func)(id, SEL) = (void *)aImp;
func([aClass superclass], @selector(layoutSubviews));
};
IMP newImp = imp_implementationWithBlock(blockImp);
class_replaceMethod(NSClassFromString(@"GMSUISettingsView"), @selector(layoutSubviews), newImp, encoding);
ORIGINAL ANSWER
I'm sorry but I didn't fully understand do you want to completely override 'layoutsubviews' or to have original implementation and change just part of it. If it's the first you could use class_replaceMethod instead of swizzling. It will have performance hits though! Something like this should do the trick:
//get method encoding
const char * encoding = method_getTypeEncoding(class_getInstanceMethod(NSClassFromString(@"GMSUISettingsView"), @selector(layoutSubviews)));
id blockImp = ^void(id aClass, SEL aSelector)
{
//what you want to happen in layout subviews
};
IMP newImp = imp_implementationWithBlock(blockImp);
class_replaceMethod(NSClassFromString(@"GMSUISettingsView"), @selector(layoutSubviews), newImp, encoding);
I've not tested this on device/simulator but something like this should work for you. I assume you know it's not a really bright idea to manipulate private classes ;)