1

I'm using Regex to search in a textView. All works fine with simple strings but when I try to enter only a part of a regular expression operator I get a cash with the error:

Error Domain=NSCocoaErrorDomain Code=2048 "The value “\” is invalid." UserInfo={NSInvalidValue=\}

For example if I enter "\n" it works, but if I enter only "\" (without quotes), I get the crash. What I can't get to do is to find a way to check the expression before to use it.

I'm using this code partially based on this tutorial and this answer by Wiktor Stribiżew:

extension NSRegularExpression {
    convenience init?(options: SearchOptions) {
        let searchString = options.searchString
        let isCaseSensitive = options.matchCase // set to true
        let isWholeWords = options.wholeWords // set to false
        let escapeMetacharacters = options.escapeMetacharacters // set to false

        // handle case sensitive option
        var regexOption: NSRegularExpressionOptions = .CaseInsensitive
        if isCaseSensitive { // if it is match case remove case sensitive option
            regexOption = []
        }

        // put the search string in the pattern
        var pattern = searchString

        if isWholeWords {
            pattern = "(?<!\\w)" + NSRegularExpression.escapedPatternForString(searchString) + "(?!\\w)"
        }

        do {
            try self.init(pattern: pattern, options: regexOption)
        } catch {
            print(error)
        }
    }
}

1 Answer 1

1

The first code below have shown unstable behaviour and you should not use it. (Please see the latter part of this answer.)

Add one line to your failable initializer:

        do {
            try self.init(pattern: pattern, options: regexOption)
        } catch {
            print(error)
            return nil //->you need to return nil to tell initialization failed
        }

(I think Swift compiler should warn about this missing return nil. May be a bug of Swift?)

After that you can safely check the result if it's nil or not:

let sOpts = SearchOptions(searchString: "\\", replacementString: "", matchCase: false, wholeWords: false)
if let regex = NSRegularExpression(options: sOpts) {
    //Use regex
    print(regex)
} else {
    //Process errors
    print("Something bad in SearchOptions")
}

(I omitted escapeMetacharacters, as it's not used yet.)


As far as I tested, using static method has never crashed.

extension NSRegularExpression {
    static func expresssionWith(options: SearchOptions) -> NSRegularExpression? {
        let searchString = options.searchString
        let isCaseSensitive = options.matchCase // set to true
        let isWholeWords = options.wholeWords // set to false

        // handle case sensitive option
        var regexOption: NSRegularExpressionOptions = .CaseInsensitive
        if isCaseSensitive { // if it is match case remove case sensitive option
            regexOption = []
        }

        // put the search string in the pattern
        var pattern = searchString

        if isWholeWords {
            pattern = "(?<!\\w)" + NSRegularExpression.escapedPatternForString(searchString) + "(?!\\w)"
        }

        do {
            return try NSRegularExpression(pattern: pattern, options: regexOption)
        } catch  {
            print(error)
            return nil
        }
    }
}

let sOpts = SearchOptions(searchString: "\\", replacementString: "", matchCase: false, wholeWords: false)

if let regex = NSRegularExpression.expresssionWith(sOpts) {
    //Use regex
    print(regex)
} else {
    //Process errors
    print("Something bad in SearchOptions")
}
Sign up to request clarification or add additional context in comments.

7 Comments

Hi OOPer, thank you for the answer. I'm sure it works for the majority of the implementations, unfortunately in my case it fails to work, maybe I'm doing something wrong. Also with returning nile and the safely check implemented I get anyway a crash with this error 'Error Domain=NSCocoaErrorDomain Code=2048 "The value “\” is invalid." UserInfo={NSInvalidValue=\}'. I'm trying different implementations, but due my few experience I think will be very a long journey...
Sorry for the bad result. When you find additional information to tell us, please edit your question and add it. I or many other readers will help you.
Thank you so much. I noticed that if I remove the "print(error)" line, I get a different error: 'malloc: *** error for object 0x7c874b80: pointer being freed was not allocated *** set a breakpoint in malloc_error_break to debug'. I will try to debug step by step.
I have found the same error "malloc: **", while trying some modification to my code, which seems to be more unstable than I expected. I'll try to find some ways stable enough to use practically.
I got another message NSRegularExpression object 0x100602650 overreleased while already deallocating; break on objc_overrelease_during_dealloc_error to debug. I'm afraid this would be a Swift bug, such as using throws initializer in convenience initializer. As far as I tested, I couldn't have succeeded to define a convenience initializer (eventually all attempts has failed), but factory methods work as expected till now. I'll edit my answer and show my code.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.