20

I want to get current method name to use in a format message similar to this one

[NSExeception raise:NSInternalInconsistencyException format:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)]

Also, I want to use _cmd to set associated object. I appreciate any idea.

LongNV
  • 892
  • 9
  • 21

2 Answers2

41
NSStringFromSelector(_cmd); // Objective-C

print(#function) // Swift 4, 5
Huynh Inc
  • 2,010
  • 1
  • 25
  • 42
  • 2
    "__FUNCTION__" will be deprecated and will be removed from Swift 3, therefore, use instead: #function – David.Chu.ca Apr 06 '16 at 04:48
  • 4
    To be exact debug identifiers like `__FILE__`, `__LINE__`, `__COLUMN__` and `__FUNCTION__` have been replaced by `#file`, `#line`, `#column` and `#function` in **Swift 2.2**. – cherrmanncom Apr 27 '16 at 14:41
  • https://github.com/apple/swift-evolution/blob/master/proposals/0028-modernizing-debug-identifiers.md – i_am_jorf Dec 09 '16 at 05:14
  • This is not same. `_cmd` is a selector type, and `#function` is not `#selector` type. – eonil Feb 25 '19 at 04:35
1

There is no Swift equivalent of _cmd. There is little reason to use it in Swift.

Consider _cmd in Objective-C. When is it useful? Most of the time, the value of _cmd would be the same as the name of the method that the code is in, so it is already known at compile time, and there is no need for a runtime value. Here are some possible cases when _cmd is useful in Objective-C:

  • In a macro. The macro is expanded in the code, so if _cmd appears in the macro, then it is inserted into the source where it is used, and so the method name can be used inside the macro. However, such macros do not exist in Swift. Plus macros are compile-time, so a compile-time mechanism like __FUNCTION__ would work similarly.
  • You can define a C function that takes self and _cmd, and use it (the same function) as the implementation of multiple methods, by adding it using class_addMethod and class_replaceMethod, and the _cmd inside the function will help distinguish between the different method calls. However, class_addMethod and class_replaceMethod are not available in Swift.
  • Method swizzling is also a process that messes with the implementation of a method. Since in swizzling you swap the implementations of two methods, _cmd will help reveal the actual method name used in the call, which may not match the method that the code is in in the source code, since implementations are swapped. I guess method swizzling may still be possible in Swift, since method_exchangeImplementations is still available in Swift. But in method swizzling, the method you swap in is tailored for the method it is swapping with, so if it is called, there is no ambiguity which method name is being called.
  • In the case where you manually get the IMP (implementing function) of a method, and manually call it with a different selector. In this case, the inside of the function can see the different selector in _cmd. However, you don't have to worry about this in Swift because the methods that get the IMP are unavailable.
newacct
  • 119,665
  • 29
  • 163
  • 224
  • Swizzling should be a last emergency solution for framework bugs. Said that, here's a post about the Swift run-time by **NSHipster** [swizzling in Swift](http://nshipster.com/swift-objc-runtime/) – Matteo Piombo Jan 30 '15 at 03:50
  • I beg to differ. Sort Descriptors. I like to use a method's accessor name, so that if the attribute's name changes, the compiler complains. – horseshoe7 Dec 05 '16 at 15:17
  • Aside swizzling, one reason would be to override an optional protocol selector more cleanly. If super.responds(to:_cmd) would be a clean improvement. – xtravar Mar 05 '18 at 22:58