Closed haashem closed 11 years ago
You won't use OHASBasicMarkupParser
directly for that, as it is designed to support the basic markup as seen in GitHub, but you can easily create your own parser by simply subclassing OHASMarkupParserBase
. I especially designed it so it would be as simple as possible for anyone to add their own custom markup parsers so that's exactly what you should do!
To do this, simply create a subclass of OHASMarkupParserBase
and override the +tagMappings
class method. In this method, return an NSDictionary
whose keys are a regular expression to match, and the associated values are a block that will take as parameters the matched string portion (as an NSAttributedString
) and the regex match (as an NSTextCheckingResult) and that will return the transformed
NSAttributedString`
You can use the OHASBasicMarkupParser
as an example, especially the last key/Value pair of the build NSDictionary
that add links when it finds text matching [text](link)
, as the principle will be quite the same for you. Simply adjust the regex to match \$(.*)\$
instead (*), and use the corresponding block to add a link to your NSAttributedString
with the setLink:range:
method
You can add any URL you want, so in your case you will probably add some custom URL scheme (say add the url "special:yourword"
on the word yourword
) and use the delegate method to catch taps on those words. You can use inspiration in my Demo project where I demonstrate this possibility in the "Custom Link" tab to show how to catch taps on custom links (in my example it is on words preceded by @
that I use as "mentions", but the principle remains the same in your case)
() be careful when building your RegEx, $
is a special character in regex, that's why I escape it with a backslash here, and don't forget to double your backslashes when putting it in your code, as I did in OHASBasicMarkupParser
too… so you will probably end up with @"\$(._)\$
" in your code._
This would give you something like this, that I just typed here. (Disclaimer: I didn't check this code at all, just took the code in OHASBasicMarkupParser
and adapted it right here from GitHub the returned dictionary of regular expressions to match your issue, I didn't test it is Xcode at all)
@implementation YourSpecialWordsMarkupParser
+(NSDictionary*)tagMappings
{
return [NSDictionary dictionaryWithObjectsAndKeys:
^NSAttributedString*(NSAttributedString* str, NSTextCheckingResult* match)
{
NSRange wordRange = [match rangeAtIndex:1]; // extract the range of the word (index 1 because we want the text captured by the first set of parenthesis in the regex)
if (wordRange.length>0)
{
// Extract just the word (without the dollar signs) and make it mutable so we can add a link to it
NSMutableAttributedString* foundWord = [[str attributedSubstringFromRange:wordRange] mutableCopy];
NSURL* specialLink = [NSURL URLWithString:[NSString stringWithFormat:@"special:%@",word]]; // create a link like "special:yourword"
[foundString setLink:specialLink range:NSMakeRange(0, foundWord.length)]; // add the link
return MRC_AUTORELEASE(foundWord);
} else {
return nil;
}
}, @"\\$(.+?)\\$", /* "$word$"
}
@end
Then add a delegate to your OHAttributedLabel
and use the methods of OHAttributedLabelDelegate
to catch when the links are tapped like I do in the CustomLinksViewController.m
file of my Demo project.
thanks for your cooperation. still not reached any milestone! I have some problems:
I tried to use your example so I add your key, value with some rehearsal:
^NSAttributedString*(NSAttributedString* str, NSTextCheckingResult* match)
{
NSRange wordRange = [match rangeAtIndex:1]; // extract the range of the word (index 1 because we want the text captured by the first set of parenthesis in the regex)
if (wordRange.length>0)
{
// Extract just the word (without the dollar signs) and make it mutable so we can add a link to it
NSMutableAttributedString* foundWord = [[str attributedSubstringFromRange:wordRange] mutableCopy];
NSURL* specialLink = [NSURL URLWithString:[NSString stringWithFormat:@"special:%@",foundWord]]; // create a link like "special:yourword"
[foundWord setLink:specialLink range:NSMakeRange(0, foundWord.length)]; // add the link
return MRC_AUTORELEASE(foundWord);
} else {
return nil;
}
}, @"\\$(.+?)\\$",
if I add this special link to the foundWord, the word wont be highlighted! but if I add a fancy or real link, the word would be highlighted but after touching it, nothing happens. (the delegate method wont be called!! how can i fix this issue? )
"special://%@"
instead of "special:%@"
maybe to add the linkfoundWord
, don't forget to add percent escapes to your foundWord to be sure the generated URL is correct, even if the foundWord
contain spaces, or special characters, etc.All that about creating a valid NSURL
is not related to OHAttributedLabel
directly and it is up to you to choose the custom URL you want. Did you look at my example I use in my demo project?
About the delegate method not being called:
userInteractionEnabled
set to YES
on your OHAttributedLabel
instance so it catch taps and user interaction (if the link becomes highlighted when you tap on it you're OK)OHAttributedLabelDelegate
protocol, of course) to the delegate
property of your OHAttributedLabel
, of course it must not be nil
if you want the delegate
's method to be calledI've uploaded my test with your API here: http://upload.ugm.ac.id/133OHAttributedLabel-master%202.zip all your recommendations I have conformed. I checked every thing but couldn't reach any results! I appreciate if you could check it.
OHAttributedLabel
and OHASBasicMarker
(instead of creating a subclass in your own project) — you are not supposed to modify my sources to do what you want to do, as I explained above alreadySMCalloutView* calloutView
… what the hell? You do know that global variables are evil and will likely to cause you problems (like multithreading issues and crashes) right?"$Some$"
word on one OHAttributedLabel
of my example project which does not have a delegate (contrary to the one on top for which I demonstrate its use). But I already explained exactly that to you in my comment above (point 2), so it seems you didn't even check that point…$xxx$
words:I tried the code I gave you above in my project and with a simple breakpoint I realized that I created the link with [NSString stringWithFormat:"special:%@",foundWord]
where foundWord
is an NSAttributedString
. So of course the link is invalid and specialLink
is nil
, and replacing with the NSString
corresponding to this attributed string solves the problem in 2 seconds. Frankly you could have found that yourself using a simple breakpoint or some NSLog
or whatever; I told you I didn't test my code and wrote it directly on GitHub without testing it on Xcode, so I expected you at least tried some easy debugging by yourself…
OHAttributedLabel
does not provide the possibility to find coordinates of a substring when it has been laid out. OHAttributedLabel
uses the CoreText framework to layout NSAttributedStrings
, using a CTFrameSetter
that lays out words for us. Layout out words of an NSAttributedString
and knowing at which position to draw them is very complex, because you have to take multiple font sizes and styles into account, in addition to the text alignment and paragraph properties chosen. So there is no easy way to compute that rect, and I won't have time to add this soon, but feel free to search and find a solution yourself, probably using the functions provided by the CoreText framework, and suggest a Pull Request if you find a wayNSAttributedText
editable, managing the caret / insertion point, the selection of words, and much more (but once again, you're welcome to propose some solution for that)wow thanks a lot for your help. I made a property for callOutView and synthesized it. I set a delegate for basicMarkupLabel: self.basicMarkupLabel.delegate = self; I corrected the special link: NSURL* specialLink = [NSURL URLWithString:[NSString stringWithFormat:@"%@",[foundWord string]]];
now everything works fine!
question: in basicDemoViewController even CustomViewController you haven't explicitly assigned objects to the OHAttributedLabelDelegate (if so I can't see clearly). but I see delegates are being called. how it happens?
You mean you didn't even look in the XIB file?
Note: I'm closing this issue now that the original problem of detecting $xxx$
markup is solved.
-(void)drawActiveLinkHighlightForRect:(CGRect)rect
won't call and I have to touch the link for more until the event fires! (before adding the label to the UIScrollView, only with a tap the event fires.) why this happens?
OHAttributedLabel
itself), look in the Events Programming Guide and allOHAttributedLabel
really)thanks for your sparks. touching delay solved! the solution is here: http://stackoverflow.com/questions/3642547/uibutton-touch-is-delayed-when-in-uiscrollview
another problem: OHAttributedLabel can't detect links for persian or arabic characters. for instance if we have: $الله$ this word wont show as a link:
even though your custom link markups if they persian or arabic characters:
The automatic links detection and persian characters is not an issue with OHAttributedLabel
but an issue with Apple's NSDataDetector
class itself (OHAttributedLabel
uses an instance of NSDataDetector
and ask it to detect links) and Apple's RegEx engine. I have no control on this one.
The only hope is in the custom links creation, where I use an NSRegularExpression
instance for which you can indicate the options
parameter, maybe you can try adding the NSRegularExpressionUseUnicodeWordBoundaries
option to the ones already listed in my code and check if it works better.
but NSData detector can detect this fancy link:
I want to add special links to my persian words (word: foundWord _ this kind of special links). so when foundWord is persian, the word wont be shown as a link! I used NSRegularExpressionUseUnicodeWordBoundaries but nothing happened. I need your help to fix this issue. maybe something is missed.
I checked and searched I guess thats not because of NSRegularExpression or NSDataDetector. I did something: [foundString setLink:[NSURL URLWithString:[linkString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]] range:NSMakeRange(0, foundString.length)];
it should solve the issue of unicode characters of in URL and always return a valid url. but the strange problem is when I debug the code in OHASBasciMarkupParser, debugger always jump over this line of this code and eve other code I write. would you check this:
if (wordRange.length>0)
{
// Extract just the word (without the dollar signs) and make it mutable so we can add a link to it
NSMutableAttributedString* foundWord = [[str attributedSubstringFromRange:wordRange] mutableCopy];
NSURL* specialLink = [NSURL URLWithString:[NSString stringWithFormat:@"word:%@",[[foundWord string] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]]; // create a link like "special:yourword"
NSLog(@"%@", specialLink.description);
[foundWord setLink:specialLink range:NSMakeRange(0, foundWord.length)]; // add the link
return MRC_AUTORELEASE(foundWord);
} else {
return nil;
}
}, @"\\$(.+?)\\$",
You mean you didn't add your percent escapes already ?
I though you had, because I told you in my previous comments above already, so of course if you didn't follow my advice yet and add these escapes before that's totally normal, as I explained already above 8 days ago…
I think that was a bug of x-code because it always jumping from my code and didn't debug some of them. so I extracted another copy of OHAttributedLabel and used above code, and works well.
another problem: but when I click on the link, the highlighted link bound won't sit in its original position for persian word (for english characters it sits in the right position).
performance problem:
I created a subclassed label of OHAttributedLabel and populated its text property with a very very long text (think a bout a chapter of book). then added this label to a scrollview. so when I click on a link it takes almost 5 second to highlight link background color and fire its delegate.
why this happens? does it needs multithreading? how should I fix this?
1) I can't understand how you can continue using the same issue to report what is so far no less than 4 different problems since the beginning, the last question isn't even closely related to the issue we are in right now… you're creating a mess in my issue tracker tool there. What about other people that could have answered you or that could have found your question/issue/solutions if you had open a dedicated issue? Please use the issue tracker tool correctly.
2) No direct solution, any performance improvement is welcome. Feel free to improve my code (that's why it's open-source) and suggest a pull request when you have a solution to improve that.
Hi thanks for developing this amazing API. Im interested in basicMarkupParser. so here is my scenario: Im developing a prose book and it has a lot of difficult word which the user needs to know its meaning. I need to parse these words with special tag like $word$ (for example this tag highlight the word).
so when the user touch it, an event raises and show its meaning in an alert view.
how can I make these words touchable using OHASBasicMarkupParser?