如何理解/创建委托以解除视图控制器

时间:2014-10-14 06:14:17

标签: ios uiviewcontroller delegates uitabbarcontroller

尝试更好地了解iOS delegation。我使用UIImagePickerController作为参考,但使用委托来解除我的视图控制器是一个很好的代码示例?

我有一个 TabBarViewController调用AViewController ,并想使用delegation来解除AViewController。

1 个答案:

答案 0 :(得分:0)

在这种情况下,想法是呈现新viewcontroller的类也应该是解析它的类。 AViewController可能不知道它是如何呈现的,因此它希望让演示者TabBarViewController以任何需要的形式处理解雇。所以,我们需要定义一个协议,比如AViewControllerProtocol,它允许有一个解雇调用的标准定义:

这适用于AViewControllerProtocol.h:

@protocol AViewControllerProtocol <NSObject>
@required
- (void) dismissWithDone:(UIViewController *)viewController;
- (void) dismissWithCancel:(UIViewController *) viewController;
@optional
- (void)dismissWithDone:(UIViewController *)viewController andPlaySoundFile:(NSString *)soundPath;
@end

这是一个名为AViewControllerProtocol.h的文件。 TabBarViewController.m和AViewController.m都将导入它。您可以将此视为AViewController的任何用户在使用它之前必须同意的协议。同样地,你不能使用UITableView来观察UITableViewDelegate和UITableViewDataSource协议(这是两个独立的协议)。

任何想要呈现AViewController的类,都可以从协议定义中看到AViewController需要两个必需的方法才能被正确解除。它还有一个可选的第三种方法,要求演示者在解散后播放声音。

为了让AViewController完成这个协议的一部分,它需要获取并存储一条关于演示者是谁的信息。这被称为代表。委托是在AViewController的@interface中定义的属性,在AViewController.h中:

这是AViewController.h:

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

现在,演示者TabBarViewController需要做到这一点。它需要定义两个必需的方法,加上可能是最优的方法,还需要设置委托值:

在TabBarViewController.m中,在@implementation中:

这是TabBarViewController.m:

- (void) dismissWithDone:(UIViewController *)viewController
{
    [self saveData:viewController.dataToSave];  // this could be the results that need to be saved
    [viewController dismissViewControllerAnimated:YES completion:^{
        ;
    }];
}


- (void) dismissWithCancel:(UIViewController *)viewController
{
    // don't save data
    [viewController dismissViewControllerAnimated:YES completion:^{
        ;
    }];
}

委托值设置在AViewController首次创建和/或出现之前:

这也适用于TabBarViewController.m:

    AViewController * aVC = [AViewController.alloc init];
    aVC.delegate = self;
    aVC.data = ...; // this may be the data you want changed by the VC
    [self presentViewController:aVC animated:YES completion:^{
    }];

在这里设置委托是AViewController类与其呈现viewController的唯一连接 - 这就是这里的重点:子类真的不应该知道很多关于使用它们的类。< / p>

最后,AViewController类需要添加以下内容才能通过委托调用返回到呈现类 - 所以在AViewController.m中:

这是AViewController.m:

-(IBAction)userHitButton:(id)sender
{
    if (sender == doneButton) {
        if ([_delegate respondsToSelector:@selector(dismissWithDone:)]) {
            [_delegate dismissWithDone:self];
        }
    } else {
        if ([_delegate respondsToSelector:@selector(dismissWithCancel:)]) {
            [_delegate dismissWithCancel:self];
        }
    }
}

如果您想知道为什么调用类必须:

    aVC.delegate = self;

这是因为在某些情况下,实际创建子类的类不是处理委托调用的类。在这种情况下,您将放置一个将处理委托回调的类的实例,而不是self。例如,假设你有AViewController,BViewController和CViewController。它们都从需要保存的用户处获取数据。一个虚构名称ABCDataHandler的类可能是可以处理dismissWithDone的一个类:和dismissWithCancel:回调并根据需要保存数据,TabBarViewController可以不受任何数据处理活动的影响。

尽可能简单地说出来。我希望我没有在这里发生任何错别字: - )