Get to UIViewController from UIView?

前端 未结 29 1734
一整个雨季
一整个雨季 2020-11-22 16:57

Is there a built-in way to get from a UIView to its UIViewController? I know you can get from UIViewController to its UIView

相关标签:
29条回答
  • 2020-11-22 17:39

    This doesn't answer the question directly, but rather makes an assumption about the intent of the question.

    If you have a view and in that view you need to call a method on another object, like say the view controller, you can use the NSNotificationCenter instead.

    First create your notification string in a header file

    #define SLCopyStringNotification @"ShaoloCopyStringNotification"
    

    In your view call postNotificationName:

    - (IBAction) copyString:(id)sender
    {
        [[NSNotificationCenter defaultCenter] postNotificationName:SLCopyStringNotification object:nil];
    }
    

    Then in your view controller you add an observer. I do this in viewDidLoad

    - (void)viewDidLoad
    {
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(copyString:)
                                                     name:SLCopyStringNotification
                                                   object:nil];
    }
    

    Now (also in the same view controller) implement your method copyString: as depicted in the @selector above.

    - (IBAction) copyString:(id)sender
    {
        CalculatorResult* result = (CalculatorResult*)[[PercentCalculator sharedInstance].arrayTableDS objectAtIndex:([self.viewTableResults indexPathForSelectedRow].row)];
        UIPasteboard *gpBoard = [UIPasteboard generalPasteboard];
        [gpBoard setString:result.stringResult];
    }
    

    I'm not saying this is the right way to do this, it just seems cleaner than running up the first responder chain. I used this code to implement a UIMenuController on a UITableView and pass the event back up to the UIViewController so I can do something with the data.

    0 讨论(0)
  • 2020-11-22 17:40

    If you aren't going to upload this to the App Store, you can also use a private method of UIView.

    @interface UIView(Private)
    - (UIViewController *)_viewControllerForAncestor;
    @end
    
    // Later in the code
    UIViewController *vc = [myView _viewControllerForAncestor];
    
    0 讨论(0)
  • 2020-11-22 17:41

    I stumbled upon a situation where I have a small component I want to reuse, and added some code in a reusable view itself(it's really not much more than a button that opens a PopoverController).

    While this works fine in the iPad (the UIPopoverController presents itself, therefor needs no reference to a UIViewController), getting the same code to work means suddenly referencing your presentViewController from your UIViewController. Kinda inconsistent right?

    Like mentioned before, it's not the best approach to have logic in your UIView. But it felt really useless to wrap the few lines of code needed in a separate controller.

    Either way, here's a swift solution, which adds a new property to any UIView:

    extension UIView {
    
        var viewController: UIViewController? {
    
            var responder: UIResponder? = self
    
            while responder != nil {
    
                if let responder = responder as? UIViewController {
                    return responder
                }
                responder = responder?.nextResponder()
            }
            return nil
        }
    }
    
    0 讨论(0)
  • 2020-11-22 17:41

    My solution would probably be considered kind of bogus but I had a similar situation as mayoneez (I wanted to switch views in response to a gesture in an EAGLView), and I got the EAGL's view controller this way:

    EAGLViewController *vc = ((EAGLAppDelegate*)[[UIApplication sharedApplication] delegate]).viewController;
    
    0 讨论(0)
  • 2020-11-22 17:43

    Even though this can technically be solved as pgb recommends, IMHO, this is a design flaw. The view should not need to be aware of the controller.

    0 讨论(0)
  • 2020-11-22 17:43

    Swift 4 version

    extension UIView {
    var parentViewController: UIViewController? {
        var parentResponder: UIResponder? = self
        while parentResponder != nil {
            parentResponder = parentResponder!.next
            if let viewController = parentResponder as? UIViewController {
                return viewController
            }
        }
        return nil
    }
    

    Usage example

     if let parent = self.view.parentViewController{
    
     }
    
    0 讨论(0)
提交回复
热议问题