Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call can throw, but it is not marked with 'try' and the error is not handled: NSRegularExpression

Tags:

ios

swift

swift3

I have written this function in String Extension and can't figure out the error.

func isEmail() -> Bool {
    let regex = NSRegularExpression(pattern: "^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}$", options: [.CaseInsensitive])

    return regex.firstMatchInString(self, options: nil, range: NSMakeRange(0, characters.count)) != nil
}

The error is:

Call can throw, but it is not marked with 'try' and the error is not handled

like image 389
Sahil Kapoor Avatar asked Jun 15 '15 12:06

Sahil Kapoor


4 Answers

That's because that initializer can now throw an exception, so you need to try to call it and be prepared to catch the exception. You can do this by adding try before the initializer and annotating your method with throws.

extension String {
    func isEmail() throws -> Bool {
        let regex = try NSRegularExpression(pattern: "^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}$", options: [.CaseInsensitive])

        return regex.firstMatchInString(self, options: NSMatchingOptions(rawValue: 0), range: NSMakeRange(0, characters.count)) != nil
    }
}

Then when you want to call the method, do it from within a do block and catch the error that comes out.

do {
    try "[email protected]".isEmail()
} catch {
    print(error)
}

Note: I've also updated your regex.firstMatchInString call to reflect the fact that the options parameter can no longer take a nil value.

like image 43
Mick MacCallum Avatar answered Nov 19 '22 18:11

Mick MacCallum


NSRegularExpression(pattern:) throws an error if the pattern is invalid. In your case, the pattern is fixed, so an invalid pattern would be a programming error.

This is a use-case for the "forced-try" expression with try!:

extension String {
    func isEmail() -> Bool {
        let regex = try! NSRegularExpression(pattern: "^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}$",
            options: [.CaseInsensitive])

        return regex.firstMatchInString(self, options:[],
            range: NSMakeRange(0, utf16.count)) != nil
    }
}

try! disables the error propagation so that the method does not throw an error (which the caller has to catch). It will abort with a runtime exception if the pattern is invalid, which helps to find programming errors early.

Note also that NSRange() counts the length of NSString, i.e. the number of UTF-16 code points, so characters.count should be utf16.count, otherwise it might crash e.g. with Emoji characters.

like image 146
Martin R Avatar answered Nov 19 '22 20:11

Martin R


If you don't like try catch :

extension String {
    func matchPattern(patStr:String)->Bool {
            var isMatch:Bool = false
            do {
                let regex = try NSRegularExpression(pattern: patStr, options: [.CaseInsensitive])
                let result = regex.firstMatchInString(self, options: NSMatchingOptions(rawValue: 0), range: NSMakeRange(0, characters.count))

                if (result != nil)
                {
                    isMatch = true
                }
            }
            catch {
                isMatch = false
            }
            return isMatch
    }
}    

check string is correct email format :

let emailInput:String = "[email protected]"
if (emailInput.matchPattern("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}$"))
{
     print("this is e-mail!")
}
like image 3
Chris Ho Avatar answered Nov 19 '22 20:11

Chris Ho


You could use string.rangeOfString, and specify the option to .RegularExpressionSearch. It's simple.

func isEmail(email: String) -> Bool {
    return email.rangeOfString("^[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}$", options: .RegularExpressionSearch) != nil
}
like image 1
solos Avatar answered Nov 19 '22 18:11

solos