views:

102

answers:

5

We're working on a project using some custom views. We have the following hierarchy:

UIViewController -> UIScrollView (custom subclass) -> UIView (custom subclass)

We are presenting a grid of buttons that are dynamically generated. When a user taps one of the UIViews that belong to the custom scroll view we fire a method that looks like this:

- (void)handleTapFrom:(UITapGestureRecognizer *)recognizer {
    [[self superview] itemSelected:self];
}

The super view in this case is our custom subclass of UIScrollView. From here we fire another method:

- (void) itemSelected: (id)selectedItem {
    itemView *item = selectedItem;
    [[self superview] initSliderViewForItemNamed:item.name];
    item = nil;
}

Now here is where things break. We want to fire another method in UIViewController to load a new view at the top of our view hierarchy. So in UIViewController we have this method to test for success:

- (void) initSliderViewForItemNamed:(NSString *)selectedItemName {
    NSLog(@"Selected item was found! %@",selectedItemName);
}

But we never reach this point and the app crashes. It's because we can't reference the UIViewController here. Instead we're referencing the view property of the UIViewController. So our actual object hierarchy is:

UIViewController.view -> UIScrollView (custom subclass) -> UIView (custom subclass)

This leads me to two questions.

  1. How do we reference the UIViewController from our subview that belongs to the controller's view property?
  2. Is this method convoluted. Is there a better way to do this? Should we be assigning the the UIViewController as a delegate of our custom subclass of UIScrollView?
A: 

Having trouble understanding exactly what you want to achieve - can you please describe the end goal? - this method does sound quite over-complicated and convoluted. I think I have a solution but don't know if it is related :P

Michael O'Brien
This set of views allows the user to open up a project. We want to instantiate a project view for the selected object at the top of the view hierarchy. When the user closes a project they return to this view.
Jim Jeffers
Will assume our skype convo fixed it :D
Michael O'Brien
A: 

Jim you should setup a delegate on your custom uiview subclass and let you view controller be it's delegate and conform to the protocol you just created and you will be fine (ie: what a tableview is doing)

Anthony Mittaz
A: 

Hey Jim,

Yeh either using a delegate or you implement:-

  • (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

or

  • (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event

depending on how you want to handle the touch.

A: 

What I ended up doing to solve this was assign the View Controller as the delegate of the scroll view. It looks like this:

    itemScrollView = [[ItemScrollView alloc] initWithFrame:CGRectMake(...)];
    [itemScrollView setDelegate:self];      
    [self.view addSubview: itemScrollView];

Then in my ItemScrollView Implementation I could refer to the ViewController with:

    [[self delegate] initSliderViewForItemNamed:selectedItem.name];

Big thanks to everyone who replied. So setting the View Controller as the delegate was the correct answer, however, no one went into detail well enough as to how to do this. So I've covered that here in this response. Additional information can also be found on this question involving delegates:

http://stackoverflow.com/questions/626898/how-do-i-create-delegates-in-objective-c

Jim Jeffers
A: 

The idiomatic way to do what you want would be to send the message up the responder chain. UIViewController takes part in the responder chain, so it will receive the message.

Chuck