How to Call Presentviewcontroller from Inside Class

How to call presentViewController from inside class

Your class RemoteAPI does not have a method called presentViewController(). presentViewController() is a method on a UIViewController. This is why you are getting the error.

To call presentViewController(), call back to a UIViewController instance when your HTTP response finishes.

Inside your else block of api.getData(), you can access the error object. Here you can create your alert controller and then present it. This block of code is called a callback, and your view controller should be responsible for creating the alert controller that indicates an error.

Calling presentViewController from custom class

I sometimes create a utilities class to display alerts and such. What I usually do is have my methods for presenting view controllers take the current view controller as a parameter. That approach works pretty well.

EDIT:

Here is an example method from a file Utils.swift in one of my projects. It defines a class function that displays a UIAlertController alert on the current view controller:

class Utils
{
static let sharedUtils = Utils()

class func showAlertOnVC(
targetVC: UIViewController,
var title: String,
var message: String)
{
title = NSLocalizedString(title, comment: "")
message = NSLocalizedString(message, comment: "")
let alert = UIAlertController(
title: title,
message: message,
preferredStyle: UIAlertControllerStyle.Alert)
let okButton = UIAlertAction(
title:"OK",
style: UIAlertActionStyle.Default,
handler:
{
(alert: UIAlertAction!) in
})
alert.addAction(okButton)
targetVC.presentViewController(alert, animated: true, completion: nil)
}
}

The code above defines a class Utils. Note that it does not have any base class, which is Ok in Swift.

Next it defines a public static variable sharedUtils that you can use to get access to the singleton Utils class.

Finally, it defines a class method showAlertOnVC that can be used to display a UIAlertController alert on top of the current view controller. To use showAlertOnVC you call it from the current view controller and pass self as the targetVC parameter.

How can I call presentViewController in UIView class?

Call this function on your button

func infoClick()  {

let storyboard: UIStoryboard = UIStoryboard (name: "Main", bundle: nil)
let vc: CampainDetailView = storyboard.instantiateViewControllerWithIdentifier("campainDetailView") as! CampainDetailView
let currentController = self.getCurrentViewController()
currentController?.presentViewController(vc, animated: false, completion: nil)

}

This function will create root view controller

 func getCurrentViewController() -> UIViewController? {

if let rootController = UIApplication.shared.keyWindow?.rootViewController {
var currentController: UIViewController! = rootController
while( currentController.presentedViewController != nil ) {
currentController = currentController.presentedViewController
}
return currentController
}
return nil

}

This above code must work, it is working for me in Swift 4.0

Present View Controller from another class

This line:

ViewControllerYoutube *vc = [[ViewControllerYoutube alloc]init];

Creates a new instance of ViewControllerYoutube. This ViewController doesn't exist anywhere else but that line, so when you follow it with this:

ViewControllerYoutube *vc = [[ViewControllerYoutube alloc]init];
[vc presentViewController:vc animated:YES completion:nil];

You're trying to present on a view controller that hasn't yet been presented.

If you want to present from an outside class, you need some way to keep a reference to the view controller you want to present, perhaps in your ActionSheet.h

@property (weak, nonatomic) ViewControllerYoutube *myViewControllerYoutube;

Then assign it when you create your action sheet (assuming you create it in ViewControllerYoutube)

ActionSheet * myActionSheet = [[ActionSheet alloc]init];
myActionSheet.myViewControllerYoutube = self;

Then instead of this:

ViewControllerYoutube *vc = [[ViewControllerYoutube alloc]init];
[vc presentViewController:vc animated:YES completion:nil];

Call this:

[_myViewControllerYoutube presentViewController:vc animated:YES completion:nil];

UPDATE

Based on our chat, here's how I think we can solve it.

  1. In ActionSheet.h:

    @property (weak, nonatomic) UIViewController *presentingViewController;
  2. In 'ActionSheet.m'

    ViewControllerYoutube *vc = [[ViewControllerYoutube alloc]init];
    [_presentingViewController presentViewController:vc animated:YES completion:nil];
  3. In your AppDelegate:

    ActionSheet * actionSheet = [[ActionSheet alloc]init];
    UITabBarController * tabController = (UITabBarController *)self.window.rootViewController;
    actionSheet.presentingViewController = tabController.selectedViewController;

how to call presentViewController from within a UICollectionViewCell

UITableViewCell should never handle any business logic. It should be implemented in a view controller. You should use a delegate:

UICollectionViewCell subclass:

protocol CustomCellDelegate: class {
func sharePressed(cell: MyCell)
}

class CustomCell: UITableViewCell {
var delegate: CustomCellDelegate?

func didTapShare(sender: UIButton) {
delegate?.sharePressed(cell: self)
}
}

ViewController:

class TableViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

@IBOutlet weak var tableView: UITableView!

//...

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! CustomCell
cell.delegate = self
return cell
}
}

extension TableViewController: CustomCellDelegate {
func sharePressed(cell: CustomCell) {
guard let index = tableView.indexPath(for: cell)?.row else { return }
//fetch the dataSource object using index
}
}

Using presentViewController from UIView

Only UIViewController can present another view controller, so if you need to show a viewcontroller from view there are several way, one of them is like this:

make a viewcontroller on which your parent view is situated a delegate of it

ParentView *view = [ParentView new];
...
view.delegate = self;

then, inside ParentView call method of that delegate

- (IBAction)homeButtonPressed:(id)sender {
[self.delegate buttonPressed];
}

and then, inside your VC implement

 -(void)buttonPressed {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
ViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"ViewController"];
[vc setModalPresentationStyle:UIModalPresentationFullScreen];
[self presentViewController:vc animated:NO completion:NULL];
}

If you need to keep this code inside UIView and avoid delegation you can do a trick like this (personally i don't like it but it should work)

-(void)buttonPressed{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
ViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"ViewController"];
[vc setModalPresentationStyle:UIModalPresentationFullScreen];
[(UIViewController*)self.nextResonder presentViewController:vc animated:NO completion:NULL];
}


Related Topics



Leave a reply



Submit