Skip to content

Instantly share code, notes, and snippets.

@SKaplanOfficial
Last active October 26, 2023 01:25
Show Gist options
  • Save SKaplanOfficial/6d7ce9b07488ca71aaa463f3f3f8b5c7 to your computer and use it in GitHub Desktop.
Save SKaplanOfficial/6d7ce9b07488ca71aaa463f3f3f8b5c7 to your computer and use it in GitHub Desktop.
JXA/ASObjC script to briefly summarize methods and properties of an Objective-C class using objc runtime methods (e.g. class_copyMethodList, method_getTypeEncoding, etc.). The script reports method names, the number of arguments they accept, the argument types, property names, property types, and property attributes such as read-only and nonatomic.
(() => {
ObjC.import('objc');
ObjC.import('AppKit')
// Get methods of ObjC class, store # of methods and properties in reference objects
const targetClass = $.NSImage;
const num_methods = Ref();
const num_properties = Ref();
const methods = $.class_copyMethodList(targetClass, num_methods);
const properties = $.class_copyPropertyList(targetClass, num_properties)
// Log name and argument info of each method
console.log(num_methods[0], "Methods:");
for (let i=0; i<num_methods[0]; i++) {
const method = methods[i];
console.log("\t", $.method_getName(method));
console.log("\t\tType Encoding:", $.method_getTypeEncoding(method));
console.log("\t\tArg Count:", $.method_getNumberOfArguments(method));
}
// ObjC property type encodings
const typeEncodings = {
"Tc": "char",
"Ti": "int",
"Ts": "short",
"Tl": "long",
"Tq": "long long",
"TC": "unsigned char",
"TI": "unsigned int",
"TS": "unsigned short",
"TL": "unsigned long",
"TQ": "unsigned long long",
"Tf": "float",
"Td": "double",
"TB": "bool",
"Tv": "void",
"T*": "char string",
"T@": "object",
"T#": "Class",
"T:": "Selector",
"T[": "array",
"T{": "structure",
"T(": "union",
"Tb": "bit field",
"T^": "pointer",
"T?": "unknown"
};
// Log name and attribute info of each property
console.log("\n");
console.log(num_properties[0], "Properties:");
for (let i=0; i<num_properties[0]; i++) {
const method = properties[i];
console.log("\t", $.property_getName(method));
const attributeString = $.property_getAttributes(method)
let attributeSummary = "";
// Format the type nicely
const typeEncoding = attributeString.split(/(,| )/g)[0]
attributeSummary += typeEncodings[typeEncoding.slice(0,2)]
if (typeEncoding.length > 2) {
const data = typeEncoding.slice(2).replaceAll(/("|\)|]|{|}|<|>|=.*)/g, "")
attributeSummary += ` (${data})`
}
// Add attribute descriptions
if (attributeString.includes(",R")) attributeSummary += ", readonly"
if (attributeString.includes(",C")) attributeSummary += ", copy"
if (attributeString.includes(",&")) attributeSummary += ", retain"
if (attributeString.includes(",N")) attributeSummary += ", nonatomic"
if (attributeString.includes(",G")) attributeSummary += ", getter"
if (attributeString.includes(",S")) attributeSummary += ", setter"
if (attributeString.includes(",D")) attributeSummary += ", dynamic"
if (attributeString.includes(",W")) attributeSummary += ", weak"
if (attributeString.includes(",P")) attributeSummary += ", eligible for garbage collection"
console.log("\t\t", attributeSummary);
}
})()
/* Output for NSImage: */
/* 256 Methods: */
/* tintedImageWithColor:operation: */
/* Type Encoding: @32@0:8@16Q24 */
/* Arg Count: 4 */
/* resizeTo: */
/* Type Encoding: @24@0:8d16 */
/* Arg Count: 3 */
/* ...
/* ...
*/
/* 42 Properties: */
/* ik_fullResolutionFileURL */
/* object (NSURL), retain, nonatomic */
/* ikProfilePictureAttributedImageName */
/* object (NSString), copy, nonatomic */
/* CGImage */
/* pointer (CGImage), readonly, nonatomic */
/* vk_imageView */
/* object (NSImageView), readonly, nonatomic */
/* willProvideAdaptedImageForPresentation */
/* bool, readonly */
/* ...
/* ...
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment