美文网首页
从 FengNiao 中学习 Swift (三)

从 FengNiao 中学习 Swift (三)

作者: 要上班的斌哥 | 来源:发表于2017-12-11 22:38 被阅读88次

    从 FengNiao 中学习 Swift (一) 中介绍了 Swift Package Manager 的基本用法,然后创建了FengNiaoCopy 项目。
    从 FengNiao 中学习 Swift (二) 中主要介绍如何处理命令行的输入参数。
    接下来的这个文章主要介绍 FengNiao 的字符串搜索规则,通过这个规则来介绍 Swift 的 protocol 和 extension。

    搜索

    FengNiao 的搜索功能是在所有的搜索文件中寻找字符串,这些文件后缀可能是 swift,m,mm,xib,storyboard 等,若是字符串存在图片后缀名,那么将这个图片后缀名去除。

    protocol

    在 swift 中定义协议使用关键字 protocol,可以在 protocol 里面声明方法, 这点和 Objective-C 一样。

    // 定义协议
    protocol FileSearchRule {
        func search(in content : String) -> Set<String>
    }
    

    RegPatternSearchRule 协议继承了 FileSearchRule 协议,并添加了 2 个 属性声明

    // 协议继承
    protocol RegPatternSearchRule : FileSearchRule {
        var extensions:[String] { get }
        var patterns:[String] { get }
    }
    

    在 FengNiao 中,我们需要从 swift,m,mm,xib,storyboard等文件类型中来进行搜索,从功能设计的角度来说,我们只是要进行 “字符串搜索”,但是需要搜索不同类型的文件,所以我们定义了一个具备基本搜索功能的协议 RegPatternSearchRule,不同类型文件的搜索规则只要继承 RegPatternSearchRule 协议,并提供该类型文件的搜索正则表达式即可。

    // 用于 ObjC 类型文件的字符串搜索
    struct ObjCImageSearchRule : RegPatternSearchRule {
        let extensions: [String]
        // 匹配任意字符串 @""  ""
        let patterns = ["@\"(.*?)\"", "\"(.*?)\""]
    }
    
    // 用于 Swift 类型文件的字符串搜索
    struct SwiftImageSearchRule : RegPatternSearchRule {
        let  extensions: [String]
        // 匹配任意字符串 ""
        let patterns = ["\"(.*?)\""]
    }
    
    // 用于 xib storyboard 的字符串搜索
    struct XibImageSearchRule : RegPatternSearchRule {
        let extensions =  [String]()
        // .xib 字符串 image=""
        let patterns = ["image name=\"(.*?)\"", "image=\"(.*?)\"", "value=\"(.*?)\""]
    }
    
    // 用于 plist 的字符串搜索
    struct PlistImageSearchRule :RegPatternSearchRule {
        let extensions =  [String]()
        let patterns = ["<key>UIApplicationShortcutItemIconFile</key>[^<]*<string>(.*?)</string>"]
    }
    
    // 用于普通文件的字符串搜索
    struct PlainImageSearchRule : RegPatternSearchRule {
        let extensions: [String]
        var patterns: [String] {
            if extensions.isEmpty {
                return []
            }
            
            let joinedExt = extensions.joined(separator: "|")
            return ["\"(.+?)\\.(\(joinedExt))\""]
        }
    }
    

    extension

    在 swift 中 protocol 也是可以 extension 的,这个 extension 类似 Objective-C 的 category 功能。
    前面提到的 FileSearchRule 协议定义搜索方法,RegPatternSearchRule 继承 FileSearchRule 并添加 extensions 和 patterns 属性,patterns 属性用来保存搜索的正则表达式。FileSearchRule 协议中定义的方法要在什么地方来实现呢?在这里我们选择在 RegPatternSearchRule 的 extension 里面实现。

    // 拓展协议
    extension RegPatternSearchRule{
        // 查找文件名
        func search(in content :String) -> Set<String>{
            let nsstring = NSString(string:content)
            var result = Set<String>()
            for pattern in patterns {
                // 正则匹配
                let reg = try! NSRegularExpression(pattern: pattern, options: .caseInsensitive)
                let matches = reg.matches(in: content, options: [], range: content.fullRange)
                for checkingResult in matches {
                    let extracted = nsstring.substring(with: checkingResult.rangeAt(1))
                    result.insert(extracted.plainFileName(extensions: extensions))
                }
            }
            return result;
        }
    }
    

    除了给 protocol 添加 extension,我们也可以给系统的类添加 extension,这一点和 Objective-C 是一致的。比如我们给 String 类型添加一个 fullRange 属性和 plainFileName 方法。

    import Foundation
    import PathKit
    
    extension String{
        var fullRange:NSRange{
            let nsstring = NSString(string: self)
            return NSMakeRange(0, nsstring.length)
        }
        
        func plainFileName(extensions:[String]) -> String{
            let p = Path(self)
            var result : String!
            for ext in extensions {
                if hasSuffix(".\(ext)"){
                    result = p.lastComponentWithoutExtension
                    break
                }
            }
            
            if result == nil {
                result = p.lastComponent
            }
            
            if result.hasSuffix("@2x") || result.hasSuffix("@3x") {
                let endIndex = result.index(result.endIndex, offsetBy: -3)
                result = result.substring(to: endIndex);
            }
            return result
        }
    
    }
    

    相关文章

      网友评论

          本文标题:从 FengNiao 中学习 Swift (三)

          本文链接:https://www.haomeiwen.com/subject/mcpvixtx.html