Menu

v0.3 unrecognized selector issue

mchartier
2007-10-31
2013-04-24
  • mchartier

    mchartier - 2007-10-31

    Trying to get the kit working in my project. I believe I followed all of the instructions. The project compiles and links fine, but when I run it, it says:

    *** -[NSCFString stringByMatching:replace:withReferenceString:]: unrecognized selector sent to instance 0xa08a5258'

    I made sure the RegexKit.framework was properly placed in my bundle. Its like the category for the NSString class isn't being added at runtime. Here is a snippet of my code:

        NSString* test            = @"<node1><node2 id=\"1\"><name>value</name></node2></node1>";
        NSString* elementMod    = @"<b>$1</b>";
        NSString* testXML        = [test stringByMatching:@"&lt;.*&gt;" replace:RKReplaceAll withReferenceString:elementMod];

    Don't know whether it would make a difference or not, but my bundle is a quick look plugin on Leopard.

     
    • mchartier

      mchartier - 2007-10-31

      Figured it out... Because I'm using the framework from a plugin bundle, I have to explicetly load the RegexKit when my plugin initializes. Did that and now all is well.

       
    • John Engelhart

      John Engelhart - 2007-10-31

      The quick look plugin might have something to do with it, but it depends on a lot of details.  I remember reading in some of the release notes that the linker is more restrictive about things in 10.5, and that "libraries at relative paths" (which regexkit would be, @executable_path/../Frameworks/RegexKit.framework/Versions/A/RegexKit) aren't loaded under some circumstances (ie, suid situations).  I don't know enough about quick look, but it's not a far stretch to see that maybe it applies in your case.

      I'd start off by double-checking that you are linked to the framework, the framework is in the right place, and then a run time test to see if it loaded.

      To check to see if you're executable is linked, use 'otool -L FILE'.  I'm going to guess at the file layout, but you should be able to fix up the examples to your specifics:

      shell% otool -L quick.plugin/Contents/MacOS/looker
      quick.plugin/Contents/MacOS/looker:
          /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 677.0.0)
          @executable_path/../Frameworks/RegexKit.framework/Versions/A/RegexKit (compatibility version 0.3.0, current version 0.3.1)
      [ snip ]

      RegexKit should obviously appear in the list.  Next, make sure that it's reachable at that path.

      shell% cd quick.plugin/Contents/MacOS/
      shell% ls -l ../Frameworks/RegexKit.framework/Versions/A/RegexKit
      -rwxr-xr-x  1 johne  wheel  1059144 Oct 31 15:24 ../Frameworks/RegexKit.framework/Versions/A/RegexKit

      Then, I'd add a runtime test that will tell you whether or not the framework loaded.  This snippet should do the trick:

        id rkClass = objc_getClass("RKRegex");
        NSString *statusString = [[rkClass regexCache] status];

        NSLog(@"rkClass: %p Status: %@", rkClass, statusString);

      This manually requests that the objc runtime system lookup and and return the class definition for "RKRegex".  If it's loaded, it'll return with a valid pointer.  If not, it'll return NULL. Then, it sends a regexCache message to whatever result it got (it's safe to message NULL/nil, the result is NULL).  And then a 'status' message to the regexCache.  Then print the results.

      If it isn't loaded, you'll get something like:

      2007-10-31 18:28:47.316 a.out[51069:807] rkClass: 0x0 Status: (null)

      If it is loaded, you'll get something like:

      2007-10-31 18:29:21.530 a.out[51077:807] rkClass: 0x6bce8 Status: Enabled = Yes (Add: Yes, Lookup: Yes), Cleared count = 0, Cache count = 0, Hit rate =   0.00%, Hits = 0, Misses = 0, Total = 0, GC Active = No

      If it is NOT loaded, you'll have to track down why.  Assuming paths and permissions are OK, my first hunch would be some kind of elevated privilege safety measure you're bumping in to.  You can try moving the framework to a non-relative, standard location.  Normally this requires recompiling the framework, re-linking your executable, etc etc.  Lucky for you that the default build of the framework adds 'headerpad_max_install_names' which adds extra space in the mach-o headers so you can overwrite some fields without having to worry about exceeding the fixed length space used to hold the old information.  You can follow these simple steps:

      shell% mkdir /Library/Frameworks/RegexKit.framework
      shell% rsync -PavE RegexKit.framework/ /Library/Frameworks/RegexKit.framework/
      shell% install_name_tool -id /Library/Frameworks/RegexKit.framework/Versions/A/RegexKit /Library/Frameworks/RegexKit.framework/Versions/A/RegexKit
      shell% install_name_tool -change '@executable_path/../Frameworks/RegexKit.framework/Versions/A/RegexKit' '/Library/Frameworks/RegexKit.framework/Versions/A/RegexKit' quick.plugin/Contents/MacOS/looker <-- Path to executable to update here

      That copies the framework to /Library/Frameworks, and updates the library and your executable to use the new path without having to recompile or relink anything.

      Oh, and it looks like the substituition part is wrong:

      [test stringByMatching:@"&lt;.*&gt;" replace:RKReplaceAll withReferenceString:@"<b>$1</b>"]

      The regex given doesn't specify any capture groups, but your replacement string references capture group 1. (capture group 0 is always valid, and it means 'the text of the entire match'). Here's two examples which should work, depending on what you're trying to accomplish.

      [test stringByMatching:@"&lt;.*&gt;" replace:RKReplaceAll withReferenceString:@"<b>$0</b>"]
      in: @"&lt;FOO&gt;"
      out: @"<b>&lt;FOO&gt;</b>"

      [test stringByMatching:@"&lt;(.*)&gt;" replace:RKReplaceAll withReferenceString:@"<b>$1</b>"]
      in: @"&lt;FOO&gt;"
      out: @"<b>FOO</b>"

       

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.