How to decipher "objc_method_description" from protocol method description list?
Asked Answered
P

1

3

I have some Swift 3 code to decode an iOS Objective-C protocol (which has a Swift counterpart). After concluding Swift 3 reflection was not developed enough to accomplish what I needed, I stumbled on the objc runtime method protocol_copyMethodDescriptionList(), which returns an array of the following C structs:

struct objc_method_description
     SEL name;
     char *types;
};

The code fetches a list of protocol selector names, but not sure what's being returned in the type field. I'm confused about how to properly decode objc_method_description.type values.

What I'm getting in the the type fields are in a cryptic format, for example, "B48@0:8@16{_NSRange=QQ}24@40" At first I thought it was a problem in how I was converting C strings, but after some study, I suspect it actually is an encoding of the parameters, similar how Java's JVM passes around method signatures. But I still have no reference by which to decode it.

import UIKit

class ViewController: UIViewController, UITextViewDelegate {

    @IBOutlet weak var noteView : UITextView!

    func decodeProto() {
        var methodCount : UInt32 = 1
        if let methodList = protocol_copyMethodDescriptionList(UITextViewDelegate.self,
                  false, true,  UnsafeMutablePointer<UInt32>(&methodCount)) {
            for i in 0..<Int(methodCount) {
                let methodDesc = methodList[i];
                let name = methodDesc.name
                let types = String(validatingUTF8: methodDesc.types)
                print("\(name) \(types)")
            }
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        decodeProto()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

The output of that in the XCode console is:

Optional(textViewDidBeginEditing:) Optional("v24@0:8@16")
Optional(textViewDidEndEditing:) Optional("v24@0:8@16")
Optional(textViewShouldBeginEditing:) Optional("B24@0:8@16")
Optional(textViewShouldEndEditing:) Optional("B24@0:8@16")
Optional(textView:shouldChangeTextInRange:replacementText:) Optional("B48@0:8@16{_NSRange=QQ}24@40")
Optional(textView:shouldChangeTextInRange:replacementText:) Optional("B48@0:8@16{_NSRange=QQ}24@40")
.
.
.

Polymer answered 6/1, 2017 at 9:3 Comment(3)
What are you planning to do with this information?Wensleydale
Right, I'm not sure if this will be possible in Swift because you would want to use invocations...Wensleydale
@Wensleydale - To answer your first question, I'm trying to 'automate' the code in this answer: https://mcmap.net/q/54030/-placeholder-in-uitextview. As for your 2nd point - I deleted the other comments, so you can remove that if it makes sense to now ;-)Polymer
P
5

What is returned objc_method_description.type field?

  • A method signature encoding scheme
  • ... which includes an obsolete stack offset representation

In other words, to get a usable method signature encoding from the type field, just just extract the alpha-symbolic characters in left-to-right order discarding the digits.

Supporting documentation:


Polymer answered 7/1, 2017 at 19:5 Comment(2)
As a general rule, documentation for this kind of stuff in the Objective-C APIs is done at the method level - in this case, class_addMethod: developer.apple.com/reference/objectivec/… Next time you find yourself on a goose chase, consider asking the question - what methods does this come from?Tamelatameless
Thanks. Updated answer.Polymer

© 2022 - 2024 — McMap. All rights reserved.