0

I have a situation where I want to call a method on a target where calling perform selector gives the error: PerformSelector may cause a leak because its selector is unknown.

To get round this I'm using the excellent solution from this SO question:

if (self.target) {
    IMP imp = [self.target methodForSelector:self.selector];
    void (*func)(id, SEL, id) = (void *)imp;
    func(self.target, self.selector, argument);
}

Now this code is part of a framework that I'm using in a Swift project and it's causing a crash.

If I ignore the warnings and use [self.target performSelector:self.selector withObject:self.argument]; It works fine.

So... I'm assuming this is to do with fundamental Swift vs. Objective-C message sending architecture. Please could someone tell me a) What's going on? b) how to get around it.

Community
  • 1
  • 1
Rob Sanders
  • 4,398
  • 3
  • 26
  • 52
  • In Swift 2.0 you can just call `performSelector` directly. – matt Oct 16 '15 at 15:52
  • The framework is in Objective-C only. The swift is the project which makes use of this framework. – Rob Sanders Oct 16 '15 at 16:00
  • Okay, well, I think I've answered the question, because _you've_ answered the questions. You have an approach that works so I don't even see what the question _is_ at this point. – matt Oct 16 '15 at 16:02
  • The question is how can I get rid of the warning (not suppress) and have it work with swift? Also I would quite like to know the differences between the Objective-C and Swift messaging system if anyone knows. – Rob Sanders Oct 16 '15 at 16:05
  • what is `sender`? why is it different than `self.target`? – newacct Oct 17 '15 at 06:34
  • `sender` is the object that is sending the message. `self.target` is the object that is receiving the message. – Rob Sanders Oct 17 '15 at 18:04
  • 1
    @RASS: So why do you do `func(sender, self.selector, argument)`? It should be `func(self.target, self.selector, self.argument)` – newacct Oct 18 '15 at 08:16
  • Ha! Ah yes. That's a typo. – Rob Sanders Oct 18 '15 at 13:31

2 Answers2

1

The most direct way to send the message (assuming it takes one object parameter and returns nothing) is:

void (*func)(id, SEL, id) = (void (*)(id, SEL, id))objc_msgSend;
func(self.target, self.selector, self.argument);
newacct
  • 110,405
  • 27
  • 152
  • 217
  • Works perfectly thank you! What's the difference between what I was doing and this code? I'm assuming that my code asks the target for the method whereas here you're constructing it independently using `objc_msgSeng`? Thanks again! – Rob Sanders Oct 17 '15 at 18:14
0

If I ignore the warnings and use [self.target performSelector:self.selector withObject:self.argument]; It works fine.

My advice, then, would be to suppress the warnings and just call performSelector:....

matt
  • 447,615
  • 74
  • 748
  • 977