Swift 3:设置Finder标签颜色 [英] Swift 3: Set Finder label color
问题描述
我尝试设置取景器显示的彩色标签。我唯一知道的函数是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 {
pre>
//默认英语标签名称
try LabelColors.set(colors:[.yellow,.red],
to:fileURL)
//局部化的标签名
let list = LabelColors.localizedLabelNames()
try LabelColors.set(colors:[.green,.blue],
to:fileURL,
using:列表)
} catch {
print(设置标签颜色时出错:\(error))
}
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屋!