Replace use of method_exchangeImplementations (#1583)

Summary:
## Changes in this pull request
class_replaceMethod is significantly faster as it doesn't need to clear the entire method cache, which can be quite expensive for large apps.

NFC, but it should be faster. No new test failures.

Issue fixed: #

### Checklist

- [ ] All tests pass. Demo project builds and runs.
- [X] I added tests, an experiment, or detailed why my change isn't tested.
- [ ] I added an entry to the `CHANGELOG.md` for any breaking changes, enhancements, or bug fixes.
- [X] I have reviewed the [contributing guide](https://github.com/Instagram/IGListKit/blob/main/.github/CONTRIBUTING.md)

Pull Request resolved: https://github.com/Instagram/IGListKit/pull/1583

Reviewed By: fabiomassimo

Differential Revision: D50013222

Pulled By: TimOliver

fbshipit-source-id: 157fea52f3768b16acd09b149bd16bea4e5fdc27
This commit is contained in:
Saagar Jha 2023-10-11 23:30:57 -07:00 committed by Facebook GitHub Bot
parent a511891376
commit 3d1cad32fe

View file

@ -24,10 +24,13 @@ static void * kIGListAdapterKey = &kIGListAdapterKey;
// override implementation for targetIndexPathForInteractivelyMovingItem:withPosition:
SEL userMoveSelector = @selector(targetIndexPathForInteractivelyMovingItem:withPosition:);
SEL overrideSelector = @selector(ig_targetIndexPathForInteractivelyMovingItem:withPosition:);
Method userLayoutMethod = class_getInstanceMethod(layoutClass, userMoveSelector);
Method overrideLayoutMethod = class_getInstanceMethod(layoutClass, overrideSelector);
method_exchangeImplementations(userLayoutMethod, overrideLayoutMethod);
SEL overrideMoveSelector = @selector(ig_targetIndexPathForInteractivelyMovingItem:withPosition:);
Method userMoveMethod = class_getInstanceMethod(layoutClass, userMoveSelector);
Method overrideMoveMethod = class_getInstanceMethod(layoutClass, overrideMoveSelector);
IMP userMoveIMP = method_getImplementation(userMoveMethod);
IMP overrideMoveIMP = method_getImplementation(overrideMoveMethod);
class_replaceMethod(layoutClass, overrideMoveSelector, userMoveIMP, method_getTypeEncoding(userMoveMethod));
class_replaceMethod(layoutClass, userMoveSelector, overrideMoveIMP, method_getTypeEncoding(overrideMoveMethod));
// override implementation for
// invalidationContextForInteractivelyMovingItems:withTargetPosition:previousIndexPaths:previousPosition:
@ -37,7 +40,10 @@ static void * kIGListAdapterKey = &kIGListAdapterKey;
@selector(ig_invalidationContextForInteractivelyMovingItems:withTargetPosition:previousIndexPaths:previousPosition:);
Method userInvalidationMethod = class_getInstanceMethod(layoutClass, userInvalidationSelector);
Method overrideInvalidationMethod = class_getInstanceMethod(layoutClass, overrideInvalidationSelector);
method_exchangeImplementations(userInvalidationMethod, overrideInvalidationMethod);
IMP userInvalidationIMP = method_getImplementation(userInvalidationMethod);
IMP overrideInvalidationIMP = method_getImplementation(overrideInvalidationMethod);
class_replaceMethod(layoutClass, overrideInvalidationSelector, userInvalidationIMP, method_getTypeEncoding(userInvalidationMethod));
class_replaceMethod(layoutClass, userInvalidationSelector, overrideInvalidationIMP, method_getTypeEncoding(overrideInvalidationMethod));
// override implementation for
// invalidationContextForInteractivelyMovingItems:withTargetPosition:previousIndexPaths:previousPosition:
@ -47,7 +53,10 @@ static void * kIGListAdapterKey = &kIGListAdapterKey;
@selector(ig_invalidationContextForEndingInteractiveMovementOfItemsToFinalIndexPaths:previousIndexPaths:movementCancelled:);
Method userEndInvalidationMethod = class_getInstanceMethod(layoutClass, userEndInvalidationSelector);
Method overrideEndInvalidationMethod = class_getInstanceMethod(layoutClass, overrideEndInvalidationSelector);
method_exchangeImplementations(userEndInvalidationMethod, overrideEndInvalidationMethod);
IMP userEndInvalidationIMP = method_getImplementation(userEndInvalidationMethod);
IMP overrideEndInvalidationIMP = method_getImplementation(overrideEndInvalidationMethod);
class_replaceMethod(layoutClass, overrideEndInvalidationSelector, userEndInvalidationIMP, method_getTypeEncoding(userEndInvalidationMethod));
class_replaceMethod(layoutClass, userEndInvalidationSelector, overrideEndInvalidationIMP, method_getTypeEncoding(overrideEndInvalidationMethod));
});
}