Dead code in action block?


#1

Commenting out the line below in the bottom of the action block has no side effects.
It will work WITH and WITHOUT that line of code.

I’m using Xcode 5.1 and iOS 7.1. I tested this on a physical device as well as a simulator and everything works fine with no error.

            // Present a 600x600 popover from the rectangle
            self.imagePopover = [[UIPopoverController alloc] initWithContentViewController:ivc];
//            self.imagePopover.delegate = self;
            self.imagePopover.popoverContentSize = CGSizeMake(600, 600);
            [self.imagePopover presentPopoverFromRect:rect
                                               inView:self.view
                             permittedArrowDirections:UIPopoverArrowDirectionAny
                                             animated:YES];
        }

My guess is it works because of the responder chain ? So it just keeps popping up until a parent in the view hierarchy handles the UIPopoverControllerDelegate method.

I’m still translating Objective C to Java in my mind.

I think of a block like an ‘anonymous listener’ that is it’s own object with a ‘self’ ptr and it’s parents ‘self’ ptr. That and the issue that it lives on the stack instead of the heap.

self.imagePopover.delegate = self;

Seems odd to me. Time to go read on blocks so more.

Could somebody shed some light on this one for me?

Thanks!


#2

Don’t confuse a “Block” with “Delegation”. Delegation is a commonly used design pattern in iOS and OSX (Cocoa). A “Block” is a feature added to objective C a few years ago and it’s similar to a function pointer in C, with some marked differences.

A “Block”, as the name implies, allows you (amongst other things) to pass a block of code as an argument to a method. The receiver of the method can then choose to hang on the block of code, and run it at a later time. Now, because the method in which the block was passed as an argument might go out of scope before the block has a chance to execute, the block is copied to the heap, and the address of where it exists on the heap is passed as the argument. This allows the class that receives the address of the block, which now exists in the heap, to call the block at any time. This is one of the reasons that a block strongly captures any variables that are within its scope (unless that variable was preceded by the __block specifier). Blocks are a powerful and flexible feature that takes a bit of time (and practice) to truly understand.

“Delegation” on the other hand is more of a process or concept. When you set the “delegate” property of a class, you’re basically committing to have the class that was set as the delegate, to implement certain method(s). These “methods” depend on what protocol (bunch of declared methods) that the delegate is expected to conform to (i.e. promise to implement).

The reason you may mix up the concept of Blocks and Delegation is because both can be used as callback mechanisms.

To simplify it. A “Block” allows you to pass a set of instructions (block of code) to another class that may execute that code at a later time. Delegation allows you to pass a reference to a class (the “delegate”) that promises to implement a bunch of methods that may be called by another class. Passing the reference, allows the other class to call back and execute any agreed upon methods. These agreed upon methods may be mandatory or optional. This implies that the delegate must be around before the “delegator” can call it. That limitation does not necessarily exist with a block, as the block is copied to the heap. The class that receives the reference to the block is able to call the block, without requiring the class that passed the block to it to be around.

In your mentioned example code, commenting out the line “self.imagePopover.delegate = self;” prevents the UIPopoverController instance class, that is referenced by self.imagePopover, from having a reference or a handle to “self”, so self.imagePopover will not be able to call any of the UIPopoverControllerDelegate declared methods. In fact, many times I’ve committed the mistake of implementing a bunch of protocol/delegate methods only to find that none of those methods are being called. After examining my code I notice that I forgot to set the delegate property, so the “delegator” was unable to call “self”.

Try this, place a NSLog message in the delegate methods - (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController, while commenting out the line “self.imagePopover.delegate = self”. Run the app, trigger the popover and then dismiss it. Do the same steps, this time uncomment “self.imagePopover.delegate = self” line, and pay attention to the messages in the debugger console. You’ll notice that when you set “self” as the delegate, then “self” will receive the delegate/callback methods from the instance of UIPopoverController class.

Hope that clearer than mud :slight_smile:


#3

[quote=“mataz137”]
In your mentioned example code, commenting out the line “self.imagePopover.delegate = self;” prevents the UIPopoverController instance class, that is referenced by self.imagePopover, from having a reference or a handle to “self”, so self.imagePopover will not be able to call any of the UIPopoverControllerDelegate declared methods. In fact, many times I’ve committed the mistake of implementing a bunch of protocol/delegate methods only to find that none of those methods are being called. After examining my code I notice that I forgot to set the delegate property, so the “delegator” was unable to call “self”.
/quote]

Just to repeat my original comment. After doing a CLEAN and re-running

[quote]Commenting out the line below in the bottom of the action block has no side effects.
It will work WITH and WITHOUT that line of code.

I’m using Xcode 5.1 and iOS 7.1. I tested this on a physical device as well as a simulator and everything works fine with no error.[/quote][/quote]


#4

I was attempting to clear up your confusion that was apparent in your original post:

The three protocol methods that are declared in UIPopoverControllerDelegate are all “Optional” methods, meaning, you don’t have to implement any of them to get the popover to work. So not assigning a delegate to the popover controller will not prevent it from appearing. Your guess that “it works because of the responder chain” or “a parent in the view hierarchy handles the UIPopoverControllerDelegate method” is incorrect. UIPopoverController does not need any required info from a delegate for it to appear and function properly. So you shouldn’t be surprised that the popover is working even though you’re commenting out the line: self.imagePopover.delegate = self;

In contrast, that is not the case for a class such as UITableViewController. For that class to function properly it requires to have a data source (sorta like a delegate) that implements two required methods, defined in UITableViewDataSource Protocol.

Some classes will require to have a delegate and the implementation of those required methods before they can function properly. UIPopoverController is not one of those classes.