Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling super in the implementation of an Objective-C block

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];
 }
}];
like image 296
Andrew Avatar asked Dec 12 '10 03:12

Andrew


People also ask

What is super in Objective C?

Super is self , but when used in a message expression, it means "look for an implementation starting with the superclass's method table."

What does __ block do in Objective C?

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.

What is Objective C blocks called in Swift?

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.

Is multiple inheritance possible in Objective C?

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.


1 Answers

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.

like image 154
Justin Spahr-Summers Avatar answered Sep 22 '22 18:09

Justin Spahr-Summers