respondsToSelector:不为委托工作

时间:2013-04-26 21:54:20

标签: ios objective-c ios5 respondstoselector

我是iOS世界的新手,在尝试将值从TableView传递回家庭控制器时遇到了问题。

我正在处理的方案是

  1. Home Controller有一个按钮
  2. 单击按钮可打开第二个UIViewController
  3. 中的项目列表
  4. 用户从列表中选择一个项目
  5. 所选项目已添加到Home Controller
  6. 上的另一个列表中

    真的很感激这个问题的任何指针:

    这就是我为Segue on Home做准备的方法

    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
        UIViewController *destination = segue.destinationViewController;
        if ([destination respondsToSelector:@selector(setDelegate:)]) { 
            [destination setValue:self forKey:@"delegate"];
        }
    
    }
    

    SecondController有一个委托id,所以我假设委托设置为“respondsToSelector”为“setDelegate”返回true

    现在,在SecondController中,当用户选择一个项目时,我会调用didSelectRowAtIndexPath& viewWillDisappear方法设置项目并使视图消失:

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
        POSAllItemsCell *cell = (POSAllItemsCell *) [tableView cellForRowAtIndexPath:indexPath];
    
        item = [NSDictionary dictionaryWithObjectsAndKeys:cell.name, @"Name", cell.price, @"Price", cell.code, @"Code", nil];
    
        [self dismissViewControllerAnimated:YES completion:NULL];
    
    }
    
    - (void)viewWillDisappear:(BOOL)animated { 
        [super viewWillDisappear:animated]; 
    
        if ([delegate respondsToSelector:@selector(setSelection:)]) {
            [delegate setValue:item forKey:@"selection"];
        }
    }
    

    现在问题是respondsToSelector setSelection返回false,即使我在HomeController中有setSelection方法:

    - (void) setSelection:(NSDictionary *)dict {
        if (![dict isEqual:selection]) {
            ......
        }
    }
    

    如果我的问题不清楚或格式不正确,请提前道歉。 BTW这适用于带有Xcode 4.2的iOS 5

2 个答案:

答案 0 :(得分:10)

要使代表团工作,您需要将其设置为:

FirstViewController.h头文件中,确保声明第二个视图控制器符合委托视图控制器的协议:

@interface FirstViewController : UIViewController <SecondViewControllerDelegate>

您可以看到委托位于视图控制器的头文件中的< >符号内。如果该协议中有必要的委托方法,如果您没有在实现文件中定义它们,Xcode将显示警告。

然后您在FirstViewController.m文件中定义了委托方法:

- (void)setSelection:(NSDictionary *)dict {
    if (![dict isEqual:selection]) {
        ......
    }
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"someSequeIdentifierHere"]) {
        SecondViewController *sv = segue.destinationViewController;
        sv.delegate = self;
    }
}

您会注意到,不应在UIViewController方法中使用prepareForSegue,而应将其强制转换为实际的视图控制器,以便在其上设置属性。这样,您不必测试视图控制器是否响应,因为它定义了delegate属性或者没有定义(在这种情况下,您需要添加一个)。

要设置原始委托协议,通常在SecondViewController.h文件中使用以下格式:

@protocol SecondViewControllerDelegate <NSObject>
- (void)setSelection:(NSDictionary *)dict;
@optional
- (void)someOptionalDelegateMethodHere;
@end

@interface SecondViewController : UIViewController

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

@end

代表几乎总是对ARC进行微弱定义。

然后,当您想要通知SecondViewController.m

中的代理人时
- (void)viewWillDisappear:(BOOL)animated { 
    [super viewWillDisappear:animated]; 

    if ([self.delegate respondsToSelector:@selector(setSelection:)]) {
        [self.delegate setSelection:item];
    }
}

由于{。1}被定义为.h文件中的公共属性,因此您可以将其引用为delegateself.delegate,但将其引用为_delegate让我思考你错误地将它定义为私有实例变量。

关于此类型的模式无法响应delegate的唯一情况是,当您未正确地将respondsToSelector:分配给delegate

希望这有帮助!

答案 1 :(得分:0)

试试这个:

if ([destination respondsToSelector:@selector(setDelegate:)]) { 
    [destination performSelector:@selector(setDelegate:) withObject:self];
}