views:

307

answers:

2

I want to change an image on a view, from a popup dialog of 4-6 icons (imagine like changing your image on a messenger application). The way I implement this modal popup is by creating a new view at IB, with opacity on the background, and then I load this as a subview:

    IconsViewController *iconsViewController = [[IconsViewController alloc] initWithNibName:@"IconsView" bundle:nil];
[self.view addSubview:iconsViewController.view];

So, when the user touches an icon, I have

- (IBAction)iconIsSelected:(id)sender {
switch ([sender tag]) {
    case 1:
        [(ParentViewController*)[self superview] changeIcon];
        break;
    case 2:
        // same here..
        break;
    default:
        break;
}
[self.view removeFromSuperview];
[self release];

}

The changeIcon just sets the image to a corresponding icon. As you can guess, this is not working - the changeIcon message never works. I can't understand what am I doing wrong, any help much appreciated!

A: 

The superview of a view is a view, not a view controller, yet you cast the superview to be of class ParentViewController. If the view has no superview, it returns nil, and message to nil are no-ops (which explains why you don't crash there).

BTW, that [self release] at the end is highly suspicious.

Johan Kool
Thank you very much for that - I'll mark the other answer as accepted, but you helped me get an understanding of my mistakes. I know that this [self release] is not good, but I'm not sure where to release it yet - this is the next thing to check though.. Thanks again!
Irene
A: 

You have a few choices here...

First one is create a property on your IconsViewController of type ParentViewController*, for example:

@property (readwrite,nonatomic,assign) ParentViewController* parentController; // weak reference

To break this down further:

  • readwrite because we want to be able to access the value via [self parentController] but also change it via [iconsViewController setParentController:self]
  • nonatomic because I'm not too worried about threading
  • assign to make it a "weak reference" where the parent will not be retained by the child. If they each retain the other, it could lead to memory leaks later because unless explicitly released you'd end up with a retain circle causing neither object to hit a zero retain count.

When you load from nib, set the property:

IconsViewController *iconsViewController = [[IconsViewController alloc] initWithNibName:@"IconsView" bundle:nil];
iconsViewController.parentController = self;

Then, call to it from inside of iconIsSelected like this:

[[self parentController] changeIcon];

Alternatively, you can create a delegate protocol:

@protocol IconViewSelectedDelegate (NSObject)

- (void) changeIcon;

@end

And use that protocol as a property, instead of the parent view controller type. This is more abstract, but it keeps the design cleaner. The parent view controller would then implement that delegate protocol, as one of many others.

Another option is to use NSNotificationCenter and publish/subscribe to events from your dynamic view. This is the "loosest" coupling between the two objects, but it might be overkill for this scenario.

slf
Thank you for helping. I must read more on delegates and protocols. One thing I also don't get, is why you make the parentController property (readwrite, nonatomic, assign). Any quick insight?
Irene
see above, I updated the description with more info about property definitions
slf