在xib中的自定义表格单元中使用PresentViewController

12
我创建了自定义的“tableView Controller”,在单元格内放置了一个按钮,以打开设备照片库。我的问题是,我无法从CustomCell.m中打开imagePickerController,它显示如下错误。请提供一些解决方法。 enter image description here

使用委托模式将您的单元格与视图控制器绑定。 - Neil Galiaskarov
你能详细说明一下你的回答吗?@NeilGaliaskarov - Ramdhas
7个回答

32

TableViewCell是一个视图,你不能在视图上执行present操作,而是应该由UIViewController处理。你应该将控制权从单元格转移到持有tableview并为其创建自定义单元格的控制器。

可以尝试以下方法:

自定义单元格.h类:

@protocol changePictureProtocol <NSObject>
-(void)loadNewScreen:(UIViewController *)controller;
@end

@property (nonatomic, retain) id<changePictureProtocol> delegate;

然后在.m文件中进行合成。

将此添加到m文件中:

-(IBAction)changePicture:(id)sender
{
    // ..... blah blah
    [self.delegate loadNewScreen:picker];
}

加载此单元格的视图控制器:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
   // create cell here

   cell.delegate = self;
}

-(void)loadNewScreen:(UIViewController *)controller;
{
  [self presentViewController:controller animated:YES completion:nil];
}

这是一个伪代码,旨在让你有个概念。

编辑:

对应 Swift 代码:

CustomTableViewCell.swift 代码:

protocol ChangePictureProtocol : NSObjectProtocol { 
    func loadNewScreen(controller: UIViewController) -> Void;  
}

class CustomTableViewCell: UITableViewCell {

    // Rest of the class stuff

    weak var delegate: ChangePictureProtocol?

    @IBAction func changePicture(sender: AnyObject)->Void
    {
        var pickerVC = UIImagePickerController();
        if((delegate?.respondsToSelector("loadNewScreen:")) != nil)
        {
           delegate?.loadNewScreen(pickerVC);
        }  
    }
}

ViewController.swift 代码:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
    var cell = tableView.dequeueReusableCellWithIdentifier("cellIdentifier") as CustomTableViewCell!

    cell.delegate = self;

    return cell;
}

func loadNewScreen(controller: UIViewController) {
    self.presentViewController(controller, animated: true) { () -> Void in

    };
}

嘿,你介意用Swift解释一下吗?根据你的解释,我在将它从Objective-C转换过程中遇到了一些问题。非常感谢! - Lukesivi
@lukesIvi,请检查我对Swift等效性的修改,并让我知道您是否有任何困难。 - NeverHopeless
Swift对我来说不起作用,我尝试显示print(delegate),但它只是“nil”。 这是我的代码: func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) { print("Hello outside") print(delegate) if((delegate?.respondsToSelector("loadNewScreen:")) != nil) { print("Hello insinde") let details = MovieDetail(); delegate?.loadNewScreen(details); print(delegate) } } - Evan Ngo
@NeverHopeless,你能帮我一下吗?我理解了,但好像无法执行。 - luke
实际上,我通过一些微调让它工作了,谢谢。 - luke
显示剩余5条评论

11

提出使用委托或实例变量的答案是正确的,但是在大多数情况下,使用特殊的视图控制器来呈现新控制器并不重要。 在这些情况下,以下解决方案要简单得多:只需使用应用程序的根视图控制器:

UIViewController* activeVC = [UIApplication sharedApplication].keyWindow.rootViewController;
[activeVC presentViewController:'new view controller'
                       animated:YES
                     completion:NULL];

2
这种方法不适用于当您将表视图和单元格结构设置为不在根视图控制器层级中时。 "警告:试图在视图不在窗口层级中的MasterViewController: 0x7ffda2d60450上呈现<SetOpenViewController: 0x7ffda2f5c280>! - greenhouse

1
另一种方法是将CustomCell的控制器引用传递给CustomCell,并使用它来呈现新的控制器。
Swift:
CustomCell.swift:
class CustomTableViewCell: UITableViewCell {

    // Rest of the class stuff

    var parentViewController: UIViewController? = nil

    gotoNewControllerBtn.addTarget(self, action: #selector(gotoNewController), for: .touchUpInside)

    func gotoNewController() {
        let newViewController = NewViewController()
        parentViewController.present(newViewController, animated: true, completion: nil)
    }
}

ViewController.swift:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
    var cell = tableView.dequeueReusableCellWithIdentifier("cellIdentifier") as CustomTableViewCell!

    cell.parentViewController = self;

    return cell;
}

1

将您的按钮创建为IBOutlet

然后在cellForRowAtIndexPath中将目标分配给按钮

CustomCell *customCell=[tableView dequeueReusableCellWithIdentifier:@"CellIdentifier"];
[customCell.yourButton addTarget:self action:@selector(yourButtonAction:) forControlEvents:UIControlEventTouchUpInside];

1

presentViewController: 是用于视图控制器的消息。将控制从单元格委托给视图控制器,并使用相同的行即可解决问题。UITableViewCell 不响应 presentViewController: 消息。


1
你需要一个UIViewController来进行呈现。这里有几个可行的方案。一种方法是创建一个自定义委托协议,其中包含一个changePicturePressed回调方法。然后,您可以将包含视图控制器作为该委托分配,并在委托方法中执行呈现。
另一种方法是在初始化期间将UIViewController传递到单元格中,并将其设置为弱属性。然后,您可以直接从单元格内使用该属性执行呈现。

-1

你需要一个视图控制器来呈现视图。你不能在表格视图单元上呈现视图控制器。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接