2

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?
Jim Jeffers
  • 17,572
  • 4
  • 41
  • 49

4 Answers4

0

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)

0

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.

0

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:

How do I create delegates in Objective-C?

Community
  • 1
  • 1
Jim Jeffers
  • 17,572
  • 4
  • 41
  • 49
0

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
  • 234,037
  • 30
  • 302
  • 389