我正在使用新功能更新我的应用程序,并将Cocoapods中的CSVImporter添加到应用程序中。但是,关于"实例成员'结果'的代码存在一些问题。不能用于' Regex.Match'"。我想知道如何解决它!
import Foundation
/// `Regex` is a swifty regex engine built on top of the NSRegularExpression api.
public struct Regex {
// MARK: - Properties
let regularExpression: NSRegularExpression
// MARK: - Initializers
/// Create a `Regex` based on a pattern string.
///
/// If `pattern` is not a valid regular expression, an error is thrown
/// describing the failure.
///
/// - parameters:
/// - pattern: A pattern string describing the regex.
/// - options: Configure regular expression matching options.
/// For details, see `Regex.Options`.
///
/// - throws: A value of `ErrorType` describing the invalid regular expression.
public init(_ pattern: String, options: Options = []) throws {
regularExpression = try NSRegularExpression(
pattern: pattern,
options: options.toNSRegularExpressionOptions
)
}
// MARK: - Methods: Matching
/// Returns `true` if the regex matches `string`, otherwise returns `false`.
///
/// - parameter string: The string to test.
///
/// - returns: `true` if the regular expression matches, otherwise `false`.
public func matches(_ string: String) -> Bool {
return firstMatch(in: string) != nil
}
/// If the regex matches `string`, returns a `Match` describing the
/// first matched string and any captures. If there are no matches, returns
/// `nil`.
///
/// - parameter string: The string to match against.
///
/// - returns: An optional `Match` describing the first match, or `nil`.
public func firstMatch(in string: String) -> Match? {
let firstMatch = regularExpression
.firstMatch(in: string, options: [], range: NSRange(location: 0, length: string.utf16.count))
.map { Match(result: $0, in: string) }
return firstMatch
}
/// If the regex matches `string`, returns an array of `Match`, describing
/// every match inside `string`. If there are no matches, returns an empty
/// array.
///
/// - parameter string: The string to match against.
///
/// - returns: An array of `Match` describing every match in `string`.
public func matches(in string: String) -> [Match] {
let matches = regularExpression
.matches(in: string, options: [], range: NSRange(location: 0, length: string.utf16.count))
.map { Match(result: $0, in: string) }
return matches
}
// MARK: Replacing
/// Returns a new string where each substring matched by `regex` is replaced
/// with `template`.
///
/// The template string may be a literal string, or include template variables:
/// the variable `$0` will be replaced with the entire matched substring, `$1`
/// with the first capture group, etc.
///
/// For example, to include the literal string "$1" in the replacement string,
/// you must escape the "$": `\$1`.
///
/// - parameters:
/// - regex: A regular expression to match against `self`.
/// - template: A template string used to replace matches.
/// - count: The maximum count of matches to replace, beginning with the first match.
///
/// - returns: A string with all matches of `regex` replaced by `template`.
public func replacingMatches(in input: String, with template: String, count: Int? = nil) -> String {
var output = input
let matches = self.matches(in: input)
let rangedMatches = Array(matches[0..<min(matches.count, count ?? .max)])
for match in rangedMatches.reversed() {
let replacement = match.string(applyingTemplate: template)
output.replaceSubrange(match.range, with: replacement)
}
return output
}
}
// MARK: - ExpressibleByStringLiteral
extension Regex: ExpressibleByStringLiteral {
/// Creates a new `Regex` based on a string literal.
/// If the internal initialization fails, the code will crash without any option to handle the error.
/// For safe `Regex` initialization, use the `init(_: String, options: Options) throws` overload instead.
///
/// - parameter stringLiteral: The pattern string.
public init(stringLiteral value: String) {
do {
try self.init(value)
} catch {
preconditionFailure("Not a valid regex: \(value)")
}
}
}
// MARK: - CustomStringConvertible
extension Regex: CustomStringConvertible {
/// Returns a string describing the regex using its pattern string.
public var description: String {
return "Regex<\"\(regularExpression.pattern)\">"
}
}
// MARK: - Equatable
extension Regex: Equatable {
/// Determines the equality of to `Regex`` instances.
/// Two `Regex` are considered equal, if both the pattern string and the options
/// passed on initialization are equal.
public static func == (lhs: Regex, rhs: Regex) -> Bool {
return lhs.regularExpression.pattern == rhs.regularExpression.pattern &&
lhs.regularExpression.options == rhs.regularExpression.options
}
}
// MARK: - Hashable
extension Regex: Hashable {
/// Returns a unique hash value for the `Regex` instance.
public var hashValue: Int {
return regularExpression.hashValue
}
}
// MARK: - Options
extension Regex {
/// `Options` defines alternate behaviours of regular expressions when matching.
public struct Options: OptionSet {
// MARK: - Properties
/// Ignores the case of letters when matching.
public static let ignoreCase = Options(rawValue: 1)
/// Ignore any metacharacters in the pattern, treating every character as
/// a literal.
public static let ignoreMetacharacters = Options(rawValue: 1 << 1)
/// By default, "^" matches the beginning of the string and "$" matches the
/// end of the string, ignoring any newlines. With this option, "^" will
/// the beginning of each line, and "$" will match the end of each line.
public static let anchorsMatchLines = Options(rawValue: 1 << 2)
/// Usually, "." matches all characters except newlines (\n). Using this,
/// options will allow "." to match newLines
public static let dotMatchesLineSeparators = Options(rawValue: 1 << 3)
/// The raw value of the `OptionSet`
public let rawValue: Int
/// Transform an instance of `Regex.Options` into the equivalent `NSRegularExpression.Options`.
///
/// - returns: The equivalent `NSRegularExpression.Options`.
var toNSRegularExpressionOptions: NSRegularExpression.Options {
var options = NSRegularExpression.Options()
if contains(.ignoreCase) { options.insert(.caseInsensitive) }
if contains(.ignoreMetacharacters) { options.insert(.ignoreMetacharacters) }
if contains(.anchorsMatchLines) { options.insert(.anchorsMatchLines) }
if contains(.dotMatchesLineSeparators) { options.insert(.dotMatchesLineSeparators) }
return options
}
// MARK: - Initializers
/// The raw value init for the `OptionSet`
public init(rawValue: Int) {
self.rawValue = rawValue
}
}
}
// MARK: - Match
extension Regex {
/// A `Match` encapsulates the result of a single match in a string,
/// providing access to the matched string, as well as any capture groups within
/// that string.
public class Match: CustomStringConvertible {
// MARK: Properties
/// The entire matched string.
public lazy var string: String = {
return String(describing: self.baseString[self.range])
}()
/// The range of the matched string.
public lazy var range: Range<String.Index> = {
return Range(self.result.range, in: self.baseString)!
}()
/// The matching string for each capture group in the regular expression
/// (if any).
///
/// **Note:** Usually if the match was successful, the captures will by
/// definition be non-nil. However if a given capture group is optional, the
/// captured string may also be nil, depending on the particular string that
/// is being matched against.
///
/// Example:
///
/// let regex = Regex("(a)?(b)")
///
/// regex.matches(in: "ab")first?.captures // [Optional("a"), Optional("b")]
/// regex.matches(in: "b").first?.captures // [nil, Optional("b")]
public lazy var captures: [String?] = {
let captureRanges = stride(from: 0, to: result.numberOfRanges, by: 1)
.map(result.range)
.dropFirst()
.map { [unowned self] in
Range($0, in: self.baseString)
}
return captureRanges.map { [unowned self] captureRange in
if let captureRange = captureRange {
return String(describing: self.baseString[captureRange])
}
return nil
}
}()
private let result: NSTextCheckingResult
private let baseString: String
// MARK: - Initializers
internal init(result: NSTextCheckingResult, in string: String) {
precondition(
result.regularExpression != nil,
"NSTextCheckingResult must originate from regular expression parsing."
)
self.result = result
self.baseString = string
}
// MARK: - Methods
/// Returns a new string where the matched string is replaced according to the `template`.
///
/// The template string may be a literal string, or include template variables:
/// the variable `$0` will be replaced with the entire matched substring, `$1`
/// with the first capture group, etc.
///
/// For example, to include the literal string "$1" in the replacement string,
/// you must escape the "$": `\$1`.
///
/// - parameters:
/// - template: The template string used to replace matches.
///
/// - returns: A string with `template` applied to the matched string.
public func string(applyingTemplate template: String) -> String {
let replacement = result.regularExpression!.replacementString(
for: result,
in: baseString,
offset: 0,
template: template
)
return replacement
}
// MARK: - CustomStringConvertible
/// Returns a string describing the match.
public var description: String {
return "Match<\"\(string)\">"
}
}
}
这是代码,我有截图了解更多细节。 Link of the screenshot of the error.
答案 0 :(得分:1)
潜在的问题是从惰性var。
调用实例成员result
这是一个古老的错误,所以不是现代的Swift / Xcode。
我猜这需要self.result
才能消失。
使用lazy vars,你需要为实例成员和类型指定self,因为它无法推断(至少曾经是这种情况)。