Swift 3:设置Finder标签颜色 [英] Swift 3: Set Finder label color

查看:234
本文介绍了Swift 3:设置Finder标签颜色的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试设置取景器显示的彩色标签。我唯一知道的函数是setResourceValue。但这需要本地化的名字!



我可以形象我的母语和英语,但所有其他我不知道。我不能相信,这应该是方式。



是翻译函数,它接受一个标准参数,如enum或int,并传递本地化的颜色名称?



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

  let colorNamesEN = [None ,Grau,Grün,Grün,Grün,Grun Lila,Blau,Gelb,Rot,Orange] 

public enum TagColors:Int8 {
case None = -1,Gray,Green,Purple,Blue ,黄色,红色,橙色,最大
}

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

extension NSURL {
// eg 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 {
//获取所有可用和请求的位的字符串
let arr = colorBitsToStrings(colorMask&(tagColorValue(TagColors.Max)-1))

do {
try self.setResourceValue(arr,forKey:NSURLTagNamesKey)
return true
}
catch {
print(无法写入文件\(self.absoluteURL) )
return false
}
}

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


// let initialBits:UInt8 = 0b00001111
func colorBitsToStrings colorMask:UInt16) - > NSArray {
//将位转换为(localized!)颜色名称
let countryCode = NSLocale.currentLocale()。objectForKey(NSLocaleLanguageCode)!

//我不知道如何为所有语言自动化它!
让colorNames = countryCode as! String ==de? colorNamesDE:colorNamesEN

var tagArray = [String]()
var bitNumber:Int = -1 //忽略第一个循环
colorNames中的colorName {
if bitNumber > = 0 {
if colorMask& UInt16(1 tagArray.append(colorName)
}
}
bitNumber + = 1
}
return tagArray
}


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

//将颜色名称转换为位
let countryCode = NSLocale.currentLocale()。objectForKey(NSLocaleLanguageCode)!
//我不知道如何为所有语言自动化它!
让colorNames = countryCode as! String ==de? colorNamesDE:colorNamesEN
var bitNumber:Int = -1 //忽略第一个循环

var tags:AnyObject?

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

colorNames中的colorName {
if bitNumber> = 0 {
//颜色名称是否列出?
if tagArray.filter({$ 0 == colorName}).count> 0 {
colorMask | = UInt16(1< bitNumber)
}
}
bitNumber + = 1
}
}
} catch {
//在此处理错误
}

return colorMask
}


解决方案

历史



,用于将一个颜色标签设置为文件: http://stackoverflow.com/a/39751001 / 2227743



然后 @ mz2 发布这个极好的答案成功地将几个颜色标签设置为文件,并说明了过程: http:// stackoverflow。 com / a / 40314367/2227743



现在这个小插件,一个简单的跟进到@ 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] = []) - >串? {
if list.isEmpty || list.count< 7 {
switch self {
case .none:return nil
case .gray:returnGray\\\
1
case .green:returnGreen\\\
2
case .purple:returnPurple\\\
3
case .blue:returnBlue\\\
4
case .yellow:returnYellow\\\
5
case。 red:returnRed\\\
6
case .orange:returnOrange\\\
7
}
} else {
switch self {
case .none :return nil
case .gray:return list [0]
case .green:return list [1]
case .purple:return list [2]
case .blue:返回列表[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'是https://github.com/billgarrison/SOExtendedAttributes
的一部分try(url as NSURL).setExtendedAttributeData(propertyListData(labels:colors,using:列表),
名称: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] {
//如果应用程序是Sandboxed则无效:
//用户必须使用NSOpenPanel指向文件本身
let url = URL(fileURLWithPath: $\\\\\\\\\\\\\\(NSHomeDirectory())/Library/SyncedPreferences/com.apple.finder.plist)

let keyPath =values.FinderTagDict.value.FinderTags
如果let d =尝试?数据(contentsOf:url){
如果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 {
如果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)\\\
\($ 0.0)}
}
}
return []
}
}

用法:

  do {
//默认英语标签名称
try LabelColors.set(colors:[.yellow,.red],
to:fileURL)

//局部化的标签名
let list = LabelColors.localizedLabelNames()
try LabelColors.set(colors:[.green,.blue],
to:fileURL,
using:列表)
} catch {
print(设置标签颜色时出错:\(error))
}
pre>

I'm trying to set the colored labels shown by the finder. The only function I know is setResourceValue. But this needs localized names!

I could image my mother language and english as well, but all others I don't know. I can't believe, that this should be the way.

Is the are translation function, which takes a standard parameter like an enum or int and delivers the localized color name?

I have an running part, but only for two languages (German and English):

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
}

解决方案

History

First there was my previous answer, which works for setting one color label to a file: http://stackoverflow.com/a/39751001/2227743.

Then @mz2 posted this excellent answer which successfully sets several color labels to a file and explains the process: http://stackoverflow.com/a/40314367/2227743.

And now this little add-on, a simple follow-up to @mz2's answer.

Solution

I've simply implemented @mz2's suggestion: I've expanded his enum example with methods for fetching the Finder's preferences and extract the correct localized label color names before setting the attributes to the file.

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 []
    }
}

Usage:

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 3:设置Finder标签颜色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆