从子视图中访问 UIViewController 方法

Posted

技术标签:

【中文标题】从子视图中访问 UIViewController 方法【英文标题】:Access UIViewController methods from within subview 【发布时间】:2016-09-25 04:39:17 【问题描述】:

我继承了 UITableViewCell 并在 UIView 中对其进行了初始化。从 TableView 中,我需要调用父 ViewController 中的一个方法(执行 segues 等)。

现在,由于 ViewController 不能直接传递给它的子视图(就 MVC 原则而言),我创建了一个委托模式,向 UITableView 添加一个协议,并在 UIVIewController 中将该协议作为委托实现。

问题在于,由于 TableView 是从 UIView 实例化的,UIView 是 Viewcontroller 的子视图,因此我无法在 cellForRowAtIndexPath 方法中将 ViewController 指定为委托,因为“self”将指向 View 而不是 ViewController。

如果我将所有表格方法移动到 ViewController 并从那里实例化表格,那么一切都会如我所愿。但这不允许我在其他 ViewController 中重用代码。

CustomViewController.h

#import "CustomTableViewCell.h"
@interface CustomViewController : UIViewController<CustomTableViewCellDelegate>

CustomViewController.m

- (void)viewDidLoad 
    [super viewDidLoad];
    // Create a sub-view where the custom table will appear
   _customUIView = [[CustomUIView alloc] initWithFrame:CGRectMake(0, 60, self.view.frame.size.width, self.view.frame.size.height-60)];

   [self.view addSubview:_customUIView];
   [_customUIView populateTheView];

CustomUIView.m

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
    NSString *cellIdentifier = [NSString stringWithFormat:@"cell%ld",(long)indexPath.row];

    CustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    if (cell == nil) 
        cell = [[CustomTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
        cell.delegate = self; // << THIS WILL NOT WORK AS IT WOULD POINT TO THE View, RATHER THAN THE ViewController
    

CustomTableViewCell.h

@protocol CustomTableViewCellDelegate <NSObject>
    -(void)performSegue;
@end
@interface CustomTableViewCell : UITableViewCell
    @property(weak, nonatomic) id<CustomTableViewCellDelegate>delegate;
@end

CustomTableViewCell.m

if ([self.delegate respondsToSelector:@selector(performSegue)]) 
    [self.delegate performSegue];

【问题讨论】:

您需要进行一些设置,以便视图控制器实现该属性,并以某种方式将对自身的引用传递给视图。您需要显示更多关于如何初始化/创建所有内容的代码 显示自定义单元格代码。 【参考方案1】:

我能找到的最佳解决方案是使用通知。 在您的 viewController 中,在 viewWillAppear 方法中设置观察者。您还需要在 viewWillDisappear 方法中删除它,否则应用程序将崩溃:

// In the parent view controller
- (void)viewWillAppear:(BOOL)animated 
    // Add observers to perform an action    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(imageTappedMessageReceived:) name:@"imageTapped" object:nil];


-(void) imageTappedMessageReceived:(NSNotification *)notification 
    NSLog(@"The image was tapped");


- (void)viewWillDisappear:(BOOL)animated 
    NSLog(@"View controller will disappear");
    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"imageTapped" object:nil];

在您需要时在您的子视图中发出通知(按钮按下或您拥有的其他逻辑):

// In the subview
[[NSNotificationCenter defaultCenter] postNotificationName:@"imageTapped" object:self userInfo:tempDictionary];

每次在子视图中调用“imageTapped”通知时,都会触发viewController中的“imageTappedMessageReceived”方法。

【讨论】:

以上是关于从子视图中访问 UIViewController 方法的主要内容,如果未能解决你的问题,请参考以下文章

从子视图 UIViewcontroller 到其他 UIViewController

您将如何从子视图中呈现ViewController?

如何从子视图内的编程 UIButton 执行 segue?

如何从子视图中隐藏 NavigationBar?

从子视图推送新的视图控制器

如何在 SwiftUI 中随时从子视图作为父视图访问数据?