mNo edit summary |
No edit summary |
||
Line 83: | Line 83: | ||
} | } | ||
</source> | </source> | ||
== Replacing existing Objective-C methods == | |||
You can simulate MSHookMessage by replacing contents in the <tt>messages</tt> array, e.g. | |||
<source lang="javascript"> | |||
cy# original_NSRunLoop_description = NSRunLoop.messages['description']; | |||
0x339d94c3 | |||
cy# NSRunLoop.messages['description'] = function() { return original_NSRunLoop_description.call(this).toString().substr(0, 80)+", etc."; } | |||
{} | |||
cy# [NSRunLoop currentRunLoop] | |||
"<CFRunLoop 0x205ee0 [0x381dbff4]>{locked = false, wait port = 0x1303, stopped = , etc." | |||
</source> | |||
Note the <tt>func.call(self)</tt> construct. This binds the <tt>self</tt> in the original function to the user-specified one. If more than one variable is needed, use <tt>func.call(self, arg1, arg2, arg3, ...)</tt>. Note that the subsequent arguments will not be automatically mapped to the corresponding Objective-C types, so instead of "foo" you will need to use <tt>[NSString stringWithString:"foo"]</tt>. |
Revision as of 18:42, 5 November 2009
Printing Ivars
Often just typing *varName works:
cy# *controller
{isa:"PrefsRootController",_contentView:"<UIView: 0x10bd70; frame = (0 0; 320 460); autoresize = W+H; layer = <CALayer: 0x150120>>",_navBar:...
cy#
Sometimes it does not...
cy# *UIApp
{message:"hasProperty callback returned true for a property that doesn't exist.",name:"ReferenceError"}
then you can do:
cy# [i for (i in *UIApp)]
["isa","_delegate","_touchMap","_exclusiveTouchWindows","_event",...
You may use this function to get as much ivar values as possible:
function tryPrintIvars(a){ var x={}; for(i in *a){ try{ x[i] = (*a)[i]; } catch(e){} } return x; }
To use:
cy# *a
{message:"hasProperty callback returned true for a property that doesn't exist.",name:"ReferenceError"}
cy# tryPrintIvars(a)
{isa:"SBWaveView",_layer:"<CALayer: 0x2a5160>",_tapInfo:null,_gestureInfo:null,_gestureRecognizers:...
Printing Methods
Function to get the methods:
function printMethods(className) {
var count = new new Type("I");
var methods = class_copyMethodList(objc_getClass(className), count);
var methodsArray = [];
for(var i = 0; i < *count; i++) {
var method = methods[i];
methodsArray.push({selector:method_getName(method), implementation:method_getImplementation(method)});
}
free(methods);
free(count);
return methodsArray;
}
Usage:
cy# printMethods("MailboxPrefsTableCell")
[{selector:@selector(layoutSubviews),implementation:0x302bf2e9},{selector:@selector(setCurrentMailbox:),implementation:0x302bee0d},...
cy#
Get methods matching particular RegExp
function methodsMatching(cls, regexp) { return [[new Selector(m).type(cls), m] for (m in cls.messages) if (!regexp || regexp.test(m))]; }
Usage:
cy# methodsMatching(NSRunLoop, /forKey:$/)
[["v20@0:4I8@12@16","didChange:valuesAtIndexes:forKey:"],["v20@0:4I8@12@16","willChange:valuesAtIndexes:forKey:"],["v16@0:4@8@12","setValue:forKey:"]]
Getting Objective-C Objects from Addresses
Use new Instance(0xdeadbabe).
cy# var p = new Instance(0x8614390)
cy# p
["<SKPaymentTransaction: 0x8613d80>"]
Load frameworks
function loadFramework(fw) {
var h="/System/Library/",t="Frameworks/"+fw+".framework";
[[NSBundle bundleWithPath:h+t]||[NSBundle bundleWithPath:h+"Private"+t] load];
}
Replacing existing Objective-C methods
You can simulate MSHookMessage by replacing contents in the messages array, e.g.
cy# original_NSRunLoop_description = NSRunLoop.messages['description'];
0x339d94c3
cy# NSRunLoop.messages['description'] = function() { return original_NSRunLoop_description.call(this).toString().substr(0, 80)+", etc."; }
{}
cy# [NSRunLoop currentRunLoop]
"<CFRunLoop 0x205ee0 [0x381dbff4]>{locked = false, wait port = 0x1303, stopped = , etc."
Note the func.call(self) construct. This binds the self in the original function to the user-specified one. If more than one variable is needed, use func.call(self, arg1, arg2, arg3, ...). Note that the subsequent arguments will not be automatically mapped to the corresponding Objective-C types, so instead of "foo" you will need to use [NSString stringWithString:"foo"].