URL Validation function improving - objective-c

i use this function to check if an URL is valid or not. it works for most of the cases, but here the following URL it return that is not Valid!
http://www.iphonedevsdk.com/forum/iphone-sdk-development/11841-stringbytrimmingcharactersinset.html
what can i do to improve the regular expression of my function that it will cover all URL types?
- (BOOL) urlIsValiad: (NSString *) url
{
NSString *regex =
#"(http|https)://((\\w)*|([0-9]*)|([-|_])*)+([\\.|/]((\\w)*|([0-9]*)|([-|_])*))+";
NSPredicate *regextest = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", regex];
if ([regextest evaluateWithObject: url] == YES) {
NSLog(#"URL is valid!");
} else {
NSLog(#"URL is not valid!");
}
return [regextest evaluateWithObject:url];
}

This would be my attempt:
((?:http|https)://)?(?:www\\.)?[\\w\\d\\-_]+\\.\\w{2,3}(\\.\\w{2})?(/(?<=/)(?:[\\w\\d\\-./_]+)?)?
EDIT
Added in a back-reference (?<=/)for extra specificity
EDIT 2
Added optional search for country name in URL (eg www.google.com.in)

Try to change the *regex = line with following.
NSString *regex = "(http|ftp|https)://[\w-_]+(.[\w-_]+)+([\w-.,#?^=%&:/~+#]* [\w-\#?^=%&/~+#])?"

Well, I found something on Microsoft site and with slight changes it's the best expression so far:
#"(?:[A-Za-z0-9!#$%\\&'*+/=?\\^_`{|}~-]+(?:\\.[A-Za-z0-9!#$%\\&'*+/=?\\^_`{|}"
#"~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\"
#"x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")#(?:(?:[A-Za-z0-9](?:[A-Za-"
#"z0-9-]*[A-Za-z0-9])?\\.)+[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?|\\[(?:(?:25[0-5"
#"]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-"
#"9][0-9]?|[A-Za-z0-9-]*[A-Za-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21"
#"-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])";

Old thread but I think my amendments may be helpful to someone else landing here:
I didn't like to check only for a "www" as a hostname, nowadays we may encounter different hostnames... Thus I extended the Regex with:
"((?:http|https)://)?(?:[A-Za-z0-9]{1,25}\\.)?[\\w\\d\\-_]+\\.\\w{2,3}(\\.\\w{2})?(/(?<=/)(?:[\\w\\d\\-./_]+)?)?"

-(BOOL)validateUrl{
// NSString *urlRegEx = #"((?:http|https)://)?(www\\.)[\\w\\d\\-_]+\\.\\w{2,3}(\\.\\w{2})?(/(?<=/)(?:[\\w\\d\\-./_]+)?)?";
NSString *urlRegEx = #"((?:http|https)://)?(www\\.)[\\w\\d\\-_]+\\.\\w{2,3}(\\.\\w{2})?(/(?<=/)(?:[\\w\\d\\-./_]+)?)?";
NSPredicate *urlTest = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", urlRegEx];
if ([urlTest evaluateWithObject: self] == YES) {
NSLog(#"URL is valid!");
} else {
NSLog(#"URL is not valid!");
}
return [urlTest evaluateWithObject:self];
}

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];
}

How do I handle file names with spaces?

I am using this code below to copy a file selected in the file browser and copying it to the temp directory with a different name. But when I select a file with spaces in it, the program throws an error saying it cannot find the specified fine path. I have tried using escape methods but they do not work either. Are there any other ways to handle file names with spaces?
Code starts here:
[openPanel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) {
[openPanel close];
if (result == NSFileHandlingPanelOKButton) {
myString = [self randomStringWithLength:7];
NSString *filePath = [[[openPanel URLs] objectAtIndex:0] absoluteString];
NSLog(#"%#", filePath);
NSString *strTemp = [self extractString:filePath toLookFor:#"//" skipForwardX:2 toStopBefore:#".png"];
NSLog(#"%#",strTemp);
NSString *realThing = [strTemp stringByReplacingOccurrencesOfString:#"%20" withString:#"\\ "];
//strTemp = [strTemp stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog(#"%#", realThing);
NSString* fullPath = [NSString stringWithFormat:#"/tmp/%#.png", myString];
NSLog(fullPath);
NSError *error = nil;
[[NSFileManager defaultManager] copyItemAtPath:realThing toPath:fullPath error:&error];
if(error) {
NSLog(#"Error!!!");
NSLog(#" error => %# ",error);
}
else {
NSLog(#"Saved to temp directory");
}
Anyone have experience with this? Thanks
Your conversion of the URL to a path is much too complicated and error-prone.
Just use the path method:
NSString *filePath = [[[openPanel URLs] objectAtIndex:0] path];
Alternatively, use copyItemAtURL:... instead of copyItemAtPath:....
You also should check the return value of copyItemAtPath:... as the indicator
of a failure:
if (![[NSFileManager defaultManager] copyItemAtPath:filePath toPath:fullPath error:&error]) {
NSLog(#" error => %# ",error);
}
Compare Handling Error Objects Returned From Methods:
Important: Success or failure is indicated by the return value of the
method. Although Cocoa methods that indirectly return error objects in
the Cocoa error domain are guaranteed to return such objects if the
method indicates failure by directly returning nil or NO, you should
always check that the return value is nil or NO before attempting to
do anything with the NSError object.
You seem to be trying to convert URLs to file paths by hand. Use fileSystemRepresentation instead.

NSPredicate created with format and va_list/NSArray failed but string success

I created categories of NSManagedObject such as create, count and else. All of them works find except for following
#interface NSManagedObject(ManagedObjectExtension)
+ (id)findWithPredicate:(id)stringOrPredicate, ...;
#end
#implementation NSManagedObject(ManagedObjectUtilities)
+ (id)findWithPredicate:(id)stringOrPredicate, ... {
NSFetchRequest *fetchRequest = [self allFetchRequest];
if (stringOrPredicate) {
NSPredicate *predicate;
if ([stringOrPredicate isKindOfClass:[NSString class]]) {
va_list variadicArguments;
va_start(variadicArguments, stringOrPredicate);
predicate = [NSPredicate predicateWithFormat:stringOrPredicate arguments:variadicArguments];
va_end(variadicArguments);
} else {
predicate = (NSPredicate *)stringOrPredicate;
}
[fetchRequest setPredicate:predicate];
}
NSError *error;
NSArray *results = [[self managedObjectContext] executeFetchRequest:fetchRequest error:&error];
if (error) {
NSLog(#"%#", [error description]);
}
if ([results count] == 0) {
return nil;
} else if ([results count] == 1) {
return [results objectAtIndex:0];
} else {
return results;
}
}
#end
And these are results
NSString *email = [NSString stringWithString:someTextField.text];
NSLog(#"%#", [User findWithPredicate:#"email == "%#", email]);
==> (null)
NSLog(#"%#", [User findWithPredicate:[NSString stringWithFormat:#"email == "%#", email]]);
==> "<User: 0x1d827e10> ..."
Basically, this method works only when I send a string instead of formatted string and arguments. If I print the predicate created inside this method, these are results
[User findWithPredicate:#"email == "%#", email];
==> email == "%#"
[User findWithPredicate:[NSString stringWithFormat:#"email == "%#", email]];
==> email == "tar.tw45#gmail.com"
Do you have any idea what could cause this? Any comment or suggestion are welcome : )
I assume that you forgot the quotation marks in the code of your question (as #kitschmaster said in his comment) and that the code actually looks like this:
NSString *email = #"tar.tw45#gmail.com";
// Case 1:
NSLog(#"%#", [User findWithPredicate:#"email == '%#'", email]);
// Case 2:
NSLog(#"%#", [User findWithPredicate:[NSString stringWithFormat:#"email == '%#'", email]]);
In case (1), your utility method creates the following predicate
[NSPredicate predicateWithFormat:#"email == '%#'", email];
and this predicate searches for the verbatim string "%#" because of the quotation marks. If you remove the quotation marks:
NSLog(#"%#", [User findWithPredicate:#"email == %#", email]);
then it works correctly.
In case (2), your utility method creates the predicate
[NSPredicate predicateWithFormat:#"email == 'tar.tw45#gmail.com'"];
because it is called with an already formatted query string. This works in this particular case. But it will fail if the query itself contains any quotation marks. For example:
[User findWithPredicate:#"name == %#", #"a'b"]
works correctly, but
[User findWithPredicate:[NSString stringWithFormat:#"name == '%#'", #"a'b"]]
crashes. The usage of stringWithFormat should generally be avoided when creating predicates.
Summary: The first version works correctly if you omit the quotation marks in the format string. The second version should not be used.

iOS Core Data how to properly compare string text using predicates?

This is literally driving me nuts.
I have 2 entities that use NSStrings as unique attribute.
What is the correct way to create a predicate that compares NSStrings?
Currently I have:
[NSPredicate predicateWithFormat:#"unique= %#", uniqueValue];
I have a feeling that this compares the pointer addresses, not actual string values, but I cannot confirm that. I need to return yes for an exact string match.
-(BOOL)uniqueEntityExistsWithEnityName:(NSString*)entityName UniqueKey:(NSString*) uniqueKey UniqueValue:(NSString*)uniqueValue SortAttribute:(NSString*)sortDescriptorAttribute ManagedObjectContext:(NSManagedObjectContext*) context;
{
BOOL returnValue = NO;
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:entityName];
//what is the correct predates to compare the text an string core data property against a passed in string?
request.predicate = [NSPredicate predicateWithFormat:#"unique= %#", uniqueValue];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:sortDescriptorAttribute ascending:YES];
request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSError *error = nil;
NSArray *matches = [context executeFetchRequest:request error:&error];
if (!matches)
{
NSLog(#"Error: no object matches");
}
else if([matches count] > 1) {
NSLog(#"Error: More than one object for unique record");
returnValue = YES;
} else if ([matches count] == 0) {
returnValue = NO;
} else {
returnValue = YES;
}
return returnValue;
}
A single equal sign is not even a comparator in terms of coding.
I'm going to assume unique is an NSManagedObject attribute.
[NSPredicate predicateWithFormat:#"unique LIKE %#", uniqueValue];
Note that this is case-sensitive. If you want to make it insensitive, then you can put [c] after the LIKE.
I don't see a problem with your predicate. A single = is perfect if you want to match exact strings. If you don't need wildcard matching you don't need the slower LIKE. (Predicate Format String Syntax)
However, there is a problem in your code, and it might lead you to assumptions that are not correct. Your if/then/else, or at least the first message is kind of wrong. If you fetch does not return an array it means the fetch failed, it does not mean that the fetch didn't return objects.
It should be more like this:
if (!matches)
{
NSLog(#"Error: couldn't execute fetch request %#", error);
}
else if([matches count] > 1) {
NSLog(#"Error: More than one object for unique record");
returnValue = YES;
} else if ([matches count] == 0) {
NSLog(#"couldn't match objects");
returnValue = NO;
} else {
// [matches count] == 1
NSLog(#"matched one object");
returnValue = YES;
}
Oh, and I would change the order of the conditions. In my opinion a structure like (!matches), ([matches count] == 1), ([matches count] == 0), (else) makes more sense and it's easier too read. You put the most important (because it is what you actually want) condition in the last "anonymous" else.

NSPredicate - Unable to generate SQL for predicate, I wonder why?

I have already solved my problem [Blindly] without understanding root cause. But I would rather understand a concept from a professional. So could you please tell me why below identical code one works but another doesn't.
Code 1: Doesn't work
//Above code omitted...
NSPredicate * predicate = [NSPredicate predicateWithFormat:#"gender == m"]; //NOTICE HERE
[request setPredicate:predicate];
NSError *error = nil;
self.people = [self.managedObjectContext executeFetchRequest:request error:&error];
//Below code omitted...
Code 2: Does work
//Above code omitted...
NSString *type = #"m";
NSPredicate * predicate = [NSPredicate predicateWithFormat:#"gender == %#",type]; //NOTICE HERE
[request setPredicate:predicate];
NSError *error = nil;
self.people = [self.managedObjectContext executeFetchRequest:request error:&error];
//Below code omitted...
Forgot to tell about what error I got, I got SIGABRT on below line, When I executed Code 1.
self.people = [self.managedObjectContext executeFetchRequest:request error:&error];
And one more thing, in GCC error was it cannot format predicate because of "gender == m".
Enlighten me!!
Thanks
See the predicate programming guide (heading "Literals"). You can use literals in your string but you have to enclose them in quotes, so
NSPredicate * predicate = [NSPredicate predicateWithFormat:#"gender == 'm'"];
Would have worked. When predicateWithFormat adds in the argument, it knows it is a string. When you just have m in there, it doesn't know what to do with it, hence the error.
example with swift
let appDelegate =
UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext!
let fetchRequest = NSFetchRequest(entityName:"Words")
fetchRequest.predicate = NSPredicate(format: "letter == '\(letter)'")
var error: NSError?
let fetchedResults =
managedContext.executeFetchRequest(fetchRequest,
error: &error) as? [NSManagedObject]
if let results = fetchedResults {
println(results)
} else {
println("Could not fetch \(error), \(error!.userInfo)")
}