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:
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.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
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];
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.
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:
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.
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:@"<.*>" 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.
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.
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:@"<.*>" 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:@"<.*>" replace:RKReplaceAll withReferenceString:@"<b>$0</b>"]
in: @"<FOO>"
out: @"<b><FOO></b>"
[test stringByMatching:@"<(.*)>" replace:RKReplaceAll withReferenceString:@"<b>$1</b>"]
in: @"<FOO>"
out: @"<b>FOO</b>"