向UITableView委托添加新方法

时间:2015-03-03 01:33:09

标签: ios objective-c uitableview

我试图将TableView子类化,并且不会调用方法。

在TouchTableView.h中我有

#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#import "SimpleTableCell.h"



@protocol myTableViewDelegate;

@interface TouchTableView : UITableView <UITableViewDelegate, UITableViewDataSource, AVAudioRecorderDelegate, AVAudioPlayerDelegate, UITextViewDelegate, UITextFieldDelegate, UIAlertViewDelegate>

@property (nonatomic, assign) id<myTableViewDelegate> myDelegate;
@property (strong, nonatomic) NSMutableArray *sortedFiles;
@property (strong, nonatomic) NSString *simpleTableIdentifier;
@property (strong, nonatomic) SimpleTableCell *cell;
@property BOOL inverted;

-(void)refreshTable;

@end


@protocol myTableViewDelegate <NSObject>

- (void)selectedFile:(TouchTableView *)tableView withURL: (NSURL *) tableViewURL IndexPath:(NSIndexPath *)indexPath;
-(void)didDelete:(TouchTableView *)tableView IndexPath:(NSIndexPath *)indexPath;
-(void)setSortedFile:(TouchTableView *)tableView;

@end

在TouchTableView.m中我有方法

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {


        NSArray *folders = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentsFolder = [folders objectAtIndex:0];
        NSString *dataPath = [documentsFolder stringByAppendingPathComponent:@"/Audio"];
        NSString *fileName = [NSString stringWithFormat:@"%@/%@",dataPath,[[sortedFiles objectAtIndex:indexPath.row] objectForKey: @"path"]];

        NSURL *tableViewUrl = [NSURL fileURLWithPath:fileName isDirectory:
               NO];


    if ([self.myDelegate respondsToSelector:@selector(selectedFile:withURL:IndexPath:)]) {
        [self.myDelegate selectedFile:self withURL:tableViewUrl IndexPath:indexPath];
    }

}

看来self.delegate没有响应选择器。它会跳过并且不会转到该方法。我做错了什么?

4 个答案:

答案 0 :(得分:0)

是否将TableView委托分配给self?默认情况下它为零,因此不会响应选择器。

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    if (!(self = [super initWithCoder:aDecoder])) {
        return self;
    }

    self.delegate = self;
    return self;
}

答案 1 :(得分:0)

我认为你应该使用:

if ([tableview.delegate respondsToSelector:@selector(selectedFile:withURL:IndexPath:)]) {
        [tableview.delegate selectedFile:self withURL:tableViewUrl IndexPath:indexPath];
    }

您更新的委托是表格视图中的属性,而不是视图控制器。

您还重新声明了子类中的delegate属性,这可能是一个问题,因为表视图已经有一个名为delegate的属性。也许你应该打电话让你的人分开并给你打电话:myDelegate

答案 2 :(得分:0)

无法向UITableViewDelegate添加新方法,因为您无权修改UIKit。但是,它可以拦截委托,因为它完全是关于在Objective-C中传递的消息。 我想告诉您的第一件事是将您自己的代理声明为weak引用,而不是assign

Whats the difference between 'weak' and 'assign' in delegate property declaration

现在,我将告诉您如何拦截代表并使其与UITableViewDelegate看起来没有区别。

1)在头文件中使用自定义协议声明委托。

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

2)添加以下方法以创建将用于拦截委托的对象。

@interface MessageInterceptor : NSObject

@property (nonatomic, assign) id receiver;
@property (nonatomic, assign) id middleMan;

@end

@implementation MessageInterceptor
@synthesize receiver;
@synthesize middleMan;

- (id)forwardingTargetForSelector:(SEL)aSelector {
    if ([middleMan respondsToSelector:aSelector]) { return middleMan; }
    if ([receiver respondsToSelector:aSelector]) { return receiver; }
    return [super forwardingTargetForSelector:aSelector];
}

- (BOOL)respondsToSelector:(SEL)aSelector {
    if ([middleMan respondsToSelector:aSelector]) { return YES; }
    if ([receiver respondsToSelector:aSelector]) { return YES; }
    return [super respondsToSelector:aSelector];
}

@end

3)为它添加一个全局对象

MessageInterceptor *delegate_interceptor;

4)初始化拦截器

delegate_interceptor = [[MessageInterceptor alloc] init];
[delegate_interceptor setMiddleMan:self];
[super setDelegate:(id)delegate_interceptor];

5)覆盖委托人的setter和getter

- (void)setDelegate:(id)newDelegate
{
    [super setDelegate:nil];
    [delegate_interceptor setReceiver:newDelegate];
    [super setDelegate:(id)delegate_interceptor];
}

- (id)delegate
{
    return delegate_interceptor.receiver;
}

6)覆盖你想要的代表

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // Call the default method again to make sure it follow the original behavior
    if ([self.delegate respondsToSelector:@selector(tableView:didSelectRowAtIndexPath:)]) {
        [self.delegate tableView:tableview didSelectRowAtIndexPath:indexPath];
    }

    NSArray *folders = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsFolder = [folders objectAtIndex:0];
    NSString *dataPath = [documentsFolder stringByAppendingPathComponent:@"/Audio"];
    NSString *fileName = [NSString stringWithFormat:@"%@/%@",dataPath,[[sortedFiles objectAtIndex:indexPath.row] objectForKey: @"path"]];

    NSURL *tableViewUrl = [NSURL fileURLWithPath:fileName isDirectory:
           NO];
    // Call the custom method which is declared in your protocol
    if ([self.delegate respondsToSelector:@selector(selectedFile:withURL:IndexPath:)]) {
        [self.delegate selectedFile:self withURL:tableViewUrl IndexPath:indexPath];
    }
}

最后一步,不要忘记在创建tableview的文件中采用协议。

@interface TheFileUsingTableView ()
<UITableViewDelegate, myTableViewDelegate>
@end

答案 3 :(得分:0)

我将此添加到我的viewDidLoad中。只需要将代表设置为自己。现在它响应选择器。

self.touchTableView = [[TouchTableView alloc] init];

[self.tableView setDelegate:self.touchTableView];
[self.tableView setDataSource:self.touchTableView];

self.touchTableView.myDelegate = self;