【Swift】xmlで管理している色情報を簡単に扱う
はじめに
今回は、xmlで色を管理した場合に、簡単に扱えるようにしたいと思います。
xmlについて
以下のフォーマットでxmlを用意します。
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="buttonBackGround">#285176</color> <color name="buttonText">#305c83</color> . . . </resources>
コード
今回は、色に関してのみですが、xmlファイル1つで色々とまとめて管理することができるので、使い回しがしやすいように、クラスを分けています。
class XMLUtil: NSObject, XMLParserDelegate { var parser: XMLParser! var compleationBlock: (([String : String]?)->Void) = {_ in} var element: String! var attribute: String! var tmpDic: [String : String]! var tmpKey: String! public func parse(fileName: String, element: String! = nil, attribute: String! = nil, compleation: @escaping (([String : String]?)->Void)) { self.element = element self.attribute = attribute compleationBlock = compleation guard let tmpData: Data = loadAssetFile(name: fileName) else { self.compleationBlock(nil) return } parser = XMLParser(data: tmpData) parser.delegate = self let _ = parser.parse() } private func loadAssetFile(name: String) -> Data! { var data: Data! = nil // Assetsから取得 if #available(iOS 9.0, *) { if let tmpData = NSDataAsset(name: name) { data = tmpData.data } } return data } // MARK: - NSXMLParserDelegate public func parserDidStartDocument(_ parser: XMLParser) { tmpDic = [ : ] } public func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) { guard let _ = element else { tmpKey = elementName return } guard let _ = attribute else { tmpKey = element return } if elementName == element { guard let key = attributeDict[attribute] else { return } tmpKey = key } } public func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) { tmpKey = nil } public func parser(_ parser: XMLParser, foundCharacters string: String) { guard let _ = tmpKey else { return } tmpDic[tmpKey] = string } public func parserDidEndDocument(_ parser: XMLParser) { self.compleationBlock(tmpDic) } }
class XMLColorUtil: NSObject { private var colors: [String : String]! = nil static var shared: XMLColorUtil = { let instance = XMLColorUtil() let res = instance.loadColors() return instance }() private override init() { } internal func loadColors() { var finish = false XMLUtil().parse(fileName: "colors", element: "color", attribute: "name") { dic in if dic != nil { self.colors = dic } finish = true } } public func getColor(key: String = #function) -> UIColor { guard let _ = colors else { return .white } guard let hexColor = colors[key] else { return .white } return UIColor(hex: hexColor) } }
extension UIColor { convenience init(hex: String) { let range = NSMakeRange(0, rgbString.characters.count) let hexStr = (rgbString as NSString).replacingOccurrences(of: "[^0-9a-fA-F]", with: "", options: .regularExpression, range: range) var r: Float = 1 var g: Float = 1 var b: Float = 1 let a: Float = 1 if hexStr.characters.count == 6 { if let num = Int(hexStr, radix: 16) { r = Float((num >> 16) & 0xFF) / 255.0 g = Float((num >> 8) & 0xFF) / 255.0 b = Float((num) & 0xFF) / 255.0 } } self.init(red: CGFloat(r), green: CGFloat(g), blue: CGFloat(b), alpha: CGFloat(a)) } }
色クラス
class AppColor: NSObject { private let util = XMLColorUtil.shared // xml上のnameと合わせる public var buttonBackGround: UIColor { return util.getColor() } public var buttonText: UIColor { return util.getColor() } . . . }
このクラスに上にxmlでname属性に設定した値をプロパティとして定義し、XMLColorUtil
クラスのgetColor()
を呼びます
getColor()
の引数の初期値は#function
なので、呼び出し元のメソッド名を取得するようになっています。
XMLColorUtil().getColor(key: "buttonBackGround")
とすることもできます。
使い方
let appColor = AppColor() let button = UIButton(frame: CGRect(origin: .zero, size: CGSize(width: 100, height: 60))) button.backgroundColor = appColor.buttonBackGround button.setTitleColor(appColor.buttonText, for: .normal)
使用する色が増えた際には、xml編集後、AppColor
クラスにプロパティを追加するだけで使えるようになります。