iOS と Mac でできるだけ多くの共用したコードを使えるようにするために。こんなコードをよく使っています。
#if os(iOS)
import UIKit
typealias XView = UIView
typealias XImage = UIImage
typealias XColor = UIColor
typealias XBezierPath = UIBezierPath
typealias XScrollView = UIScrollView
typealias XViewController = UIViewController
#elseif os(macOS)
import Cocoa
typealias XView = NSView
typealias XImage = NSImage
typealias XColor = NSColor
typealias XBezierPath = NSBezierPath
typealias XScrollView = NSScrollView
typealias XViewController = NSViewController
#endif
すると、以下のように以外と iOS でも mac でも使えるコードが書けたりします。
let bezier = XBezierPath(ovalIn: CGRect(x: 0, y: 0, width: 100, height: 200))
XColor.red.set()
bezier.fill()
UIColor または NSColor から R、G、B、Aの要素を取得したい時に、これを使えば、getRed(_:green:blue:alpha:)
で iOS でも macOS でも同様に r, g, b, a の要素を取得できそうですが…
var r: CGFloat = 0
var g: CGFloat = 0
var b: CGFloat = 0
var a: CGFloat = 0
XColor.white.getRed(&r, green: &g, blue: &b, alpha: &a)
iOSでは実際に値が取れるのですが、macOS ではなぜか runtime エラーとなってしまう場合があります。具象クラスはどちらも似たようなものだと思うのですが、iOS と macOS のコードを共用したい場合には障害になります。
type(of: color) // NSCachedWhiteColor.Type
type(of: color) // UICachedDeviceWhiteColor.Type
色々調べてみると、CIColor を使うと、r,g,b,a の値が綺麗に取れそうです。そこで、UIColor と NSColor の共通メソッド cgColor を介して、CIColor に変換すると、CIColor のプロパティで RGBA の値を直接取り出せそうです。
CIColor
よって以下のような extension を書いてみました。
#if os(iOS)
import UIKit
#elseif os(macOS)
import Cocoa
#endif
extension XColor {
var rgba: (r: CGFloat, g: CGFloat, b: CGFloat, a: CGFloat) {
let color = CIColor(cgColor: self.cgColor)
return (color.red, color.green, color.blue, color.alpha)
}
}
これで、iOS でも macOS でも r,g,b,a の値が綺麗に取れるようになりました。
XColor.red.rgba // (1.0, 0.0, 0.0, 1.0)
おまけ
ちなみに、UIBezierPath と NSBezierPath のメソッドも似ているのですが、addLine
と line
のように微妙な違いがあるものもあります。そんな場合は以下のような extension を用意しておけば、どちらのスタイルでも書く事が出来るので便利です。
#if os(macOS)
extension NSBezierPath {
func addLine(to point: CGPoint) { self.line(to: point) }
}
#endif
#if os(iOS)
extension UIBezierPath {
func line(to point: CGPoint) { self.addLine(to: point) }
}
#endif
[環境に関する表記]
Xcode Version 8.2.1 (8C1002)
Apple Swift version 3.0.2 (swiftlang-800.0.63 clang-800.0.42.1)