swift: Equivalent objective-c runtime class
First, it's hard to translate that code to Swift without knowing what you used that class object for in Objective-C.
In Objective-C, class objects are objects, and the type Class
can hold a pointer to any class object. However, when Objective-C APIs are bridged to Swift, the type Class
is converted to AnyClass!
in Swift, where AnyClass
is defined as AnyObject.Type
. Types in Swift are not objects, and thus are not directly equivalent to class objects in Objective-C. However, if you intend to use an Objective-C API from Swift, it will have been bridged to expect AnyClass
anyway, so you have to pass a type. You can get the type of any expression using .dynamicType
; for example:
self.dynamicType
(If you really want to get the class object as an Swift object the same way as in Objective-C, and not as a Swift type, there are some convoluted ways to do that too.)
However, your description of your problem reveals another issue. If you just want to get the type of an object, and self
is an object, then var klass: AnyClass = object_getClass(self)
should have worked, since object_getClass()
takes an AnyObject
and returns an AnyClass
. The only explanation for it not working is if self
is not an object. Your error message reveals that, indeed, self
is a type, not an object.
self
is a type if this code is running in a class method. You should have really given context for your code (obviously, you didn't put Class class = [self class];
at the top level of a file), because taken out of context it's easy to misunderstand. In Objective-C Cocoa, there are two very different methods named class
: an instance method, -class
, which returns the class of the object, and a class method, +class
, which simply returns the (class) object it's called on. Since your code is in a class method, in Objective-C, self
points to a class object, and [self class]
runs the class method +class
, which just returns the object it's called on. In other words, [self class]
is exactly identical to self
. You should have just written self
all along, but didn't realize it.
So the answer is that the Objective-C should have been
Class class = self;
and similarly the Swift should be
var klass: AnyClass = self
Swift Objective-C runtime class naming
They're not random. They're the length of the following value. This is similar to common C++ name mangling and supports identifiers that may have fairly arbitrary characters in them without needing some new separator character. It also can make them easier to parse, especially in C.
In this particular case, it's _TtC
then "an eleven character module name" then the module name and then "a fourteen character class name" and the class name. I assume C
is class. Not sure about Tt
(maybe "type").
What are objective c runtime features?
Quoting the apple docs
The Objective-C runtime is a runtime library that provides support for the dynamic properties of the Objective-C language, and as such is linked to by all Objective-C apps. Objective-C runtime library support functions are implemented in the shared library found at /usr/lib/libobjc.A.dylib.
That API is useful primarily for developing bridge layers between Objective-C and other languages, or for low-level debugging. You most likely don't need to use it.
Even when written without a single line of Objective-C code, every Swift app executes inside the Objective-C runtime, so that's why you can access it.
You can do things like swizzling
equivalent to [obj class] in Swift?
The equivalent of [obj class] in SWIFT is :
obj.dynamicType
Getting class name in SWIFT equivalent to Objective C [self class]?
You can use print("Class = \(type(of: self))"
in Swift.
Swift runtime - calling superclass method
As Martin says, objc_msgSendSuper
isn't available in Swift because it's a C variadic function, which Swift doesn't import due to the lack of type safety.
One alternative is to use class_getMethodImplementation
in order to get a pointer to the function to call for a selector on a given class type. From there, you can cast it to a function type which Swift can call using unsafeBitCast
, taking care that the parameter and return types match up.
For example:
import Foundation
class C {
@objc func foo() {
print("C's foo")
}
}
class D : C {
override func foo() {
print("D's foo")
}
}
let d = D()
let superclass: AnyClass = class_getSuperclass(type(of: d))!
let selector = #selector(C.foo)
// The function to call for a message send of "foo" to a `C` object.
let impl = class_getMethodImplementation(superclass, selector)!
// @convention(c) tells Swift this is a bare function pointer (with no context object)
// All Obj-C method functions have the receiver and message as their first two parameters
// Therefore this denotes a method of type `() -> Void`, which matches up with `foo`
typealias ObjCVoidVoidFn = @convention(c) (AnyObject, Selector) -> Void
let fn = unsafeBitCast(impl, to: ObjCVoidVoidFn.self)
fn(d, selector) // C's foo
Note that like objc_msgSendSuper
this assumes that the return type bridged to Obj-C is layout compatible with a pointer. This is true in most cases (including yours), but wouldn't be true for a method returning a type such as CGRect
, which is represented in Obj-C using a C structure type.
For those cases, you would need to use class_getMethodImplementation_stret
instead:
import Foundation
class C {
@objc func bar() -> CGRect {
return CGRect(x: 2, y: 3, width: 4, height: 5)
}
}
class D : C {
override func bar() -> CGRect {
return .zero
}
}
let d = D()
let superclass: AnyClass = class_getSuperclass(type(of: d))!
let selector = #selector(C.bar)
let impl = class_getMethodImplementation_stret(superclass, selector)!
typealias ObjCVoidVoidFn = @convention(c) (AnyObject, Selector) -> CGRect
let fn = unsafeBitCast(impl, to: ObjCVoidVoidFn.self)
let rect = fn(d, selector)
print(rect) // (2.0, 3.0, 4.0, 5.0)
The distinction between class_getMethodImplementation
and class_getMethodImplementation_stret
is due to the difference in calling convention – a word sized type can be passed back through a register, however a structure of larger size needs to be passed back indirectly. This matters for class_getMethodImplementation
because it could pass back a thunk for message forwarding in the case where the object doesn't respond to the selector.
Another option is to use method_getImplementation
, which doesn't perform message forwarding and therefore doesn't need to distinguish between stret and non-stret.
For example:
let impl = method_getImplementation(class_getInstanceMethod(superclass, selector)!)
However bear in mind that the documentation notes:
class_getMethodImplementation
may be faster thanmethod_getImplementation(class_getInstanceMethod(cls, name))
.
At runtime, how do I list all Objective-C class methods for a given class?
Each Objective-C @implementation
is represented at run time by an object, the “class object”. The class object manages the method dictionary for instance methods.
For example, for UIView
, there is an UIView
class object. When you call NSClassFromString(@"UIView")
(or [UIView class]
or [UIView self]
), it returns the UIView
class object. The UIView
class object manages the method dictionary for UIView
instance methods.
The UIView
class object is itself an instance of another class, called the UIView
metaclass. The UIView
metaclass is represented by another class object, the UIView
metaclass object. The UIView
metaclass object manages the method dictionary for UIView
class methods.
So, to get the class method list for UIView
, you need to pass the UIView
metaclass object to class_copyMethodList
.
Class UIView_class = NSClassFromString(@"UIView");
Class UIView_metaclass = object_getClass(UIView_class);
unsigned int count;
Method *classMethods = class_copyMethodList(UIView_metaclass, &count);
Swift - Objective-C load class method?
Prior to Swift 1.2:
override class func load() {
NSLog("load");
}
EDIT:
As of Swift 1.2 you can no longer override the load
method. Look into the method initialize
instead, it behaves different than load though, it get's called the first time the class is being referenced somewhere rather than on application initial load
Related Topics
iOS 10 Rich Media Push Notification (Media Attachment) in Objective-C
Uicollectionview Multiple Sections and Headers
(iOS + Storekit) How to Detect When I'm in the Sandbox
Ios/Swift - Hide/Show Uitabbarcontroller When Scrolling Down/Up
Detect Tap on Calloutbubble in Mkannotationview
Get Average Color of Uiimage in Swift
How to Restrict the iOS App Only for iPhone Excluding iPad
Better Way to Get the User's Name from Device
How to Set Selected Segment Index in Uisegmentedcontrol
Is -[Uitableview Reloaddata] Asynchronous or Synchronous
Pop the Current View Using Segues/Storyboard on iOS 5
How to Detect a Dual Core CPU on iOS
Swift: Custom Camera Save Modified Metadata with Image
Change Uifont in Secure Uitextfield Strange Behaviour in iOS7
Customizing the Mkannotation Callout Bubble