IOS Swizzle лучше понять - PullRequest
       94

IOS Swizzle лучше понять

0 голосов
/ 07 ноября 2018

У меня есть UIViewController с этим кодом:

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    NSLog(@"CLASIC");
}

А затем у меня есть фреймворк с категорией UIViewController, который делает следующее:

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{

        SEL viewWillAppearSelector = @selector(viewDidAppear:);
        SEL viewWillAppearLoggerSelector = @selector(logged_viewDidAppear:);
        Method originalMethod = class_getInstanceMethod(self, viewWillAppearSelector);
        Method extendedMethod = class_getInstanceMethod(self, viewWillAppearLoggerSelector);
        method_exchangeImplementations(originalMethod, extendedMethod);

    });
}

- (void)logged_viewDidAppear:(BOOL)animated
{
    [self logged_viewDidAppear:animated];

    NSLog(@"SWIZZLED");
}

Выход SWIZZLED, а затем CLASIC.

Теперь мой вопрос: если в моем viewcontroller я комментирую [super viewDidAppear: animated]; тогда закрученный метод больше не вызывается; это почему? Я понял большинство аспектов, но кажется, что этот как-то ускользнул.

- (void)viewDidAppear:(BOOL)animated
{
    // we comment this and this will trigger the swizzled method not being called anymore
    //[super viewDidAppear:animated];
    NSLog(@"CLASIC");
}

// ========================

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{

        SEL viewWillAppearSelector = @selector(viewDidAppear:);
        SEL viewWillAppearLoggerSelector = @selector(logged_viewDidAppear:);
        Method originalMethod = class_getInstanceMethod(self, viewWillAppearSelector);
        Method extendedMethod = class_getInstanceMethod(self, viewWillAppearLoggerSelector);
        method_exchangeImplementations(originalMethod, extendedMethod);

    });
}

- (void)logged_viewDidAppear:(BOOL)animated
{
    [self logged_viewDidAppear:animated];

    NSLog(@"SWIZZLED");
}

1 Ответ

0 голосов
/ 07 ноября 2018

Метод Swizzling используется для переопределения оригинальных методов с пользовательскими во время выполнения. Таким образом, вы можете заменить практически любой метод (включая методы, реализованные в частном яблоке) на тот, который вы написали.

Итак, представьте, что есть класс с именем Parent с методом с именем A, и вы обмениваетесь с B где-то до того, как он был вызван, как внутри load метода. Отныне каждый подкласс off 'Parent' будет использовать B, за исключением оригинального метода "A". Но что если вы переопределите A в дочернем классе? В качестве определения наследования объекты будут вызывать свои собственные методы и, если они не реализовали его, они используют метод suprclass . Так что, если вы хотите parent implementation? Вот где super входит.

Заключение

  • Если вы переопределите метод, метод суперкласса (или метод, которым пользователь обменивается в суперклассе) не будет вызван
  • Если вам нужна родительская реализация, вы должны использовать ключевое слово super , чтобы получить к нему доступ

И в этом случае вопросы:

  • Переопределение метода в подклассе без вызова super означает, что вы просто переопределите метод swizzled, и он не будет вызван.

Надеюсь, это поможет

...