Projects

Ticket #330 (new defect)

Opened 2 years ago

Last modified 14 months ago

forwardingTargetForSelector not working properly in Objective-C classes loaded in MR

Reported by: diffengr@… Owned by: lsansonetti@…
Priority: major Milestone: MacRuby 1.0
Component: MacRuby Keywords: #reduction
Cc:

Description (last modified by martinlagardette@…) (diff)

When using forwardingTargetForSelector: to create a wrapper class in ObjC, it does not work in MacRuby.

It's kind of a complicated setup, so I've created a minimal-ish project in github containing ObjC and MacRuby code to illustrate the problem. It's here:

 http://github.com/diffengr/macruby_forwarding_invocation_example

That contains an XCode project and a rakefile. It has the ObjC classes Candy and CandyWrapper, and they both have the NSString* property flavor. CandyWrapper declares that property @dynamic, and forwards it to Candy.

Here's the code that works in ObjC.

  Candy* rootBeerCandy = [[Candy alloc] init];
  rootBeerCandy.flavor = @"Root Beer";

  CandyWrapper* rootBeerWrapper = [[CandyWrapper alloc]
initWithCandy:rootBeerCandy];
  NSLog(@"Candy#flavor \"%@\", Wrapper#flavor \"%@\"", rootBeerCandy.flavor,
          rootBeerWrapper.flavor);

If you load and run the xcode project in this directory, you'll get this output:

  NSLog[...] <CandyWrapper: 0x104fb0> forwarding flavor to <Candy: 0x103380>
  NSLog[...] Candy#flavor "Root Beer", Wrapper#flavor "Root Beer"

Here's that same code instantiated in MacRuby, from candy_test.rb:

  rootBeerCandy = Candy.alloc.init
  rootBeerCandy.flavor = 'Root Beer'

  rootBeerWrapper = CandyWrapper.alloc.initWithCandy rootBeerCandy
  puts "Candy#flavor #{rootBeerCandy.flavor}, Wrapper#flavor
#{rootBeerWrapper.flavor}"

You can run this with "macrake test" in the project directory, and it will give (among other things):

  candy_test.rb:7:in `<main>': undefined method `flavor' for
#<CandyWrapper:0x8000aa2a0> (NoMethodError)
  rake aborted!

Attachments

reduction_app.zip Download (23.5 KB) - added by mattaimonetti@… 14 months ago.

Change History

Changed 20 months ago by martinlagardette@…

  • description modified (diff)
  • milestone MacRuby 0.4 deleted

Changed 14 months ago by mattaimonetti@…

  • keywords #reduction added
  • milestone set to MacRuby 1.0

I can confirmed that the - (id)forwardingTargetForSelector:(SEL)sel method doesn't get triggered when called from MacRuby.

I reduced the problem a bit further to show how MacRuby isn't allowing the forwarding of selectors.

Changed 14 months ago by mattaimonetti@…

Changed 14 months ago by mattaimonetti@…

Summary of the reduction code.

DummyClass.h

#import <Cocoa/Cocoa.h>

@interface DummyClass : NSObject {  }

@end

DummyClass.m

#import "DummyClass.h"

@implementation DummyClass

- (id)forwardingTargetForSelector:(SEL)sel {
    NSLog(@"The following method was caught by forwardingTargetForSelector: %@", NSStringFromSelector(sel));
		return @"foo";
}

@end

main.m

#import <MacRuby/MacRuby.h>
#import "DummyClass.h"

int main(int argc, char *argv[])
{
    DummyClass* objcObj = [[DummyClass alloc] init];    
    NSLog(@"Calling a string method on our objC object forwarding it to a NSString object.");
    [objcObj boolValue];
    return macruby_main("rb_main.rb", argc, argv);
}

rb_main.rb

framework 'Cocoa'
    
obj = DummyClass.alloc.init
puts "called from MacRuby: obj#foo #{obj.boolValue}"

# Starting the Cocoa main loop.
NSApplicationMain(0, nil)

Changed 14 months ago by mattaimonetti@…

Output:

2010-12-04 22:12:26.580 testApp[51067:a0f] Calling a string method on our objC object forwarding it to a NSString object.
2010-12-04 22:12:26.584 testApp[51067:a0f] The following method was caught by forwardingTargetForSelector: boolValue
/Users/mattetti/Code/builds/Debug/testApp.app/Contents/Resources/rb_main.rb:14:in `<main>': undefined method `boolValue' for #<DummyClass:0x200ba7fa0> (NoMethodError)
Note: See TracTickets for help on using tickets.