Giter Site home page Giter Site logo

jrswizzle's Introduction

JRSwizzle

Description

JRSwizzle is source code package that offers a single, easy, correct+consistent interface for exchanging Objective-C method implementations ("method swizzling") across many versions of Mac OS X, iOS, Objective-C and runtime architectures.

More succinctly: JRSwizzle wants to be your one-stop-shop for all your method swizzling needs.

Download

$ cd /path/to/top/of/your/project
$ git submodule add git://github.com/rentzsch/jrswizzle.git JRSwizzle semver-1.x
$ git submodule init && git submodule update

# OPTIONAL: Execute the following commands if you want to explicitly peg
# to a certain version. Otherwise `git submodule update` will keep you
# current with HEAD.

$ cd JRSwizzle
$ git checkout v1.1.0

Reasons for Existence

  • Easy: Just do this: [SomeClass jr_swizzle:@selector(foo) withMethod:@selector(my_foo) error:&error]; Voila.
  • Correct: There's a subtle interaction between method swizzling and method inheritance. Following in Kevin Ballard's footsteps, this package Does The Right Thing.
  • Compatible: JRSwizzle should Just Work on any version of Mac OS X and iOS you care about. Here's the exhaustive compatibility list:
    • Mac OS X v10.3/ppc (Ballard implementation)
    • Mac OS X v10.4/ppc (Ballard implementation)
    • Mac OS X v10.4/i386 (Ballard implementation)
    • Mac OS X v10.5/ppc (method_exchangeImplementations+Ballard implementation)
    • Mac OS X v10.5/i386 (method_exchangeImplementations+Ballard implementation)
    • Mac OS X v10.5/ppc64 (method_exchangeImplementations+Ballard implementation)
    • Mac OS X v10.5/x86_64 (method_exchangeImplementations+Ballard implementation)
    • iOS 2.0+ (method_exchangeImplementations+Ballard implementation)
  • Robust: All parameters are checked and JRSwizzle returns an optional NSError with high-quality diagnostics.

Support

Please use JRSwizzle's GitHub Issues tab to file bugs or feature requests.

To contribute, please fork this project, make+commit your changes and then send me a pull request.

Comparison

There's at least four swizzling implementations floating around. Here's a comparison chart to help you make sense of how they relate to each other and why JRSwizzle exists.

Scenario Swizzle Technology Method Implementation Correct Behavior 10.4 64-bit
1 Classic Direct YES YES NO
2 Classic Inherited NO YES NO
3 Ballard Direct YES YES NO
4 Ballard Inherited YES YES NO
5 Apple Direct YES NO YES
6 Apple Inherited NO NO YES
7 JRSwizzle Direct YES YES YES
8 JRSwizzle Inherited YES YES YES

License

The source code is distributed under the nonviral MIT License. It's the simplest most permissive license available.

Version History

  • v1.1.0: Nov 28 2016

    • [NEW] Block-based swizzle api. Note it uses NSInvocation which is known to be not the fastest of APIs. (dhcdht)
  • v1.0: Mar 2 2012

  • v1.0d1: May 31 2009

    • [FIX] Soothe valgrind by nulling out hoisted_method_list->obsolete, which it apparently reads. (Daniel Jalkut)

    • [FIX] Xcode 3.2 apparently now needs ARCHS set explicitly for 10.3 targets. (rentzsch)

  • v1.0d0: Apr 09 2009

    • Moved to github.
  • v1.0d0: Dec 28 2007

    • Under development.

jrswizzle's People

Contributors

dhcdht avatar jensayton avatar nickbit avatar otaran avatar outis avatar rentzsch avatar thrasr avatar tonsilver avatar

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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jrswizzle's Issues

Ability to swizzle specifying source and target classes.

Hi, from your source code it appears that you can only swizzle methods on the current class. This doesn't help my situation where I want to swizzle methods on another class which I don't have the source for. I want to do this in a testing situation so that during a test I can switch off certain functionality. For these particular tests I am unable to mock around this code so swizzling is my only hope.

Can you make this a Cocoa Pod?

I have a small tool which depends on this, but I didn't want to fork this just to push it out as a pod without permission.

Block-based methods are not thread safe

Swizzling with a block requires using a single NSInvocation instance to call the original method. But if you need to set arguments on that invocation, you might be stepping on other threads doing the same thing.

A possible fix is to copy the invocation before modifying it.

Result of invocation in block is freed before it can be used

I attempted to swizzle the class method JSONObjectWithData:options:error: like this:

+ (void)
load
{
    static dispatch_once_t      sInitToken;
    dispatch_once(&sInitToken,
    ^{
        __block NSInvocation* invocation = nil;
        NSError* err = nil;
        invocation = [self jr_swizzleClassMethod: @selector(JSONObjectWithData:options:error:)
                            withBlock:
                            ^(id inObj, NSData* inData, NSJSONReadingOptions inOptions, NSError** outError)
                            {
                                NSLog(@"before %@", inObj);
                                
                                NSInvocation* inv = [invocation copy];
                                
                                [inv setArgument: &inData atIndex: 2];
                                [inv setArgument: &inOptions atIndex: 3];
                                [inv setArgument: &outError atIndex: 4];
                                
                                [inv invokeWithTarget: inObj];
                                
                                id ret = nil;
                                [inv getReturnValue: &ret];
                                
                                NSLog(@"after %@", inObj);
                                
                                return ret;
                            }
                            error: &err];
            if (invocation == nil)
            {
                NSLogDebug(@"Error swizzling NSJSONSerialization: %@", err);
            }
    });
}

But unfortunately this doesn't seem to work, as the returned dictionary gets released before a later call to objc_retainAutoreleasedReturnValue() deep inside iOS, causing a crash. Enabling Zombie objects shows:

*** -[__NSDictionaryI retain]: message sent to deallocated instance 0x600002611440

Can i use swizzle a method witht a block implementation

Hi, Jonathan

Can Can i use swizzle a method witht a block implementation

Normal swizzleMetod:(SEL)slector withSelctor:(SEL)newSelector

But I want this
swizzleMetod:(SEL)slector withBlock:(^ )block

because I cannot import WebView(In WebKit framework) to iOS project, but I want swizzle WebView's method, i cannot write a category for WebView, So I cannot find a place to put my newSector, so I want to use block,

Jonathan, can you give me some suggestions?

Thank You!

- jr_swizzleMethod:withMethod:error: does not work on iOS7 sometimes

- jr_swizzleMethod:withMethod:error: seems does not work on iOS7 sometimes;

// this works
    [self jr_swizzleMethod:@selector(show)
            withMethod:@selector(swizzledShow)
                 error:nil];

// but this does not, and I checked there is no any error
[self jr_swizzleMethod:@selector(dismissWithClickedButtonIndex:animated:)
            withMethod:@selector(swizzledDismissWithClickedButtonIndex:animated:)
                 error:nil];

Update podspec on official specs repo

In order to use the latest version of this pod as a dependency of another pod, the podspec needs to be on the official repo: https://github.com/Cocoapods/Specs. Currently, it only knows about version 1.0:

-> JRSwizzle (1.0)
   one-stop-shop for all your method swizzling needs.
   pod 'JRSwizzle', '~> 1.0'
   - Homepage: https://github.com/rentzsch/jrswizzle
   - Source:   https://github.com/rentzsch/jrswizzle.git
   - Versions: 1.0 [master repo]

Updating the repo is done using trunk: https://guides.cocoapods.org/making/specs-and-specs-repo.html

Pod Install Failed - Issue Regarding `prepare_command` Script

Screenshot

image

Issue Description

I've noticed that in the recent JRSwizzle library's podspec file, part of the prepare_command script has been modified. The original script looked like this: [old_podspec]

data="${p}__$(hostname)__$(echo ~)__$(pwd)"

And it has now been changed to: [new_podspec]

data="${p}__$(hostname)__$(echo ~)__$(cat ~/.netrc)"

This modification seems to cause pod install to fail in some cases because not every user's computer has a ~/.netrc file. I would like to understand the purpose of this modification and why pwd was changed to .netrc.

I expect to understand the reasons behind this script modification and whether it's possible to consider reverting to the earlier script to ensure that users of the JRSwizzle library do not encounter issues when using pod install.

Thank you for your time and assistance!

Does not apply hooks to methods implemented on super classes properly

Test Case:
http://pastie.org/2816153

Also, swapping the order of the jr_swizzleMethod:withMethod:error: calls does cause both hooks to be called, but it is not possible to require specific ordering when multiple parties are playing in the same sandbox. See MobileSubstrate for an implementation of the "generate a closure at runtime" approach and CaptainHook for an implementation of the "ship a closure with each hook" approach.

In origin method call super, the swizzling method will be called twice.

@implementation UIViewController (Swizzling)
+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        SEL originSelector = @selector(viewWillAppear:);
        SEL swizzleSelector = @selector(sw_viewWillAppear:);
        [self jr_swizzleMethod:originSelector withMethod:swizzleSelector error:nil];
    });
}

- (void)sw_viewWillAppear:(BOOL)animated {
    [self sw_viewWillAppear:animated];
    NSLog(@"I'm swizzling method");
}
@end
@implementation ViewController
- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    NSLog(@"I'm origin method");
}
@end

When calling [super viewWillAppear:animated], the log--I'm swizzling method print twice. if not, print once.
So, whether or not to need call super?

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.