4

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

我正在处理的场景是

  1. 家庭控制器有一个按钮
  2. 单击按钮打开第二个 UIViewController 中的项目列表
  3. 用户从列表中选择一个项目
  4. 所选项目被添加到家庭控制器上的另一个列表中

非常感谢有关此问题的任何指示:

这就是我为 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"];
    }
}

现在这里的问题是即使我的 HomeController 中有 setSelection 方法, respondsToSelectorfor也会返回 false:setSelection

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

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

4

2 回答 2

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;
    }
}

您会注意到,您应该将其转换为实际的视图控制器,而不是UIViewControllerprepareForSegue方法中使用,这样您就可以在其上设置属性。这样,您不必测试视图控制器是否响应,因为它要么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];
    }
}

由于delegate在 .h 文件中被定义为公共属性,因此您可以将其引用为self.delegate_delegate但将其引用为delegate使我认为您错误地将其定义为私有实例变量。

这种类型的模式唯一不会响应的情况respondsToSelector:是您没有正确地将其分配delegate给您的FirstViewController

希望这可以帮助!

于 2013-04-26T22:37:15.837 回答
0

试试这个:

if ([destination respondsToSelector:@selector(setDelegate:)]) { 
    [destination performSelector:@selector(setDelegate:) withObject:self];
}
于 2013-04-26T22:37:47.927 回答