我正在尝试设置取景器显示的彩色标签.我所知道的唯一功能是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)") }