简体   繁体   English

向UITableView委托添加新方法

[英]Add new method to UITableView delegate

I'm trying to subclass a TableView, and a method isn't getting called. 我正在尝试对TableView进行子类化,并且未调用任何方法。

in the TouchTableView.h I have 在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

and in the TouchTableView.m I have the method 在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];
    }

}

It appears that the self.delegate doesn't respond to the selector. 看来self.delegate没有响应选择器。 It skips over and doesn't go to the method. 它跳过并且不转到该方法。 What am I doing wrong? 我究竟做错了什么?

Is the TableView delegate being assigned to self ? TableView委托是否已分配给self By default it is nil so won't respond to the selector. 默认情况下为nil,因此不会响应选择器。

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

    self.delegate = self;
    return self;
}

I think you should be using: 我认为您应该使用:

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

Your updated delegate is a property in the table view and not the view controller. 您更新的委托是表视图中的属性,而不是视图控制器中的属性。

You have also redeclared the delegate property in your subclass which could be an issue as the table view already has a property called delegate. 您还已经在子类中重新声明了delegate属性,这可能是一个问题,因为表视图已经具有一个称为委托的属性。 Perhaps you should call make yours separate and call yours: myDelegate ? 也许您应该将您的电话分开,然后打电话给您: myDelegate

It's impossible to add new method to UITableViewDelegate , because you don't have authorization to modify the UIKit . 无法向UITableViewDelegate添加新方法,因为您无权修改UIKit However it's possible to intercept the delegate because it's all about messages passing in Objective-C. 但是,可以截取委托,因为这与在Objective-C中传递的消息有关。 The first thing I would like to tell you is to declare your own delegate as weak reference instead of assign . 我想告诉你的第一件事是将自己的委托声明为weak引用,而不是assign

Whats the difference between 'weak' and 'assign' in delegate property declaration 委托属性声明中的“弱”和“分配”之间有什么区别

Now I'm going to tell you how to intercept the delegate and make it look like no difference from the UITableViewDelegate . 现在,我将告诉您如何截取委托并使它与UITableViewDelegate毫无区别。

1) Declare the delegate with your custom protocol in the header file. 1)在头文件中用您的自定义协议声明委托。

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

2) Add the following methods to create an object which will be used in intercepting the 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) Add a global object for it 3)为其添加一个全局对象

MessageInterceptor *delegate_interceptor;

4) Initialize the interceptor 4)初始化拦截器

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

5) Override the setter and getter for delegate 5)覆盖代表的设置者和获取者

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

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

6) Override the delegate you want 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];
    }
}

The last step, Don't forget to adopt the protocol at the file you create the tableview. 最后一步,不要忘记在创建tableview的文件中采用协议。

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

I added this to my viewDidLoad. 我将此添加到我的viewDidLoad中。 Just had to set the delegate to self. 只需将代表设置为自我即可。 Now it responds to the selector. 现在它响应选择器。

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

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

self.touchTableView.myDelegate = self;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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