From 467f1ac6cfa9a4de3ea5d1ddc72056d8d7fbed67 Mon Sep 17 00:00:00 2001 From: Saagar Jha Date: Wed, 11 Oct 2023 23:30:57 -0700 Subject: [PATCH] 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 --- ...llectionViewLayout+InteractiveReordering.m | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/Source/IGListKit/Internal/UICollectionViewLayout+InteractiveReordering.m b/Source/IGListKit/Internal/UICollectionViewLayout+InteractiveReordering.m index 4c950b099..4ec61c526 100644 --- a/Source/IGListKit/Internal/UICollectionViewLayout+InteractiveReordering.m +++ b/Source/IGListKit/Internal/UICollectionViewLayout+InteractiveReordering.m @@ -24,10 +24,13 @@ + (void)load // 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 @@ + (void)load @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 @@ + (void)load @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)); }); }