From 3d1cad32fed1f90cf9e0e012f24cadcb77b4c5ff 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)); }); }