RegexKitLite in IOS5 - objective-c

I need RegexKitlite in my App as a part of String validation.
Have also added libicucore.A.dylib .
Currently working with xcode 4.2,Base sdk iOS 5.0,Apple LLVM compiler 3.0,architechture armv7.
Adding the regexkit folder to my app, causes too many errors like
Automatic Reference Counting Errors ,
Cast of Objective-C pointer type 'NSString *' to C pointer type 'CFStringRef' etc
Please help;where have I gone wrong.

You can also disable the ARC for the RegexKitLite only by adding a flag:
select the project -> YOUR Target -> on the Tab the "Build Phases" and open the "Compile Sources" and add for "RegexKitLite.m" the flag "-fno-objc-arc".
Update:
If you get:
Undefined symbols:
"_uregex_reset", referenced from:
_rkl_splitArray in RegexKitLite.o
_rkl_replaceAll in RegexKitLite.o
"_uregex_appendTail", referenced from:.......
Then you need to add in the Tab "Build Settings" -> "Linking" -> "Other Linker Flags" the "-licucore"

You aren't doing anything wrong. Regexkit just hasn't been updated to iOS 5 yet. The big change in iOS 5 is there are no longer retains, releases, or autoreleases. Every memory thing is automatic like Java. (Except that it happens at compile time instead of run time. So it's conceptually like Java. Mostly.)
Anyway, instead of waiting for Regexkit to update you can use NSRegularExpression. Using Apple stuff is also future-proof since they keep their own stuff updated version to version.
Good luck!

CBGraham is right. Alternatively, you could disable automatic reference counting (Project > Build settings > search for 'automatic reference counting').
You will obviously have to do manual reference counting, but RegexKitLite should build now...

I replaced RegexKitLite with there two methods.
String Results:
+(NSString*) regExString: (NSString *) pattern withString: (NSString *) searchedString {
NSError *error = nil;
NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:&error];
NSTextCheckingResult *match = [regex firstMatchInString:searchedString options:0 range: NSMakeRange(0, [searchedString length])];
if ([searchedString substringWithRange:[match rangeAtIndex:1]]) {
return [searchedString substringWithRange:[match rangeAtIndex:1]];
} else {
return #"";
}
}
Array of Results:
+(NSArray *) regExArray:(NSString *) pattern withString: (NSString *) searchedString {
NSMutableArray *results = [[NSMutableArray alloc] init];
NSError *error;
NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:&error];
NSArray* matches = [regex matchesInString:searchedString options:0 range: NSMakeRange(0, searchedString.length)];
for (NSTextCheckingResult* match in matches) {
NSMutableArray *result = [NSMutableArray array];
NSRange matchRange = [match range];
NSString *numString = [searchedString substringWithRange:matchRange];
[result addObject:numString];
for (int i=1;i < (int)match.numberOfRanges;i++) {
NSRange range = [match rangeAtIndex:i];
#try {
NSString *numString = [searchedString substringWithRange:range];
[result addObject:numString];
}
#catch (NSException *exception) {
[result addObject:[NSNull null]];
}
}
[results addObject:result];
}
return results;
}

Related

Checking if UITextView has url (boolean value) or extract Url

I am aware I can do textView.dataDetectorTypes = UIDataDetectorTypeLink; to auto detect links.
Now this seems straightforward but I can't find a way to check if the UITextView's dataDetector actually found a match.
I'm looking for something like BOOL hasLink = textView.hasLink; or BOOL hasLink = textView.text.hasLink; or maybe even a way to pull a reference to the NSDataDetector(I could probably use NSDataDetector methods to check but I'd have to confirm, just throwing out ideas)
Is there no built in way to check this or do I have to confirm it independently?
Edit:
So I just used my own NSDataDetector to do this, (code below) but the question remains as to whether there really is no way of extracting a detected data type or confirming the existence of a detected data type in a UITextView?
This is what I used to check myself:
-(BOOL) doesTextHaveLink:(NSString *)text {
NSDataDetector *linkDetector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeLink error:nil];
NSArray *matches = [linkDetector matchesInString:text options:0 range:NSMakeRange(0, [text length])];
for (NSTextCheckingResult *match in matches) {
if ([match resultType] == NSTextCheckingTypeLink) {
return YES;
}
}
return NO;
}
plz use this code this return yes if textview has url
-(BOOL)checkUrl:(NSString *)strText{
NSString *urlRegEx =
#"(http|https)://((\\w)*|([0-9]*)|([-|_])*)+([\\.|/]((\\w)*|([0-9]*)|([-|_])*))+";
NSPredicate *urlTest = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", urlRegEx];
return [urlTest evaluateWithObject:strText];
}

NSString find the symbol got crashed

Everytime I will get a string from my server as:
"&abc;123:342:431:234& &xyz;232:2344:433:434& &pqr;234:453:534:3445&"
but sometimes I'll get
"&pqr;234:453:534:3445& &abc;123:342:431 &xyz;232:2344:433:434&"
I want to discard those messages (without ends with "&") ex:&abc;123:342:431. I tried but I don't know where I am making mistakes.
Here is my code:
- (BOOL)ashCheckandsemiclonCheck:(NSString *)string {
if([string rangeOfString:#"&abc"].location != NSNotFound) {
NSLog(#"is here");
NSString *pattern = #"&abc[^&]+&";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern
options:0 error:NULL];
[regex enumerateMatchesInString:string options:0 range:NSMakeRange(0, [string length])
usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
NSRange range = [result range];
matched = [string substringWithRange:range];
NSLog(#"%#", matched);
}];
NSLog(#"filtered Message :%#", matched);
int times = [[matched componentsSeparatedByString:#"&"] count] - 1;
NSLog(#"counted times :%i", times);
if (times == 2) {
return TRUE;
} else {
return FALSE;
}
} else {
return FALSE;
}
}
I want to call this argument if I have two & but in my code I get error NSLog(#"is here");. As I said sometimes I'll get half message. Can anyone tell me where I am going wrong?
If I'm reading your question correctly, it seems you just need to test whether a message string is valid by checking it begins and ends with '&'. The way I'd do that is to write something like this:
NSString* testMessage = #"&bfjhfbgfjhb&";
NSString* firstCharacter = [testMessage substringToIndex:1];
NSString* lastCharacter = [testMessage substringFromIndex:testMessage.length - 1];
if (([firstCharacter isEqualToString:#"&"]) &&
[lastCharacter isEqualToString:#"&"]){
//This is a valid message. Proceed.
}else{
//This is not a valid message. Discard.
}
Update
Okay, based on your question edit/update, I edited your code -- and in particular your regex pattern string -- to do what I think you want, which is to check that the '&abc...' subsection of your message begins and ends with the '&' character:
-(BOOL) ashCheckandsemiclonCheck :(NSString *)string;
{
if([string rangeOfString:#"&abc"].location !=NSNotFound)
{
NSLog(#"is here");
NSString *pattern = #"&abc[^&\\s]+[^\\s]";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern
options:0 error:NULL];
NSString* __block matched;
[regex enumerateMatchesInString:string options:0 range:NSMakeRange(0, [string length])
usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
NSRange range = [result range];
matched = [string substringWithRange:range];
NSLog(#"Matched: %#", matched);
}];
NSLog(#"filtered Message :%#", matched);
int times =[[matched componentsSeparatedByString:#"&"]count]-1;
NSLog(#"counted times :%i",times);
if(times ==2){
return YES;
}else
{
return NO;
}
}
else
{
return NO;
}
}
Also changed your BOOL returns to Objective-C standard YES and NO rather than TRUE and FALSE.
Hope that does what you need.

iOS app searching large amounts of text

I apologize if this is a repeat, but I honestly have done my best to research this and haven't come up with much.
I'm making an iPad reference app that will make several large textbooks searchable (maybe 3-4k pages in total). It's a fairly simple idea: the user can choose any combination of texts to search, put in his term, and the app will find those terms in all the texts and return them, indexed in a table view.
The view controller has a series of switches, the value of which get read by a method into an NSSet and passed to the search controller. That part works.
I have a SearchController class which the view controller instantiates and calls a method on:
-(void)performSearchWithString:(NSString *)searchString andTexts:(NSSet *)texts
{
for (id book in texts) {
if ([book isEqual:kBook1]){
NSError *error = nil;
NSURL *url = [[NSBundle mainBundle] URLForResource:#"neiJing" withExtension:#"txt"];
NSString *text = [NSString stringWithContentsOfURL:url encoding:NSStringEncodingConversionAllowLossy error:&error];
[text enumerateSubstringsInRange:NSMakeRange(0, [text length])
options:NSStringEnumerationByWords
usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
NSRange found = [substring rangeOfString:text];
if (found.location != NSNotFound) {
NSLog(#"%#", substring);
} else {
NSLog(#"Not found");
}
}];
}
I seem to have succeeded in enumerating through every word in all the texts, but no return values are found so I just get a never-ending stream of "Not found".
I inserted a test phrase into each text that I know for certain to be there, but it's not coming up.
I have a feeling I'm going about this all wrong. Even if I made this work, the performance hit might be too big for a useable app...I'm still trying to wrap my head around blocks, too. I just haven't found any ready-baked solutions out there for searching large volumes of text and picking out results. If anyone has any hints or references to an open-source library that I might adapt, I would be very grateful.
It looks like you're searching for the whole text inside of each substring passed to the block. This line is the problem (and causes a retain cycle):
NSRange found = [substring rangeOfString:text];
The code needs to look for something it can find:
NSString *findMe = #"A string we expect to find";
[text enumerateSubstringsInRange:NSMakeRange(0, [text length])
options:NSStringEnumerationByWords
usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
if ([findMe isEqualToString:substring] ) {
NSLog(#"Found %#", substring);
} else {
NSLog(#"Not found");
}
}];
I don't think the block of code is what you want. It loops through each word in the text and you want to find all the search strings. Here is a loop that sets a new search range based on the last successful match.
-(void)performSearchWithString:(NSString *)searchString andTexts:(NSSet *)texts
{
for (id book in texts) {
if ([book isEqual:kBook1]){
NSError *error = nil;
NSURL *url = [[NSBundle mainBundle] URLForResource:#"neiJing" withExtension:#"txt"];
NSString *text = [NSString stringWithContentsOfURL:url encoding:NSStringEncodingConversionAllowLossy error:&error];
NSRange searchRange = NSMakeRange(0, [text length]);
NSRange match = [text rangeOfString:searchString options:0 range:searchRange];
while (match.location != NSNotFound) {
// match is the range of the current successful match
NSLog(#"matching range -- %#", NSStringFromRange(match));
NSUInteger locationOfNextSearchRange = NSMaxRange(match);
searchRange = NSMakeRange(locationOfNextSearchRange, [text length] - locationOfNextSearchRange);
match = [text rangeOfString:searchString options:0 range:searchRange];
}
}
}

NSRegularExpression:enumerateMatchesInString hangs when called more than once

In the context of an iPhone app I am developing, I am parsing some html to extract data to map, using NSRegularExpression. This information is updated whenever the user "pans" the map to a new location.
This works fine the first time or two through, but on the second or third time the function is called, the application hangs. I have used XCode's profiler to confirm I am not leaking memory, and no error is generated (the application does not terminate, it just sits in execution at the point shown below).
When I examine the HTML being parsed, I do not see that it is incomplete or otherwise garbled when the application hangs.
Furthermore, if I replace the regex code with a collection of explicitly address strings, everything works as expected.
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
// receivedData contains the returned HTML
NSString *result = [[NSString alloc] initWithData:receivedData encoding:NSASCIIStringEncoding];
NSError *error = nil;
NSString *pattern = #"description.*?h4>(.*?)<\\/h4>.*?\"address>[ \\s]*(.*?)<.*?zip>.*?(\\d{5,5}), US<";
NSRegularExpression *regex = [NSRegularExpression
regularExpressionWithPattern:pattern
options:NSRegularExpressionDotMatchesLineSeparators
error:&error];
__block NSUInteger counter = 0;
// the application hangs on the next line after 1-2 times through
[regex enumerateMatchesInString:result options:0 range:NSMakeRange(0, [result length]) usingBlock:^(NSTextCheckingResult *match, NSMatchingFlags flags, BOOL *stop){
NSRange range = [match rangeAtIndex:2];
NSString *streetAddress =[result substringWithRange:range];
range = [match rangeAtIndex:3];
NSString *cityStateZip = [result substringWithRange:range];
NSString *address = [NSString stringWithFormat:#"%# %#", streetAddress, cityStateZip];
EKItemInfo *party = [self addItem:address]; // geocode address and then map it
if (++counter > 4) *stop = true;
}];
[receivedData release];
[result release];
[connection release]; //alloc'd previously, so release here.
}
I realize this is going to be difficult/impossible to duplicate, but I was wondering if anyone has run into a similar issue with NSRegularExpression or if there is something obviously wrong here.
I also have encountered the regular expression exception, too. In my case, the problem was Character Encoding. So that I wrote a code to go well with several character encoding. Maybe this code help you.
+ (NSString *)encodedStringWithContentsOfURL:(NSURL *)url
{
// Get the web page HTML
NSData *data = [NSData dataWithContentsOfURL:url];
// response
int enc_arr[] = {
NSUTF8StringEncoding, // UTF-8
NSShiftJISStringEncoding, // Shift_JIS
NSJapaneseEUCStringEncoding, // EUC-JP
NSISO2022JPStringEncoding, // JIS
NSUnicodeStringEncoding, // Unicode
NSASCIIStringEncoding // ASCII
};
NSString *data_str = nil;
int max = sizeof(enc_arr) / sizeof(enc_arr[0]);
for (int i=0; i<max; i++) {
data_str = [
[NSString alloc]
initWithData : data
encoding : enc_arr[i]
];
if (data_str!=nil) {
break;
}
}
return data_str;
}
You can download the whole category library from GitHub and just run it. I wish this helps you.
https://github.com/weed/p120801_CharacterEncodingLibrary
Maybe the answer to this question can be found at: NSRegularExpression enumerateMatchesInString: [...] usingBlock does never stop .
I had this issue solved by passing NSMatchingReportCompletion as option and by setting stop to YES when the match is nil.

NSNumberFormatter subclass working in 10.6 but failing in 10.5 with generic error

I'm subclassing NSNumberFormatter to allow the currency symbol to be optional. Here's my code:
- (BOOL)getObjectValue:(out id *)anObject forString:(NSString *)aString range:(inout NSRange *)rangep error:(out NSError **)error {
if (rangep == NULL){
NSRange newRange = NSMakeRange(0, [aString length]);
rangep = &newRange;
}
NSString *newStr = [aString stringByReplacingOccurrencesOfString:[self currencySymbol]
withString:#""
options:0
range:*rangep];
if (![newStr isEqualToString:aString]) {
NSRange newRange;
newRange.location = ((NSRange)*rangep).location;
newRange.length = ((NSRange)*rangep).length;
newRange.length -= ([aString length] - [newStr length]);
rangep = &newRange;
}
return [super getObjectValue:anObject
forString:newStr
range:rangep
error:error];
}
On Mac OS X 10.6 and higher, this code works absolutely fine. However, on 10.5.x, the code fails — the call to [super getObjectValue:...] fails, and the error returned is the rather generic "NSFormattingError" (code 2048).
Does anyone know what's going on?
The formatter is set to generate decimal numbers.