PresentViewController from custom TableCell in xib

Solution 1:

TableViewCell is a view, you can not present on views instead UIViewController can handle it. You should transfer the control from your cell to your controller that holds tableview and creates custom cell for it.

Try like this:

Custom Cell .h Class:

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

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

Then Synthesize it in.m.

Add this in m file:

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

The viewcontroller that loads this cell:

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

   cell.delegate = self;
}

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

Its a psuedocode to give you an idea.

EDIT:

Swift equivalent:

CustomTableViewCell.swift code:

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 code:

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

    };
}

Solution 2:

The answers proposing a delegate or instance variable are correct, but, however, in most cases it is not important to use a special view controller to present the new controller. In these cases the following solution is much simpler: Just use the applications root view controller:

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