在 ViewControllerB 到 ViewControllerA 之间传递数据,委托不会被调用

Posted

技术标签:

【中文标题】在 ViewControllerB 到 ViewControllerA 之间传递数据,委托不会被调用【英文标题】:Passing data between ViewControllerB to ViewControllerA, Delegate not get called 【发布时间】:2014-07-28 09:54:31 【问题描述】:

我尝试使用委托但没有成功,委托没有被调用。 这是我的委托代码:

设置委托(ViewControllerB)

@class SearchGardenTable;
@protocol SearchGardenDelegate <NSObject>
- (void)addItemViewController:(SearchGardenTable *)controller didFinishWithGardenID:(NSString *)gardenID gardenName:(NSString*)gardenName andCityName:(NSString*)cityName;
@end

@interface SearchGardenTable : UITableViewController

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

告诉 VC B VC A 是它的代表:

 // in VC A viewDidLoad.
self.searchGarden = [[SearchGardenTable alloc]init];
[self.searchGarden setDelegate:self];

VC A 采用协议

@interface AddKid () <MZFormSheetBackgroundWindowDelegate,SearchGardenDelegate>

@end

@implementation AddKid 

设置我想从 VC B 传回 VC A 的参数:

    _kidGaedenID  = [temp objectAtIndex:indexPath.row];
    _kidGardenName = [temp1 objectAtIndex:indexPath.row];


    [self.delegate addItemViewController:self didFinishWithGardenID:_kidGaedenID gardenName:_kidGardenName andCityName:_kidCityName];

在VC A实现协议方法:

- (void)addItemViewController:(SearchGardenTable *)controller didFinishWithGardenID:(NSString *)gardenID gardenName:(NSString*)gardenName andCityName:(NSString*)cityName

    _kidGardenID = gardenID;
    _gardenName.text = gardenName;
    _kidCity.text = cityName;


编辑

ViewController B didSelectRowAtIndexPath: code

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

        NSArray *temp = [_responseDict valueForKey:@"ID"];
        NSArray *temp1 = [_responseDict valueForKey:@"name"];

        _kidGaedenID  = [temp objectAtIndex:indexPath.row];
        _kidGardenName = [temp1 objectAtIndex:indexPath.row];



        [[self delegate] addItemViewController:self didFinishWithGardenID:_kidGaedenID gardenName:_kidGardenName andCityName:_kidCityName];

        [self mz_dismissFormSheetControllerAnimated:YES completionHandler:^(MZFormSheetController *formSheetController) 

//dismiss the popup view which i create it VC A with that gitHub package:
https://github.com/m1entus/MZFormSheetController/issues/98

        ];

编辑 2 呈现 ViewControllerB 的代码:

- (IBAction)chooseGardenAndCityBtn:(id)sender 
    UIViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"modal"];

    MZFormSheetController *formSheet = [[MZFormSheetController alloc] initWithViewController:vc];

    formSheet.presentedFormSheetSize = CGSizeMake(300, 298);
    //    formSheet.transitionStyle = MZFormSheetTransitionStyleSlideFromTop;
    formSheet.shadowRadius = 2.0;
    formSheet.shadowOpacity = 0.3;
    formSheet.shouldDismissOnBackgroundViewTap = YES;
    formSheet.shouldCenterVertically = YES;
    formSheet.movementWhenKeyboardAppears = MZFormSheetWhenKeyboardAppearsCenterVertically;
    // formSheet.keyboardMovementStyle = MZFormSheetKeyboardMovementStyleMoveToTop;
    // formSheet.keyboardMovementStyle = MZFormSheetKeyboardMovementStyleMoveToTopInset;
    // formSheet.landscapeTopInset = 50;
    // formSheet.portraitTopInset = 100;

    __weak MZFormSheetController *weakFormSheet = formSheet;


    // If you want to animate status bar use this code
    formSheet.didTapOnBackgroundViewCompletionHandler = ^(CGPoint location) 
        UINavigationController *navController = (UINavigationController *)weakFormSheet.presentedFSViewController;
        if ([navController.topViewController isKindOfClass:[SearchCityTable class]]) 
            SearchCityTable *mzvc = (SearchCityTable *)navController.topViewController;
            mzvc.showStatusBar = NO;
        


        [UIView animateWithDuration:0.3 animations:^
            if ([weakFormSheet respondsToSelector:@selector(setNeedsStatusBarAppearanceUpdate)]) 
                [weakFormSheet setNeedsStatusBarAppearanceUpdate];
            
        ];
    ;

    formSheet.willPresentCompletionHandler = ^(UIViewController *presentedFSViewController) 
        // Passing data
        UINavigationController *navController = (UINavigationController *)presentedFSViewController;
        navController.topViewController.title = @"בחר עיר";
    ;
    formSheet.transitionStyle = MZFormSheetTransitionStyleCustom;

    [MZFormSheetController sharedBackgroundWindow].formSheetBackgroundWindowDelegate = self;

    [self mz_presentFormSheetController:formSheet animated:YES completionHandler:^(MZFormSheetController *formSheetController) 

    ];




编辑

【问题讨论】:

你指定VC A采用SearchGardenDelegate协议了吗? 是的,我做了.. 看我编辑。 您从哪里向委托方法发送消息?来自您的 VC B 类中的哪个方法? 你在哪里有这个 [self.delegate addItemViewController:self didFinishWithGardenID:_kidGaedenID gardenName:_kidGardenName andCityName:_kidCityName]; didSelectRowAtIndexPath: tableview 方法 【参考方案1】:

你在做

self.searchGarden = [[SearchGardenTable alloc]init];

但是您说您在情节提要中有您的视图控制器。这让我觉得 self.searchGarden 在 vi​​ewDidLoad: 的角度是与故事板中的不同的对象。

当您准备推送您的 VC B 或执行 TheSegue 之前(如果您正在使用 segue),您应该为 self.searchGarden 分配一个对象。

编辑

根据您的代码,我假设

UIViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"modal"];

是你的VC B,所以你需要做vc.delegate = self; 请记住,您的 vc 必须是 VC B 类型,在您的情况下是 SearchGardenTable

编辑 2

鉴于当前的设置,我现在想到的最快的解决方案是 NSNotification。从您的 VC B 发送通知:

[[NSNotificationCenter defaultCenter] postNotificationName:@"userDidTapOnCell" object:nil userInfo:dictionaryOfObjects];

使用从模型中检索到的对象初始化对象字典的位置,例如:

NSDictionary *dictionary = @ @"gardenID": _kidGaedenID, @"gardenName": _kidGardenName ;

与在 VC A 中相比,您将自己作为观察者添加到 viewDidLoad 上的通知中:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(gardenInfoDidComeBack:) name:@"userDidTapOnCell" object:nil];

并实现方法:

- (void)gardenInfoDidComeBack:(NSNotification *)notification 
    NSDictionary *userInfo = notification.userInfo;
    // retrieve the kidGardenID and kidGardenName from the dict and use them as you whish.

希望这可以帮助您完成任务。您的导航架构可能不是最好的,但这已经超出了本主题的范围。

【讨论】:

我在 ViewControllerA 中有一个属性 @property (nonatomic, strong) SearchGardenTable *searchGarden; 我可以看到。但是您正在 viewDidLoad 中初始化一个新的 VC B 实例,因此它可能与您显示的不同。值得看看您编写的从 VC A 推送 VC B 的代码 仍然缺少从 VC A 推送 VC B 的代码 再次编辑,现在所有代码都用于显示 VC B 弹出窗口。 @OshriALM 查看我的编辑 2。【参考方案2】:

请出示您的 VC B 初始化。

在调用此行之前确保 self.searchGarden 已初始化

self.searchGarden.delegate = self; // in VC A viewDidLoad.

【讨论】:

【参考方案3】:

远射,但你试过了吗:

 [[self delegate] addItemViewController:self didFinishWithGardenID:_kidGaedenID gardenName:_kidGardenName andCityName:_kidCityName]];

而不是

 [self.delegate addItemViewController:self didFinishWithGardenID:_kidGaedenID gardenName:_kidGardenName andCityName:_kidCityName];

【讨论】:

@property (nonatomic, weak) id 委托;虚弱的????我认为这是在它被使用之前发布的 - Try Strong 我最后一次尝试被告知它应该是分配的,绝对不是 Strong 不确定。【参考方案4】:

我从您的查询和疑虑中了解到我发现了一些东西

   UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];

    searchVC = (ControllerA *)[storyboard instantiateViewControllerWithIdentifier:@"controllerA"];
    searchVC.delegate = self;

    [self.navigationController pushViewController:searchVC animated:YES];

希望对你有帮助:)

【讨论】:

我不能使用 segue,因为 ViewController B 是一个弹出窗口,我使用来自 gitHub MZFormSheetController 的这个包来实现。当我点击 ViewControllerB 中的一个单元格时,弹出窗口被关闭。所以我必须在关闭弹出窗口(VC B)之前准备好要传递的数据 是的,在你点击的地方收集你的数据是执行你只需要在你之后调用 [self performSegueWithIdentifier:@"controllerB" sender:self];收集了您的数据。它将调用方法 -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 但是他们之间的故事板中没有segue。正如我所说的VC B是AC A上的一个弹出窗口。我仍然可以使用prepareForSegue?

以上是关于在 ViewControllerB 到 ViewControllerA 之间传递数据,委托不会被调用的主要内容,如果未能解决你的问题,请参考以下文章

在导航历史记录中跳过视图

if Condition 在执行 segue 之前为 True

在类 Obj-C 之间发送消息?

准备继续时在目标视图控制器中设置选择器

在运行时以编程方式激活约束

UIView 过渡动画