Giter Club home page Giter Club logo

maobjcruntime's Introduction

MAObjCRuntime

MAObjCRuntime is an ObjC wrapper around the Objective-C runtime APIs. If that's confusing, it provides a nice object-oriented interface around (some of) the C functions in /usr/include/objc.

MAObjCRuntime is released under a BSD license. For the official license, see the LICENSE file.

Quick Start

The action begins in MARTNSObject.h. Various methods are added to NSObject to allow querying and manipulation. Most of these are class methods, because they operate on classes. There are a couple of instance methods as well. All of these methods start with rt_ to avoid name conflicts. The RTMethod and RTIvar classes are used to represent a single method and a single instance variable, respectively. Their use should be fairly obvious.

Querying

You can query any class's methods, instance variables, or other attributes using the methods provided. For example:

// get all subclasses of a class
NSArray *subclasses = [MyClass rt_subclasses];

// check out the methods on NSString
NSArray *methods = [NSString rt_methods];
for(RTMethod *method in methods)
    NSLog(@"%@", method);

// does it have any ivars?
NSLog(@"%@", [NSString rt_ivars]);

// how big is a constant string instance?
NSLog(@"%ld", (long)[[@"foo" rt_class] rt_instanceSize]);

Modifying

You can add new methods using +rt_addMethod:. You can modify the implementation of an existing method using the -setImplementation: method on RTMethod. Example:

// swizzle out -[NSObject description] (don't do this)
static NSString *NewDescription(id self, SEL _cmd)
{
    return @"HELLO WORLD!";
}

Method *description = [NSObject rt_methodForSelector: @selector(description)];
[description setImplementation: (IMP)NewDescription];

You can create new classes using +rt_createSubclassNamed: or +rt_createUnregisteredSubclassNamed:. Note that if you want to add instance variables to a class then you have to use the Unregistered version, and add them before registering the class.

Objects

Two instance methods are provided as well. -rt_class exists because Apple likes to fiddle with the return value of -class, and -rt_class always gives you the right value. -rt_setClass: does pretty much what it says: sets the class of the object. It won't reallocate the object or anything, so the new class had better have a memory layout that's compatible with the old one, or else hilarity will ensue.

Sending Messages

After getting a list of methods from a class, it's common to want to actually use those on instances of the class. RTMethod provides an easy method for doing this, as well as several convenience wrappers around it.

The basic method for sending messages is -[RTMethod returnValue:sendToTarget:]. You use it like this:

RTMethod *method = ...;
SomeType ret;
[method returnValue: &ret sendToTarget: obj, RTARG(@"hello"), RTARG(42), RTARG(xyz)];

It may seem odd to have the return value at the beginning of the argument list, but this comes closest to the order of the normal ret = [obj method] syntax.

All arguments must be wrapped in the RTARG macro. This macro takes care of packaging up each argument so that it can survive passage through the variable argument list and also includes some extra metadata about the argument types so that the code can do some basic sanity checking. No automatic type conversions are performed. If you pass a double to a method that expects an int, this method will abort. That checking is only based on size, however, so if you pass a float where an int is expected, you'll just get a bad value.

Note that while it's not 100% guaranteed, this code does a generally good job of detecting if you forgot to use the RTARG macro and warning you loudly and calling abort instead of simply crashing in a mysterious manner. Also note that there is no sanity checking on the return value, so it's your responsibility to ensure that you use the right type and have enough space to hold it.

For methods which return an object, the -[RTMethod sendToTarget:] method is provided which directly returns id instead of making you use return-by-reference. This simplifies the calling of such methods:

RTMethod *method = ...;
id ret = [method sendToTarget: obj, RTARG(@"hello"), RTARG(42), RTARG(xyz)];

There is also an NSObject category which provides methods that allows you to switch the order around to be more natural. For example:

RTMethod *method = ...;
id ret = [obj rt_sendMethod: method, RTARG(@"hello"), RTARG(42), RTARG(xyz)];

And the same idea for rt_returnValue:sendMethod:.

Finally, there are a pair of convenience methods that take a selector, and combine the method lookup with the actual message sending:

id ret = [obj rt_sendSelector: @selector(...), RTARG(@"hello"), RTARG(42), RTARG(xyz)];
SomeType ret2;
[obj rt_returnValue: &ret2 sendSelector: @selector(...), RTARG(12345)];

maobjcruntime's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

maobjcruntime's Issues

Deployable to App Store?

Hi,

Just wanted to double check this awesome library is deployable to app store.

It's really well written, I use it alot to understand how the runtime works. I didn't realize how dynamic ObjC was until I used your library to runtime inspect how UIAppearance works in iOS5.

Nice work!

-CV

Attribution for spawned project

Thanks for this great work! The RTProperty class has seeded a library I've been using heavily in a project. This library been useful enough that I've been thinking about releasing it. The library consists of a few classes, one of which is based off of RTProperty (but has grown a bit since then). I'm currently planning on using an MIT license, but which license is not something I feel strongly about. Before I released it, I wanted to check with you:

  1. that this was ok with you,
  2. what sort of attribution you would want, if any,
  3. if you had any other comments.

Thanks again for your work! It's made the objc runtime libraries far more approachable.

James

Definition of 'Protocol' must be imported from module 'ObjectiveC.Protocol' before it is required

I get the following error when compiling a project that has this library as a dependency:

MAObjCRuntime/RTProtocol.m:79:13: Definition of 'Protocol' must be imported from module 'ObjectiveC.Protocol' before it is required

It seems to only happen with XCode 7.3, running 7.2 side by side compiles and runs just fine. Wondering if something changed in 7.3 or the compiler that causes these issues?

Methods with primitive arguments

I can't seem to invoke methods that have arguments which are not 4-bytes (i.e. BOOL, CGSize, etc...). It works fine with NSInteger, CGFloat and objects. Is this a known limitation?

It always aborts at the line checking if(inSize != sigSize) in RTMethod.m

How to better use of PLCrashReporter?

Man, sorry for asking here since I cannot ask issue from the page of PLC;
I'm using your popular repository:
https://github.com/plausiblelabs/plcrashreporter

What I'm doing now is monitor cpu/gpu/memory programmatically(not monitoring crash, since there already many 3rd party lib can do that, what I'm monitoring is app's performance);

For example, when cpu overloads, I'll dump the backtrace of the suspicious thread with BSBacktraceLogger ,also I use your PLC to catch the whole trace info.

What I get is like this, by PLC:
screen shot 2017-11-02 at 7 49 45 pm

And by BSBacktraceLogger:
screen shot 2017-11-02 at 7 26 56 pm

But seems none of above stack trace can help me to analyze and find how the performance issue happens.

Generally, when we are using 3rd party "crash report" platform, we can see crash log like following, with clear line number, method, etc, which can help very much in specifying and locating issue (I know it's symboled by atos):
screen shot 2017-11-02 at 7 32 56 pm

But now my app is not crashing, just memory overloads, no crash log;
I just want to locate where or which thread or what action that caused the occasional low performance;
Am I wrong? or How can I better analyze the stack trace? Man

TestProtocolQuery fails for i386

Works fine for x86-64, but fails when built+run as i386:
2011-11-27 17:18:34.254 MAObjCRuntime[4644:a0f] Testing TestSubclasses
2011-11-27 17:18:34.263 MAObjCRuntime[4644:a0f] TestSubclasses: SUCCESS
2011-11-27 17:18:34.264 MAObjCRuntime[4644:a0f] Testing TestCreateClass
2011-11-27 17:18:34.264 MAObjCRuntime[4644:a0f] TestCreateClass: SUCCESS
2011-11-27 17:18:34.265 MAObjCRuntime[4644:a0f] Testing TestMetaclass
2011-11-27 17:18:34.266 MAObjCRuntime[4644:a0f] TestMetaclass: SUCCESS
2011-11-27 17:18:34.266 MAObjCRuntime[4644:a0f] Testing TestSetSuperclass
2011-11-27 17:18:34.267 MAObjCRuntime[4644:a0f] TestSetSuperclass: SUCCESS
2011-11-27 17:18:34.268 MAObjCRuntime[4644:a0f] Testing TestInstanceSize
2011-11-27 17:18:34.268 MAObjCRuntime[4644:a0f] TestInstanceSize: SUCCESS
2011-11-27 17:18:34.269 MAObjCRuntime[4644:a0f] Testing TestSetClass
2011-11-27 17:18:34.270 MAObjCRuntime[4644:a0f] TestSetClass: SUCCESS
2011-11-27 17:18:34.270 MAObjCRuntime[4644:a0f] Testing TestMethodList
2011-11-27 17:18:34.271 MAObjCRuntime[4644:a0f] TestMethodList: SUCCESS
2011-11-27 17:18:34.272 MAObjCRuntime[4644:a0f] Testing TestAddMethod
2011-11-27 17:18:34.272 MAObjCRuntime[4644:a0f] TestAddMethod: SUCCESS
2011-11-27 17:18:34.273 MAObjCRuntime[4644:a0f] Testing TestMethodFetching
2011-11-27 17:18:34.275 MAObjCRuntime[4644:a0f] TestMethodFetching: SUCCESS
2011-11-27 17:18:34.275 MAObjCRuntime[4644:a0f] Testing TestSetMethod
2011-11-27 17:18:34.278 MAObjCRuntime[4644:a0f] TestSetMethod: SUCCESS
2011-11-27 17:18:34.279 MAObjCRuntime[4644:a0f] Testing TestProtocolQuery
2011-11-27 17:18:34.280 MAObjCRuntime[4644:a0f] TestProtocolQuery:189: assertion failed: [[protocol incorporatedProtocols] containsObject: [RTProtocol protocolWithObjCProtocol: NSProtocolFromString(@"NSObject")]]
2011-11-27 17:18:34.280 MAObjCRuntime[4644:a0f] TestProtocolQuery: FAILED
2011-11-27 17:18:34.281 MAObjCRuntime[4644:a0f] Testing TestIvarQuery
2011-11-27 17:18:34.282 MAObjCRuntime[4644:a0f] TestIvarQuery: SUCCESS
2011-11-27 17:18:34.286 MAObjCRuntime[4644:a0f] Testing TestPropertyQuery
2011-11-27 17:18:34.289 MAObjCRuntime[4644:a0f] TestPropertyQuery: SUCCESS
2011-11-27 17:18:34.290 MAObjCRuntime[4644:a0f] Testing TestIvarAdd
2011-11-27 17:18:34.291 MAObjCRuntime[4644:a0f] TestIvarAdd: SUCCESS
2011-11-27 17:18:34.292 MAObjCRuntime[4644:a0f] Testing TestEquality
2011-11-27 17:18:34.292 MAObjCRuntime[4644:a0f] TestEquality: SUCCESS
2011-11-27 17:18:34.293 MAObjCRuntime[4644:a0f] Testing TestMessageSending
2011-11-27 17:18:34.293 MAObjCRuntime[4644:a0f] TestMessageSending: SUCCESS
2011-11-27 17:18:34.294 MAObjCRuntime[4644:a0f] Testing TestMessageSendingNSObjectCategory
2011-11-27 17:18:34.297 MAObjCRuntime[4644:a0f] TestMessageSendingNSObjectCategory: SUCCESS
2011-11-27 17:18:34.298 MAObjCRuntime[4644:a0f] Tests complete: FAILED: 1 total assertion failure

The Xcode project in my fork make it easy to repro: just switch to the i386 executable.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.