Swift 3:设置Finder标签颜色

前端之家收集整理的这篇文章主要介绍了Swift 3:设置Finder标签颜色前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在尝试设置取景器显示彩色标签.我所知道的唯一功能是setResourceValue.但这需要本地化的名称

我可以想象我的母语和英语,但我不知道所有其他人.我不敢相信,这应该是这样的.

是翻译函数,它采用像enum或int这样的标准参数并提供本地化的颜色名称

我有一个正在运行的部分,但只有两种语言(德语和英语):

let colorNamesEN = [ "None","Gray","Green","Purple","Blue","Yellow","Red","Orange" ]
let colorNamesDE = [ "","Grau","Grün","Lila","Blau","Gelb","Rot","Orange" ]

public enum TagColors : Int8 {
    case None = -1,Gray,Green,Purple,Blue,Yellow,Red,Orange,Max
}

//let theURL : NSURL = NSURL.fileURLWithPath("/Users/dirk/Documents/MyLOG.txt")

extension NSURL {
    // e.g.  theURL.setColors(0b01010101)
    func tagColorValue(tagcolor : TagColors) -> UInt16 {
        return 1 << UInt16(tagcolor.rawValue)
    }

    func addTagColor(tagcolor : TagColors) -> Bool {
        let bits : UInt16 = tagColorValue(tagcolor) | self.getTagColors()
        return setTagColors(bits)
    }

    func remTagColor(tagcolor : TagColors) -> Bool {
        let bits : UInt16 = ~tagColorValue(tagcolor) & self.getTagColors()
        return setTagColors(bits)
    }

    func setColors(tagcolor : TagColors) -> Bool {
        let bits : UInt16 = tagColorValue(tagcolor)
        return setTagColors(bits)
    }

    func setTagColors(colorMask : UInt16) -> Bool {
        // get string for all available and requested bits
        let arr = colorBitsToStrings(colorMask & (tagColorValue(TagColors.Max)-1))

        do {
            try self.setResourceValue(arr,forKey: NSURLTagNamesKey)
            return true
        }
        catch {
            print("Could not write to file \(self.absoluteURL)")
            return false
        }
    }

    func getTagColors() -> UInt16 {
        return getAllTagColors(self.absoluteURL)
    }
}


// let initialBits: UInt8 = 0b00001111
func colorBitsToStrings(colorMask : UInt16) -> NSArray {
    // translate bits to (localized!) color names
    let countryCode = NSLocale.currentLocale().objectForKey(NSLocaleLanguageCode)!

    // I don't know how to automate it for all languages possible!!!!
    let colorNames = countryCode as! String == "de" ? colorNamesDE : colorNamesEN

    var tagArray = [String]()
    var bitNumber : Int = -1   // ignore first loop
    for colorName in colorNames {
        if bitNumber >= 0 {
            if colorMask & UInt16(1<<bitNumber) > 0 {
                tagArray.append(colorName)
            }
        }
        bitNumber += 1
    }
    return tagArray
}


func getAllTagColors(file : NSURL) -> UInt16 {
    var colorMask : UInt16 = 0

    // translate (localized!) color names to bits
    let countryCode = NSLocale.currentLocale().objectForKey(NSLocaleLanguageCode)!
    // I don't know how to automate it for all languages possible!!!!
    let colorNames = countryCode as! String == "de" ? colorNamesDE : colorNamesEN
    var bitNumber : Int = -1   // ignore first loop

    var tags : AnyObject?

    do {
        try file.getResourceValue(&tags,forKey: NSURLTagNamesKey)
        if tags != nil {
            let tagArray = tags as! [String]

            for colorName in colorNames {
                if bitNumber >= 0 {
                    // color name listed?
                    if tagArray.filter( { $0 == colorName } ).count > 0 {
                        colorMask |= UInt16(1<<bitNumber)
                    }
                }
                bitNumber += 1
            }
        }
    } catch {
        // process the error here
    }

    return colorMask
}
历史

首先是我之前的答案,它适用于将一个颜色标签设置为文件https://stackoverflow.com/a/39751001/2227743.

然后@mz2发布了这个优秀的答案,成功地为文件设置了几个颜色标签并解释了这个过程:https://stackoverflow.com/a/40314367/2227743.

现在这个小插件,一个简单的follow-up到@ mz2的答案.

我只是简单地实现了@ mz2的建议:我已经使用获取Finder首选项的方法扩展了他的枚举示例,并在将属性设置到文件之前提取了正确的本地化标签颜色名称.

enum LabelColors: Int {
    case none
    case gray
    case green
    case purple
    case blue
    case yellow
    case red
    case orange

    func label(using list: [String] = []) -> String? {
        if list.isEmpty || list.count < 7 {
            switch self {
            case .none: return nil
            case .gray: return "Gray\n1"
            case .green: return "Green\n2"
            case .purple: return "Purple\n3"
            case .blue: return "Blue\n4"
            case .yellow: return "Yellow\n5"
            case .red: return "Red\n6"
            case .orange: return "Orange\n7"
            }
        } else {
            switch self {
            case .none: return nil
            case .gray: return list[0]
            case .green: return list[1]
            case .purple: return list[2]
            case .blue: return list[3]
            case .yellow: return list[4]
            case .red: return list[5]
            case .orange: return list[6]
            }
        }
    }

    static func set(colors: [LabelColors],to url: URL,using list: [String] = []) throws
    {
        // 'setExtendedAttributeData' is part of https://github.com/billgarrison/SOExtendedAttributes
        try (url as NSURL).setExtendedAttributeData(propertyListData(labels: colors,using: list),name: "com.apple.Metadata:_kMDItemUserTags")
    }

    static func propertyListData(labels: [LabelColors],using list: [String] = []) throws -> Data
    {
        let labelStrings = labels.flatMap { $0.label(using: list) }
        return try PropertyListSerialization.data(fromPropertyList: labelStrings,format: .binary,options: 0)
    }

    static func localizedLabelNames() -> [String] {
        // this doesn't work if the app is SandBoxed:
        // the users would have to point to the file themselves with NSOpenPanel
        let url = URL(fileURLWithPath: "\(NSHomeDirectory())/Library/SyncedPreferences/com.apple.finder.plist")

        let keyPath = "values.FinderTagDict.value.FinderTags"
        if let d = try? Data(contentsOf: url) {
            if let plist = try? PropertyListSerialization.propertyList(from: d,options: [],format: nil),let pdict = plist as? NSDictionary,let ftags = pdict.value(forKeyPath: keyPath) as? [[AnyHashable: Any]]
            {
                var list = [(Int,String)]()
                // with '.count == 2' we ignore non-system labels
                for item in ftags where item.values.count == 2 {
                    if let name = item["n"] as? String,let number = item["l"] as? Int {
                        list.append((number,name))
                    }
                }
                return list.sorted { $0.0 < $1.0 }.map { "\($0.1)\n\($0.0)" }
            }
        }
        return []
    }
}

用法

do {
    // default English label names
    try LabelColors.set(colors: [.yellow,.red],to: fileURL)

    // localized label names
    let list = LabelColors.localizedLabelNames()
    try LabelColors.set(colors: [.green,.blue],to: fileURL,using: list)
} catch {
    print("Error when setting label color(s): \(error)")
}

猜你在找的Swift相关文章