简体   繁体   中英

best way to message a different object in objective-c

I have a UITableView and inside each header, I have a gesture recognizer. Inside the gesture handler, I want to make changes to something inside the headerview.

-(void) sectionHeaderButtonPressed: (UIButton *)sender{
    NSLog(@"Header Button pressed");
    //UIView *mySubView = [sender.view.subviews objectAtIndex:0];
    NSLog(@"Class: %@",[self class]);
    int count = [self.view.subviews count];
    NSLog(@"Self.view.subviews: %u",count);
    Class buttonClass = NSClassFromString(@"UIButton");
    for (int i=0; i < count; i++){
        int subViewCount = [[self.view.subviews objectAtIndex:i] subviews].count;
        Class className = [[self.view.subviews objectAtIndex:i] class];
        NSLog(@"SubView (%u) Class:%@ SubViews: %u",i,className,subViewCount);
        for (int j=0; j < subViewCount; j++){
            Class className01 = [[[self.view.subviews objectAtIndex:i].subviews objectAtIndex:j ] class];
            NSLog(@"----SubSubView (%u) Class:%@",j,[[[self.view.subviews objectAtIndex:i].subviews objectAtIndex:j ] class]);
            NSLog(@"Comparing Class: %@ to Class: %@",className01, buttonClass);
            if (className01 == buttonClass){
                [[[self.view.subviews objectAtIndex:i].subviews objectAtIndex:j ] setTitle:@"ABCDE" forState:UIControlStateNormal];
                NSLog(@"found button class");
            }
        }
    }
}

The above code is the gesture handler and I can find the button and every other subview, but this is a real hassle.

I seem to be confused about how one object can call another object. I wanted to pass the headerview down to the gesture handler but can't figure out how to do that.

How can I directly send or access the headerview and/or it's subviews. Looking at the class name won't do much good if I have several of the same class type.

The question is about the proper way to invoke an action in another object. Running thru all the subviews doesn't seem to be the proper way. Basing the id on the class name is an error prone way to go as you might have many of the same class.

I want to have a "slide in from the side" selection menu and have that modify the header based on what the user selects from the menu. They'll tap on the header, that'll call the gesture handler, that'll call the slide out menu, the slide out menu will call the header to make it change it's contents.

It's the last part that's confusing, how do I get the menu to change the header view contents when they're completely different objects.

The best approach for this would be to use a delegate, and let your ViewController do te heavy lifting for you. Some examples on how to create a delegate can be found here .


Create a custom view with a custom delegate protocol

The first thing you would need to do is create a subclass of the HeaderView you want to implement. As you already said yourself, your code is becoming kind of a hassle, and this would be a good opportunity to create a custom view.

In this custom view, recreate your header as you want, and hook up some labels/buttons either using interface builder, or programmatically (remember to change all weak pointers for UI elements to strong if you do this programmatically, I assumed you will use interface builder)

Your .h should look something like this:

#import <UIKit/UIKit.h>

@protocol CustomHeaderViewDelegate;

@interface CustomHeaderView : UIView

@property (nonatomic, weak) UILabel *someLabel;
@property (nonatomic, weak) UILabel *someButton;

@property (nonatomic, weak) id<CustomHeaderViewDelegate> delegate;

@end

@protocol CustomHeaderViewDelegate <NSObject>

- (void)customHeaderView:(CustomHeaderView *)customheaderView receivedTouchOnButton:(UIButton *)button;

@end

and your .m file:

#import "CustomHeaderView.h"

@implementation CustomHeaderView

- (IBAction)buttonPressed:(id)sender {
    if (self.delegate) {
        [self.delegate customHeaderView:self receivedTouchOnButton:sender];
    }
}

@end

Make the viewcontroller conform to the delegate protocol

In your view controller you want to implement the delegate protocol from your newly created CustomHeaderView. Start by making sure your viewController actually conforms to the newly created protocol by adding <CustomHeaderViewDelegate> to the interface declaration in your viewcontroller's .m file. It should look something like:

...
#import "CustomHeaderView.h"

@interface YOURVIEWCONTROLLER () <CustomHeaderViewDelegate>
...

Now somewhere in your viewController you can add the following method:

- (void)customHeaderView:(CustomHeaderView *)customheaderView receivedTouchOnButton:(UIButton *)button {
    [button setTitle:@"ABCDE" forState:UIControlStateNormal];
}

Adding your header to the tableView

In your viewForHeaderInSection code do something like:

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    CustomHeaderView headerView = [[CustomHeaderView alloc] init];
    headerView.delegate = self;
    /* do some more customisation */

    return headerView;
}

Finding your button

If you want to find your button, or some other view in a section header, you can simply do the following:

CustomHeaderView *customHeaderView = (CustomHeaderView *)[self tableView:YOURTABLEVIEW viewForHeaderInSection:SOMESECTION];
customHeaderView.button;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM