JAL JAL - 3 months ago 54
Objective-C Question

How do I expose a private class method of an Objective-C object using protocols in Swift?

Consider two private methods on


  1. The instance method
    which returns the RGB string of the color

  2. The class method
    which returns the red color used by destructive buttons.

UIColor.h private header for reference

For instance methods, I can create an
protocol and use
to expose the private method:

@objc protocol UIColorPrivate {
func styleString() -> UIColor

let white = UIColor.whiteColor()
let whitePrivate = unsafeBitCast(white, UIColorPrivate.self)
whitePrivate.styleString() // rgb(255,255,255)

However, I'm not sure how this would work for class methods.

First attempt:

@objc protocol UIColorPrivate {
class func _systemDestructiveTintColor() -> String // Error: Class methods are only allowed within classes

Makes sense, I'll change it to

@objc protocol UIColorPrivate {
static func _systemDestructiveTintColor() -> String

let colorClass = UIColor.self
let privateClass = unsafeBitCast(colorClass, UIColorPrivate.self) // EXC_BAD_ACCESS

This causes a crash. Well this is going nowhere fast. I could use a bridging header and just expose the class methods as an
, but is there a way to expose these private class methods in pure Swift?

I could do this with
, but I'd rather expose the method as an interface or protocol:

if UIColor.respondsToSelector("_systemDestructiveTintColor") {
if let red = UIColor.performSelector("_systemDestructiveTintColor").takeUnretainedValue() as? UIColor {
// use the color


One way to achieve what you want via protocols is to use a separate protocol for the static method. Static methods in Objective-C are actually instance methods on the metaclass of the class, so you can safely take an approach like below:

@objc protocol UIColorPrivateStatic {
    func _systemDestructiveTintColor() -> UIColor

let privateClass = UIColor.self as! UIColorPrivateStatic
privateClass._systemDestructiveTintColor() // UIDeviceRGBColorSpace 1 0.231373 0.188235 1

This will give you both exposure of the private method and usage of protocols, and you get rid of the ugly unsafeBitCast (not that a forced cast would be more beautiful).

Just note that as always if you are working with private API's your code can break at any time if Apple decides to change some of the internals of the class.