Vee
Vee

Reputation: 1841

Swift 3 - superclass method is executing instead of its override counterpart

How can I override the ObjC methods, runThisMethod and controller:didChangeObject:, from the ViewControllerA class so that the app executes the counterparts from the Swift subclass, ViewControllerC, instead? In the code below, [ViewControllerA runThisMethod(someParameter)] will execute when the app detects a change in fetchedResultsController (via [ViewControllerA controller:didChangeObject:]. Can somebody help me see what I'm missing?

Main.swift

let vc = ViewControllerC.init()
self.myNavigationController?.pushViewController(vc, animated: true)

ViewControllerA.h

@interface ViewControllerA : UIViewController <NSFetchedResultsControllerDelegate>
    @property (nonatomic, strong) NSFetchedResultsController *fetchedResultsController;
    - (void)setUpFetchedResultsController;
    - (void)runThisMethod:(SomeParameterClass *)someParameter;
@end

ViewControllerA.m

@implementation ViewControllerA
    - (void)setUpFetchedResultsController
    {
        // build fetch "request" here
        self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:[[MYCoreDataManager sharedCoreDataManager] managedObjectContext] sectionNameKeyPath:nil cacheName:nil];
        self.fetchedResultsController.delegate = self;
    }

    - (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)someParameter atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
    {
        [self runThisMethod:someParameter]
    }

    - (void)runThisMethod:(SomeParameterClass *)someParameter
    {
        NSLog(@"This method will execute")
    }
@end

ViewControllerB.h

@interface ViewControllerB : ViewControllerA
    // declare a bunch of properties
@end

ViewControllerB.m

@implementation ViewControllerB

    - (void)viewWillAppear:(BOOL)animated {
        [self setUpFetchedResultsController];
    }

@end

ViewControllerC.swift

class ViewControllerC: ViewControllerB {

    override func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange someParameter: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
        // this function won't run
        self.runThisMethod(someParameter)
    }

    override func runThisMethod(someParameter){
        // this function won't run
    }
}

Upvotes: 1

Views: 93

Answers (2)

Vee
Vee

Reputation: 1841

Turns out the problem was in the predicate of my fetchedResultsController property. The predicate had a parameter that will causing fetchResultsController to always be nil when performing the fetch. Thus, the delegate method, controller:didChangeObject: was not being triggered.

Upvotes: 0

Fahim
Fahim

Reputation: 3556

When I set up a sample project with the code as you've mentioned (and set up a bridging header file which imports in ViewControllerB.h) the overridden runThisMethod on ViewControllerC executes correctly. This is with Xcode 8.2.1. So everything appears to work as it should with the set up you mention.

Could you perhaps upload a sample project showing the behaviour that you mention so that we can take a look? My suspicion is that something is not set up correctly somewhere ...

One thing you might not be doing (since you've only provided part of the code) is overriding NSFetchedResultsController's didChangeObject delegate method in ViewControllerC.

Upvotes: 1

Related Questions