Is calling a method on super supported in the implementation of an Objective-C block?
When I was calling a method on super an EXC_BAD_ACCESS error would be thrown but as soon as I changed those calls from [super methodToCall]
to [self methodToCall]
and let the message move up the responder chain it worked fine.
There is no implementation of -methodToCall
in the instance of the class that the block exists in, but there is one in the superclass (that is, the class that self inherits from).
I'm just curious to learn the details as to why calling a method on super inside the implementation of a block was a problem in the first place (technically) so I can avoid it in the future. I have a suspicion it is related to how the variables are captured in the block and something about the stack and the heap, but I really have no concrete idea.
Note: the block implementation code is called up to a few seconds after the block is stored in a property, the property uses copy so I don't think it's a problem with the block's lifecycle, that all looks to be fine. Also, this was only crashing on the iPhone device (3G) but was working without crashing in the iPhone Simulator.
Results in EXC_BAD_ACCESS
:
[self retrieveItemsForId:idString completionHandler:^(NSError *error) {
if (!error) {
[super didRetrieveItems];
} else {
[super errorRetrievingItems];
}
}];
Works perfect, implementations of -didRetrieveItems
and -errorRetrievingItems
are in the super-class.
[self retrieveItemsForId:idString completionHandler:^(NSError *error) {
if (!error) {
[self didRetrieveItems];
} else {
[self errorRetrievingItems];
}
}];
Super is self , but when used in a message expression, it means "look for an implementation starting with the superclass's method table."
The __block Storage Type __block variables live in storage that is shared between the lexical scope of the variable and all blocks and block copies declared or created within the variable's lexical scope.
Closures are self-contained blocks of functionality that can be passed around and used in your code. Closures in Swift are similar to blocks in C and Objective-C and to lambdas in other programming languages.
In keeping with its clean and simple design, Objective C does not support multiple inheritance, though features have been developed to replace some of the functionality provided by multiple inheritance (see run-time section below). The root of the Objective C class hierarchy is the Object class.
Technically, this is an issue with the Objective-C runtime, and the underlying mechanics of how calls to super
actually work. Basically, they capture both the object which is the recipient of the message (self
in all cases) and the class which implements the specific version of the method (the superclass of the class in which the method implementation occurs). Because a lot of the preparation for such a message send happens at compile-time, not runtime, I wouldn't be surprised if it interacted badly with blocks.
I would check to see if self
is still valid when the message is about to be sent. Normally, any objects referenced in a block are automatically retained. Since super
works a bit differently, it might mean that self
is not getting retained like one would expect. One easy way to check this would be to use the calls to super
as originally written, and simply leak the object referred to as self
, and see if it works. If this turns out to be the problem, you might have to insert a dummy reference to self
within the block to get that automatic memory management.
In the strictest sense, however, I'm not sure you can depend on this working forever and always. Although blocks can capture the current runtime state, it doesn't really make sense (from an OOP perspective) for them to break encapsulation and invoke superclass implementations, since the hierarchical level at which methods are implemented should be opaque to any external calling code. I would try to find another solution which doesn't depend on the inheritance hierarchy.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With