作為一門先進的程式設計語言,Swift 可以說吸收了眾多其他先進語言的優點,但是有一點卻是讓人略微失望的,就是 Swift 至今為止並沒有在語言層面上支援Regex。
Regex的用處:
判斷給定的字串是否符合某一種規則(專門用於操作字串)
- 電話號碼,電子郵箱,URL...
- 可以直接百度別人寫好的正則
- 別人真的寫好了,而且測試過了,我們可以直接用
- 要寫出沒有漏洞正則判斷,需要大量的測試,通常最終結果非常負責
過濾篩選字串,網路爬蟲
替換文字,QQ聊天,圖文混排
文法規則
使用過程
1、建立規則
2、建立Regex對象
3、開始匹配
程式碼範例
private func check(str: String) { // 使用Regex一定要加try語句 do { // - 1、建立規則 let pattern = "[1-9][0-9]{4,14}" // - 2、建立Regex對象 let regex = try NSRegularExpression(pattern: pattern, options: NSRegularExpressionOptions.CaseInsensitive) // - 3、開始匹配 let res = regex.matchesInString(str, options: NSMatchingOptions(rawValue: 0), range: NSMakeRange(0, str.characters.count)) // 輸出結果 for checkingRes in res { print((str as NSString).substringWithRange(checkingRes.range)) } } catch { print(error) }}
其他幾個常用方法
// 匹配字串中所有的符合規則的字串, 返回匹配到的NSTextCheckingResult數組 public func matchesInString(string: String, options: NSMatchingOptions, range: NSRange) -> [NSTextCheckingResult] // 按照規則匹配字串, 返回匹配到的個數 public func numberOfMatchesInString(string: String, options: NSMatchingOptions, range: NSRange) -> Int // 按照規則匹配字串, 返回第一個匹配到的字串的NSTextCheckingResult public func firstMatchInString(string: String, options: NSMatchingOptions, range: NSRange) -> NSTextCheckingResult? // 按照規則匹配字串, 返回第一個匹配到的字串的範圍 public func rangeOfFirstMatchInString(string: String, options: NSMatchingOptions, range: NSRange) -> NSRange
使用子類來匹配日期、地址、和URL
看官網文檔解釋,可以知道這個 NSDataDetector 主要用來匹配日期、地址、和URL。在使用時指定要匹配的類型
public class NSDataDetector : NSRegularExpression { // all instance variables are private /* NSDataDetector is a specialized subclass of NSRegularExpression. Instead of finding matches to regular expression patterns, it matches items identified by Data Detectors, such as dates, addresses, and URLs. The checkingTypes argument should contain one or more of the types NSTextCheckingTypeDate, NSTextCheckingTypeAddress, NSTextCheckingTypeLink, NSTextCheckingTypePhoneNumber, and NSTextCheckingTypeTransitInformation. The NSTextCheckingResult instances returned will be of the appropriate types from that list. */ public init(types checkingTypes: NSTextCheckingTypes) throws public var checkingTypes: NSTextCheckingTypes { get }}// 這個是類型選擇 public static var Date: NSTextCheckingType { get } // date/time detection public static var Address: NSTextCheckingType { get } // address detection public static var Link: NSTextCheckingType { get } // link detection
NSDataDetector 擷取URL樣本
/**匹配字串中的URLS- parameter str: 要匹配的字串*/private func getUrl(str:String) { // 建立一個Regex對象 do { let dataDetector = try NSDataDetector(types: NSTextCheckingTypes(NSTextCheckingType.Link.rawValue)) // 匹配字串,返回結果集 let res = dataDetector.matchesInString(str, options: NSMatchingOptions(rawValue: 0), range: NSMakeRange(0, str.characters.count)) // 取出結果 for checkingRes in res { print((str as NSString).substringWithRange(checkingRes.range)) } } catch { print(error) }}
".*?" 可以滿足一些基本的匹配要求
如果想同時匹配多個規則 ,可以通過 "|" 將多個規則串連起來
將字串中文字替換為表情
/**顯示字元中的表情- parameter str: 匹配字串*/private func getEmoji(str:String) { let strM = NSMutableAttributedString(string: str) do { let pattern = "\\[.*?\\]" let regex = try NSRegularExpression(pattern: pattern, options: NSRegularExpressionOptions.CaseInsensitive) let res = regex.matchesInString(str, options: NSMatchingOptions(rawValue: 0), range: NSMakeRange(0, str.characters.count)) var count = res.count // 反向取出文字表情 while count > 0 { let checkingRes = res[--count] let tempStr = (str as NSString).substringWithRange(checkingRes.range) // 轉換字串到表情 if let emoticon = EmoticonPackage.emoticonWithStr(tempStr) { print(emoticon.chs) let attrStr = EmoticonTextAttachment.imageText(emoticon, font: 18) strM.replaceCharactersInRange(checkingRes.range, withAttributedString: attrStr) } } print(strM) // 替換字串,顯示到label emoticonLabel.attributedText = strM } catch { print(error) }}
TextKit 給URL高亮顯示
主要用到三個類
NSTextStorage
NSLayoutManager
NSTextContainer
自訂UILabel來實現url高亮
1、定義要用到的屬性
/* 只要textStorage中的內容發生變化, 就可以通知layoutManager重新布局 layoutManager重新布局需要知道繪製到什麼地方, 所以layoutManager就會文textContainer繪製的地區 */ // 准們用於儲存內容的 // textStorage 中有 layoutManager private lazy var textStorage = NSTextStorage() // 專門用於管理布局 // layoutManager 中有 textContainer private lazy var layoutManager = NSLayoutManager() // 專門用於指定繪製的地區 private lazy var textContainer = NSTextContainer() override init(frame: CGRect) { super.init(frame: frame) setupSystem() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) setupSystem() } private func setupSystem() { // 1.將layoutManager添加到textStorage textStorage.addLayoutManager(layoutManager) // 2.將textContainer添加到layoutManager layoutManager.addTextContainer(textContainer) } override func layoutSubviews() { super.layoutSubviews() // 3.指定地區 textContainer.size = bounds.size }
2、重寫label的text屬性
override var text: String? { didSet{ // 1.修改textStorage儲存的內容 textStorage.setAttributedString(NSAttributedString(string: text!)) // 2.設定textStorage的屬性 textStorage.addAttribute(NSFontAttributeName, value: UIFont.systemFontOfSize(20), range: NSMakeRange(0, text!.characters.count)) // 3.處理URL self.URLRegex() // 2.通知layoutManager重新布局 setNeedsDisplay() }}
3、匹配字串
func URLRegex() { // 1.建立一個Regex對象 do{ let dataDetector = try NSDataDetector(types: NSTextCheckingTypes(NSTextCheckingType.Link.rawValue)) let res = dataDetector.matchesInString(textStorage.string, options: NSMatchingOptions(rawValue: 0), range: NSMakeRange(0, textStorage.string.characters.count)) // 4取出結果 for checkingRes in res { let str = (textStorage.string as NSString).substringWithRange(checkingRes.range) let tempStr = NSMutableAttributedString(string: str)// tempStr.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor(), range: NSMakeRange(0, str.characters.count)) tempStr.addAttributes([NSFontAttributeName: UIFont.systemFontOfSize(20), NSForegroundColorAttributeName: UIColor.redColor()], range: NSMakeRange(0, str.characters.count)) textStorage.replaceCharactersInRange(checkingRes.range, withAttributedString: tempStr) } }catch { print(error) } }
4、重繪文字
// 如果是UILabel調用setNeedsDisplay方法, 系統會促發drawTextInRectoverride func drawTextInRect(rect: CGRect) { // 重繪 // 字形 : 理解為一個小的UIView /* 第一個參數: 指定繪製的範圍 第二個參數: 指定從什麼位置開始繪製 */ layoutManager.drawGlyphsForGlyphRange(NSMakeRange(0, text!.characters.count), atPoint: CGPointZero)}
擷取label中URL的點擊
如果要擷取URL的點擊,那麼必須擷取點擊的範圍
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) { // 1、擷取手指點擊的位置 let touch = (touches as NSSet).anyObject()! let point = touch.locationInView(touch.view) print(point) // 2、擷取URL地區 // 注意: 沒有辦法直接設定UITextRange的範圍 let range = NSMakeRange(10, 20) // 只要設定selectedRange, 那麼就相當於設定了selectedTextRange selectedRange = range // 給定指定的range, 返回range對應的字串的rect // 返回數組的原因是因為文字可能換行 let array = selectionRectsForRange(selectedTextRange!) for selectionRect in array { if CGRectContainsPoint(selectionRect.rect, point) { print("點擊了URL") } }}
以上內容就是小編跟大家介紹的swift中的Regex小結,希望大家喜歡。