UITableview / UIView代表混淆

时间:2015-05-26 17:20:30

标签: ios objective-c uitableview uiview delegates

我正在创建自己的下拉菜单,因为我无法找到一个完全符合我需要的开源软件。 我已经将下拉列表作为UIView实现,并将其添加到按钮的超级视图中,以便显示它。

代码:

ViewController.m

#import "ViewController.h"
#import "MenuView.h"

@interface ViewController () <MenuViewDelegate>
@property (weak, nonatomic) IBOutlet UIView *fakeHeader;
@property (nonatomic, strong) MenuView *menuView;
@end

@implementation ViewController

- (void)viewDidLoad { 
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (IBAction)btnTapped:(id)sender {
    NSArray *array = @[@"Item 1", @"Item 2", @"Item 3", @"Item 4"];
    NSArray *imgArray = nil;

    if (self.menuView == nil) {
        self.menuView = [[MenuView alloc] showDropDownWith:sender txtArr:array     imgArr:imgArray direction:@"down" delegate:self];

        self.menuView.delegate = self;
    } else {
        [self.menuView hideDropDown:sender];

        self.menuView = nil;
    }
}

- (void) menuDelegateMethod:(MenuView *)sender {
    self.menuView = nil;
}

@end

MenuView.h

#import <UIKit/UIKit.h>

@class MenuView;

@protocol MenuViewDelegate
- (void)menuDelegateMethod:(MenuView *)sender;
@end

@interface MenuView : UIView
@property (nonatomic, retain) id <MenuViewDelegate> delegate;

- (id)showDropDownWith:(UIButton *)button txtArr:(NSArray *)txtArr imgArr:(NSArray *)imgArr direction:(NSString *)direction delegate:(id)delegate;
- (void)hideDropDown:(UIButton *)button;
@end

MenuView.m

#import "MenuView.h"
#import "QuartzCore/QuartzCore.h"

@interface MenuView () <UITableViewDataSource, UITableViewDelegate>

@property (nonatomic, strong) UITableView *table;
@property (nonatomic, strong) UIButton *btnSender;
@property (nonatomic, retain) NSString *animationDirection;
@property (nonatomic, retain) NSArray *list;
@property (nonatomic, retain) NSArray *imageList;
@end

@implementation MenuView

- (id)showDropDownWith:(UIButton *)button txtArr:(NSArray *)txtArr imgArr:(NSArray *)imgArr direction:(NSString *)direction delegate:(id)delegate {
    CGFloat width = [UIScreen mainScreen].bounds.size.width;
    CGFloat origin = [UIScreen mainScreen].bounds.origin.x;
    CGFloat realHeight = 40 * txtArr.count;

    self.btnSender = button;
    self.animationDirection = direction;
    self.table = (UITableView *)[super init];

    if (self) {
        // Initialization code
        CGRect btn = button.frame;
        self.list = [NSArray arrayWithArray:txtArr];
        self.imageList = [NSArray arrayWithArray:imgArr];

        if ([direction isEqualToString:@"up"]) {
            self.frame = CGRectMake(origin, (btn.origin.y - btn.size.height) , width, 0);

            self.layer.shadowOffset = CGSizeMake(0, 1);
        } else if ([direction isEqualToString:@"down"]) {
            self.frame = CGRectMake(origin, (btn.origin.y + btn.size.height + 10), width, 0);

            self.layer.shadowOffset = CGSizeMake(0, 1);
        }

        self.layer.masksToBounds = YES;
        self.layer.shadowOpacity = 0.2;

        self.table = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, width, 0)];
        self.table.delegate   = delegate;
        self.table.dataSource = self;
        self.table.backgroundColor = [UIColor colorWithRed:0.239 green:0.239 blue:0.239 alpha:1];
        self.table.separatorStyle  = UITableViewCellSeparatorStyleSingleLine;
        self.table.separatorColor  = [UIColor lightGrayColor];
        self.table.backgroundColor = [UIColor whiteColor];
        self.table.userInteractionEnabled = YES;

        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationDuration:0.5];

        if ([direction isEqualToString:@"up"]) {
            self.frame = CGRectMake(origin, (btn.origin.y - realHeight), width, realHeight);
        } else if([direction isEqualToString:@"down"]) {
            self.frame = CGRectMake(origin, (btn.origin.y + btn.size.height + 10), width, realHeight);
        }

        self.table.frame = CGRectMake(0, 0, width, realHeight);
        [UIView commitAnimations];
        [button.superview addSubview:self];

        self.table.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];

        [self addSubview:self.table];
    }

    return self;
}

- (void)hideDropDown:(UIButton *)button {
    CGRect btn = button.frame;
    CGFloat width = [UIScreen mainScreen].bounds.size.width;
    CGFloat origin = [UIScreen mainScreen].bounds.origin.x;

    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:0.5];

    if ([self.animationDirection isEqualToString:@"up"]) {
        self.frame = CGRectMake(origin, btn.origin.y, width, 0);
    } else if ([self.animationDirection isEqualToString:@"down"]) {
        self.frame = CGRectMake(origin, (btn.origin.y + btn.size.height + 10),     width, 0);
    }

    self.table.frame = CGRectMake(0, 0, width, 0);

    [UIView commitAnimations];
}

#pragma mark - Table View DataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [self.list count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView     dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
        cell.textLabel.font = [UIFont systemFontOfSize:15];
        cell.textLabel.textAlignment = NSTextAlignmentLeft;
    }

    cell.textLabel.text = [self.list objectAtIndex:indexPath.row];

    cell.backgroundColor = [UIColor colorWithRed:48.0f/255.0f green:48.0f/255.0f blue:48.0f/255.0f alpha:1.0f];
    cell.textLabel.textColor = [UIColor lightTextColor];

    return cell;
}

#pragma mark - Table View Delegate

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return 40;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [self hideDropDown:self.btnSender];

    [self myDelegate];
}

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    // Remove seperator inset
    if ([cell respondsToSelector:@selector(setSeparatorInset:)]) {
        [cell setSeparatorInset:UIEdgeInsetsZero];
    }

    // Prevent the cell from inheriting the Table View's margin settings
    if ([cell respondsToSelector:@selector(setPreservesSuperviewLayoutMargins:)]) {
        [cell setPreservesSuperviewLayoutMargins:NO];
    }

    // Explictly set your cell's layout margins
    if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
        [cell setLayoutMargins:UIEdgeInsetsZero];
    }
}

#pragma mark - View Delegate
- (void)myDelegate {
    [self.delegate menuDelegateMethod:self];
}

@end

完美显示,但永远不会调用didSelect方法。

我没有任何关于窃听触摸事件的观点。

似乎UIViews可能无法成为UITableviewDelegates。如果这是真的我不知道为什么,当我将调用视图控制器作为委托时,它仍然无法选择。

注意:我通过不使用更新的方法来了解动画失礼。这是基于旧的示例代码。在我解决了这个问题之后,我将更新动画。

问题:

  1. UIViews不能是UITableView代表吗?

  2. 如果是这样,如何让一个调用视图控制器成为驻留在UIView中的表视图的委托?除了将其设置为UITableViewDelegate并在创建表时将调用视图控制器指定为委托的过程之外。

  3. 我是否错过了我设置的方法,窃取了单元格点击,以便在视图或viewController中不会调用didSelect?

  4. 感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

正如我所看到的,您正在将ViewControllerMenuViewDelegate}传递给showDropDownWith方法,然后将其用作表委托。这是不正确的。

您应该在那里传递self(与数据源相同),因为您希望MenuView成为表的委托,而不是ViewController,对吗?

self.table.delegate = self;

答案 1 :(得分:2)

同意@Piotr菜单必须是表的委托,因此在MenuView.m中将self.table.delegate = delegate;替换为self.table.delegate = self;

但另外,MenuView.m从不调用其委托,它应该在tableview中选择....

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [self hideDropDown:self.btnSender];

    // remove this, since it does nothing
    //[self myDelegate];

    // replace it with
    [self.myDelegate menuDelegateMethod:self];
}

最后一行说,告诉代表菜单发生了什么事。

另一个问题是菜单并没有真正告诉代表发生了什么。当然,代表会对选择哪个项目感兴趣。考虑将协议更改为:

@protocol MenuViewDelegate
- (void)menuView:(MenuView *)sender didSelectOptionAtIndex:(NSInteger)index;
@end
// calling it
[self.myDelegate menuView:self didSelectOptionAtIndex:indexPath.row];

另一种方法是将选定的字符串交还给委托。这可以在indexview.row的tableview的数据源中找到。

最后,由于菜单的客户可能会保留您的委托,因此不保留您的委托是一种良好做法,从而导致保留周期。相反,声明委托:

// notice "weak"
@property (nonatomic, weak) id <MenuViewDelegate> delegate;