Sam Sam - 30 days ago 8
Swift Question

Value of type 'NSLinguisticTag' has no member 'range'

I have text direction code its working good with swift 3 but after migration to swift 4, I got error

let tagScheme = [NSLinguisticTagScheme.language]
let tagger = NSLinguisticTagger(tagSchemes: tagScheme, options: 0)
tagger.string = self.text
let lang = tagger.tag(at: 0, scheme: NSLinguisticTagScheme.language,
tokenRange: nil, sentenceRange: nil)

if lang?.range(of: "he") != nil || lang?.range(of: "ar") != nil { //Value of type 'NSLinguisticTag' has no member 'range'
self.textAlignment = NSTextAlignment.right
} else {
self.textAlignment = NSTextAlignment.left
}


Anyone know how to fix this? thanks

Answer Source

As of Swift 4, NSLinguisticTagger returns tags not as (optional) strings, but as (optional) values of NSLinguisticTag:

public struct NSLinguisticTag : RawRepresentable, Equatable, Hashable {
    public init(_ rawValue: String)
    public init(rawValue: String)
}

You get the underlying string with the rawValue property:

 if let lang = tagger.tag(at: 0, scheme: .language, tokenRange: nil, sentenceRange: nil) {
    print(lang.rawValue)
    if lang.rawValue.hasPrefix("he") { ... }
}

If you want to check for equality and not for containment then you can also define your own NSLinguisticTag constants:

extension NSLinguisticTag {
    static let hebrew = NSLinguisticTag("he")
}

and use them as

if let lang = tagger.tag(at: 0, scheme: .language, tokenRange: nil, sentenceRange: nil) {
    if lang == .hebrew { ... }
}

Another option would be to define a custom computed property

extension NSLinguisticTag {
    var isRightToLeft: Bool {
        return rawValue.hasPrefix("he") || rawValue.hasPrefix("ar")
    }
}

and use it as

if let lang = tagger.tag(at: 0, scheme: .language, tokenRange: nil, sentenceRange: nil) {
    if lang.isRightToLeft { ... }
}