如何使用Storyboard制作可在代码中使用的popover?

时间:2012-06-22 18:15:12

标签: xcode storyboard popover

我正在构建一个表单集合,每个表单都包含几个字段。某些字段为UITextField,将显示日期。我创建了一个名为DatePickerTextField的新类,它是UITextField的后代。点击DatePickerTextField时,我希望UIDatePicker控件显示在popover中。

我的问题是如何使用故事板来实现popover?当场景中有特定的可见控件时,我可以做一个segue。但是如何在场景中表示我可以附加到任何变为活动的实例化popover的通用DatePickerTextField

5 个答案:

答案 0 :(得分:36)

你可以创建没有连接到任何控件的segue,但我认为没有办法为代码中的popover指定锚点。另一种选择是创建未与任何segue连接的ViewController。编辑故事板时,创建将放置在弹出窗口中的ViewController,选择它并导航到实用程序窗格 - > 属性检查器。将大小设置为自由格式,将状态栏设置为,指定唯一的标识符用于从代码中实例化ViewController。现在,您可以通过选择ViewController并导航到 Utilities窗格 - > Size Inspector 来更改ViewController的大小。

之后,您可以从代码创建弹出窗口:

- (IBAction)buttonPressed:(id)sender {
    UIView *anchor = sender;
    UIViewController *viewControllerForPopover = 
        [self.storyboard instantiateViewControllerWithIdentifier:@"yourIdentifier"];

    popover = [[UIPopoverController alloc] 
               initWithContentViewController:viewControllerForPopover];
    [popover presentPopoverFromRect:anchor.frame 
                             inView:anchor.superview 
           permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}

有一点需要注意,您需要将popover引用为类的ivar,否则它会崩溃,因为UIPopoverController将在buttonPressed返回后释放并释放:

@interface MyViewController : UIViewController {
//  ...
    UIPopoverController *popover;
//  ...
}

答案 1 :(得分:2)

所以,我有一个类似的问题,如果其他人可能会受益,我想我会分享它,因为我从stackoverflow中受益匪浅。

此解决方案允许您设置可自定义的popover segue的锚点。它还允许你将segue配置为模态或不是(我找不到通过调暗外部环境来防止segue的方法,所以如果有人知道如何做到这一点,我会有兴趣听到它);这是通过为弹出控制器设置passthrough视图来完成的。我还添加了指定自定义视图的容量,而不是源视图控制器的视图(因为我需要这个容量);这部分对解决方案并不重要。

DynamicPopoverSegue.h

@interface DynamicPopoverSegue : UIStoryboardPopoverSegue

@property BOOL isModal;
@property UIView* sourceView;
@property CGRect anchor;

@end

DynamicPopoverSegue.m

@implementation DynamicPopoverSegue

- (void)perform
{
   if (!self.popoverController.popoverVisible)
   {
      UIViewController* dst = (UIViewController*)self.destinationViewController;
      UIViewController* src = (UIViewController*)self.sourceViewController;

      UIView* inView =  _sourceView ? _sourceView : src.view;

      self.popoverController.contentViewController = dst;
      if (!_isModal)
      {
         [self.popoverController setPassthroughViews:[[NSArray alloc] initWithObjects:inView, nil]];
      }
      [self.popoverController presentPopoverFromRect:_anchor
                                              inView:inView
                            permittedArrowDirections:UIPopoverArrowDirectionAny
                                            animated:YES];
   }
}

@end

然后,您只需在故事板中将segue设置为“Custom”,并将segue类设置为“DynamicPopoverSegue”。在我的情况下,因为我想将它与视图中的动态图层相关联,所以我无法设置锚点,所以我通过控制点击从视图控制器下方的栏中的视图控制器图标到视图控制器我创建了segue用来呈现弹出窗口。

调用popover segue:

[self performSegueWithIdentifier:@"MyPopoverSegue" sender:self];

并配置popover segue:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
   if ([[segue identifier] isEqualToString:@"MyPopoverSegue"])
   {
      DynamicPopoverSegue* popoverSegue = (DynamicPopoverSegue*)segue;
      // set the anchor to wherever you want it to be
      popoverSegue.anchor = _destinationFrame;
   }
}

答案 2 :(得分:0)

- (IBAction)pressItemChooseOprateRoom:(id)sender {
    if (isPad){
        // UIView *anchor = sender;
        UIViewController *viewControllerForPopover =
        [self.storyboard instantiateViewControllerWithIdentifier:@"OperateRoomList"];

        _myPopover = [[UIPopoverController alloc]
                      initWithContentViewController:viewControllerForPopover];

        CGRect rc=[self getBarItemRc:sender];
        [_myPopover presentPopoverFromRect:rc
                                    inView:self.view
                  permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];

        [MLControl shared].popover =self;
        // [self perfformSegueWithIdentifier:SEGUE_POP_OPERATEROOM sender:self];
    }else{
        [self iphoneOpenOperateRoomList];
        /* [self performSegueWithIdentifier:@"iPhonePushOperateRoom" sender:self];
         */
    }
}

-(void)iphoneOpenOperateRoomList{
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"OperateRoomList"];
    //        if (!index.showTabBar) {
    //            vc.hidesBottomBarWhenPushed = YES;
    //        }

    [self.navigationController pushViewController:vc animated:YES];
}

答案 3 :(得分:0)

刚刚将Jonnywho的答案用于我的SWIFT项目。如果您需要它:

以下是SWIFT版本:

    let anchor: UIView = sender
    var viewControllerForPopover = self.storyboard?.instantiateViewControllerWithIdentifier("GameAboutViewController") as! UIViewController?


    let popover = UIPopoverController(contentViewController: viewControllerForPopover!)
    popover.presentPopoverFromRect(anchor.frame, inView: anchor, permittedArrowDirections: UIPopoverArrowDirection.Any, animated: true)

答案 4 :(得分:0)

在场景底座中添加一个UIView。

您可以将其作为子视图添加到视图控制器上的任何现有视图。

然后您可以根据需要切换它的isHidden属性。

您可以添加多个此类子视图并创建许多此类弹出窗口。

此技术将使您不必设置新的View Controller和使用segues。