iOS 8에서 올바르게 팝 오버를 표시하는 방법


118

Swift iOS 8 앱에 UIPopoverView를 추가하려고하는데 팝 오버가 올바른 모양으로 표시되지 않기 때문에 PopoverContentSize 속성에 액세스 할 수 없습니다. 내 코드 :

var popover: UIPopoverController? = nil 

    func addCategory() {

    var newCategory = storyboard.instantiateViewControllerWithIdentifier("NewCategory") as UIViewController
    var nav = UINavigationController(rootViewController: newCategory)
    popover = UIPopoverController(contentViewController: nav)
    popover!.setPopoverContentSize(CGSizeMake(550, 600), animated: true)
    popover!.delegate = self
    popover!.presentPopoverFromBarButtonItem(self.navigationItem.rightBarButtonItem, permittedArrowDirections: UIPopoverArrowDirection.Any, animated: true)
}

산출:

여기에 이미지 설명 입력

UIPopoverPresentationController를 통해 동일한 작업을 수행 할 때도 여전히 수행되지 않습니다. 이것은 내 코드입니다.

func addCategory() {

    var popoverContent = self.storyboard.instantiateViewControllerWithIdentifier("NewCategory") as UIViewController
    var nav = UINavigationController(rootViewController: popoverContent)
    nav.modalPresentationStyle = UIModalPresentationStyle.Popover
    var popover = nav.popoverPresentationController as UIPopoverPresentationController
    popover.delegate = self
    popover.popoverContentSize = CGSizeMake(1000, 300)
    popover.sourceView = self.view
    popover.sourceRect = CGRectMake(100,100,0,0)

    self.presentViewController(nav, animated: true, completion: nil)

}

나는 똑같은 출력을 얻습니다.

팝 오버의 크기를 어떻게 사용자 정의합니까? 어떤 도움이라도 대단히 감사하겠습니다!


개발자 사이트에 "A Look Inside Presentation Controllers"라는 WWDC 비디오가 있습니다. UIPopoverPresentationController
— Wextux

UIpopoverpresentationctontroller에 관한 사과 비디오에 따라 질문을 편집했지만 아무것도 변경되지 않았습니다! 내가 이것에 대해 변경해야 할 것이 있습니까? 그래도 입력 해 주셔서 감사합니다!
— Joris416

답변:


148

좋아, 한 집 친구가 그것을보고 알아 냈다.

 func addCategory() {

    var popoverContent = self.storyboard?.instantiateViewControllerWithIdentifier("NewCategory") as UIViewController
    var nav = UINavigationController(rootViewController: popoverContent)
    nav.modalPresentationStyle = UIModalPresentationStyle.Popover
    var popover = nav.popoverPresentationController
    popoverContent.preferredContentSize = CGSizeMake(500,600)
    popover.delegate = self
    popover.sourceView = self.view
    popover.sourceRect = CGRectMake(100,100,0,0)

    self.presentViewController(nav, animated: true, completion: nil)

}

바로 그거야.

더 이상 팝 오버 자체와 대화하지 않고 속성을 호출하여 콘텐츠 크기를 설정하기 위해 그 안에있는 뷰 컨트롤러와 대화합니다. preferredContentSize


15
아마도 명백한 것을 말하지만 이것은 단지 신속한 관련이 아닙니다. 또한 : 내 OBJ-C 응용 프로그램에서이 작업을 수행했다
— 케빈 R에게

4
코드에 대한 또 다른 설명- "var"대신 "let"을 사용할 수 있습니다. Apple은 값을 재 할당 할 필요가없는 경우에 권장합니다.
— EPage_Ed 2014 년

3
이것은 iPhone 용 GM에서 버그가 있습니다. 시뮬레이터가 세로로있는 상태에서 프레젠테이션을 시도하면 항상 전체 화면이됩니다. 가로로 회전하면 팝 오버가됩니다. 다시 세로로 회전하면 팝 오버로 유지됩니다.
— jjxtra

1
해결책은 presentViewController를 호출하기 전에 팝 오버를 설정하는 것입니다. 이것은 presentViewController를 호출 한 후 팝 오버를 설정하라고 명시 적으로 말하는 Apple의 예와 정확히 반대입니다.
— jjxtra

1
@PsychoDad가 언급 한이 솔루션에 대한 링크를 제공하십시오. 나는 여전히 "시뮬레이터가 세로로있는 동안에는 항상 전체 화면입니다"에 갇혀 있습니다. 감사합니다
— Nishant 2014 년

53

사실 그것은 그것보다 훨씬 간단합니다. 스토리 보드에서 팝 오버로 사용할 viewcontroller를 만들고 평소와 같이 viewcontroller 클래스를 만들어야합니다. 팝 오버를 열려는 개체에서 아래와 같이 segue를 만듭니다.이 경우에는 UIBarButton"Config"라는 이름으로 지정합니다.

여기에 이미지 설명 입력

"mother viewcontroller"에서 UIPopoverPresentationControllerDelegate및 delegate 메소드를 구현합니다 .

func popoverPresentationControllerDidDismissPopover(popoverPresentationController: UIPopoverPresentationController) {
    //do som stuff from the popover
}

다음 prepareForSeque과 같이 메서드를 재정의합니다 .

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
     //segue for the popover configuration window
    if segue.identifier == "yourSegueIdentifierForPopOver" {
        if let controller = segue.destinationViewController as? UIViewController {
            controller.popoverPresentationController!.delegate = self
            controller.preferredContentSize = CGSize(width: 320, height: 186)
        }
    }
}

그리고 당신은 끝났습니다. 이제 팝 오버보기를 다른보기로 취급 할 수 있습니다. 필드를 추가하고 무엇을하지 마십시오! 그리고 다음을 사용하여 콘텐츠 컨트롤러를 확보 할 수 있습니다.popoverPresentationController.presentedViewController 메서드를 를 확보합니다 UIPopoverPresentationController.

또한 iPhone에서는 덮어 써야합니다.

func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {

        return UIModalPresentationStyle.none
    } 

28

장치 / 방향 https://github.com/frogcjn/AdaptivePopover_iOS8_Swift에 관계없이 항상 팝 오버를 표시 할 수 있도록이 모든 작업을 수행하는 방법에 대한 완전한 예제를 찾았습니다 .

핵심은 UIAdaptivePresentationControllerDelegate를 구현하는 것입니다.

func adaptivePresentationStyleForPresentationController(PC: UIPresentationController!) -> UIModalPresentationStyle {
    // This *forces* a popover to be displayed on the iPhone
    return .None
}

그런 다음 위의 예를 확장합니다 (Imagine Digital).

nav.popoverPresentationController!.delegate = implOfUIAPCDelegate

나는 UIPopoverPresentationControllerDelegate를 사용
— onmyway133

3
맞습니다. UIPopoverPresentationControllerDelegate는 UIAdaptivePresentationControllerDelegate를 확장합니다. 따라서 정의에 따라 둘 다 'adaptivePresentationStyleForPresentationController'메서드를 포함합니다. 메서드가 Apple의 API 문서에 문서화되어 있으므로 기본 인터페이스를 제공했습니다.
— David Hunt

1
이것은 문서화되지 않은 동작입니다. 문서는이 대리자 메서드가 " UIModalPresentationFullScreen또는 UIModalPresentationOverFullScreen"을 반환해야한다고 말합니다 . 또한, "이 방법을 구현하거나 이외의 어떤 스타일을 반환하지 않는 경우 UIModalPresentationFullScreen나 UIModalPresentationOverFullScreen, 프리젠 테이션 컨트롤러는에 프리젠 테이션 스타일 조정 UIModalPresentationFullScreen스타일을."
— 톰

1
현재 문서는 iOS 8.3부터 adaptivePresentationStyleForPresentationController : traitCollection :을 사용해야하며 반환 된 스타일은 "UIModalPresentationFullScreen, UIModalPresentationOverFullScreen, UIModalPresentationFormSheet 또는 UIModalPresentationNone"이어야한다고 조언합니다.
— Dale

25

스위프트 2.0

글쎄요. 보세요. StoryBoard에서 ViewController를 만들었습니다. PopOverViewController 클래스와 연결됩니다.

import UIKit

class PopOverViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()    
        self.preferredContentSize = CGSizeMake(200, 200)    
        self.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Done, target: self, action: "dismiss:")    
    }    
    func dismiss(sender: AnyObject) {
        self.dismissViewControllerAnimated(true, completion: nil)
    }
}      

ViewController를 참조하십시오.

//  ViewController.swift

import UIKit

class ViewController: UIViewController, UIPopoverPresentationControllerDelegate
{
    func showPopover(base: UIView)
    {
        if let viewController = self.storyboard?.instantiateViewControllerWithIdentifier("popover") as? PopOverViewController {    

            let navController = UINavigationController(rootViewController: viewController)
            navController.modalPresentationStyle = .Popover

            if let pctrl = navController.popoverPresentationController {
                pctrl.delegate = self

                pctrl.sourceView = base
                pctrl.sourceRect = base.bounds

                self.presentViewController(navController, animated: true, completion: nil)
            }
        }
    }    
    override func viewDidLoad(){
        super.viewDidLoad()
    }    
    @IBAction func onShow(sender: UIButton)
    {
        self.showPopover(sender)
    }    
    func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle {
        return .None
    }
}  

참고 : func showPopover (base : UIView) 메서드는 ViewDidLoad 앞에 배치해야합니다. 도움이 되길 바랍니다!


안녕하세요 @Alvin,지도 주석에서보기를 팝업하겠습니다. 그래서 나는 당신이했던 것과 똑같이했습니다. 차이점은 view 대신 tableviewcontroller를 채울 것이라는 것입니다. 이제 문제는 델리게이트 메소드. "popoverPresentationControllerDidDismissPopover"를 치는 것이 아닙니다. 컨트롤러를 닫을 때. 도울 수 있니 ? (질문 게시물과 관련이 없습니다)
— 수빈 K Kuriakose에게

1
왜 showPopover(base: UIView)전에 메서드를 배치해야 viewDidLoad()합니까?
— Eimantas

15

iOS9에서 UIPopoverController는 감가 상각됩니다. 따라서 iOS9.x 이상의 Objective-C 버전에 대해 아래 코드를 사용할 수 있습니다.

- (IBAction)onclickPopover:(id)sender {
UIStoryboard *sb = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];
UIViewController *viewController = [sb instantiateViewControllerWithIdentifier:@"popover"];

viewController.modalPresentationStyle = UIModalPresentationPopover;
viewController.popoverPresentationController.sourceView = self.popOverBtn;
viewController.popoverPresentationController.sourceRect = self.popOverBtn.bounds;
viewController.popoverPresentationController.permittedArrowDirections = UIPopoverArrowDirectionAny;
[self presentViewController:viewController animated:YES completion:nil]; }

이 질문은 Objective-C가 아닌 Swift를 구체적으로 요구합니다.
— Eric Aya

8

여기에서 "Joris416"Swift 코드를 Objective-c로 변환합니다.

-(void) popoverstart
{
    ViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:@"PopoverView"];
    UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:controller];
    nav.modalPresentationStyle = UIModalPresentationPopover;
    UIPopoverPresentationController *popover = nav.popoverPresentationController;
    controller.preferredContentSize = CGSizeMake(300, 200);
    popover.delegate = self;
    popover.sourceView = self.view;
    popover.sourceRect = CGRectMake(100, 100, 0, 0);
    popover.permittedArrowDirections = UIPopoverArrowDirectionAny;
    [self presentViewController:nav animated:YES completion:nil];
}

-(UIModalPresentationStyle) adaptivePresentationStyleForPresentationController: (UIPresentationController * ) controller
{
    return UIModalPresentationNone;
}

추가하는 것을 잊지 마십시오
UIPopoverPresentationControllerDelegate, UIAdaptivePresentationControllerDelegate


이 질문은 Objective-C가 아닌 Swift를 구체적으로 요구합니다.
— Eric Aya

4

이것은 iOS8 Day-by-Day 블로그

간단히 말해 UIViewController의 modalPresentationStyle을 .Popover로 설정하면 컨트롤러의 popoverPresentationController 속성을 통해 UIPopoverPresentationClass (새로운 iOS8 클래스)를 확보 할 수 있습니다.


3

위에서 Imagine Digitals의 Objective-C 버전을 신속하게 답변했습니다. 나는 예비 테스트에서 작동하는 것처럼 보이는 것처럼 아무것도 놓친 것 같지 않습니다. 무언가를 발견하면 알려 주시면 업데이트하겠습니다.

-(void) presentPopover
{
    YourViewController* popoverContent = [[YourViewController alloc] init]; //this will be a subclass of UIViewController
    UINavigationController* nav =  [[UINavigationController alloc] initWithRootViewController:popoverContent];
    nav.modalPresentationStyle = UIModalPresentationPopover;
    UIPopoverPresentationController* popover = nav.popoverPresentationController;
    popoverContent.preferredContentSize = CGSizeMake(500,600);
    popover.delegate = self;
    popover.sourceRect = CGRectMake(100,100,0,0); //I actually used popover.barButtonItem = self.myBarButton;

    [self presentViewController:nav animated:YES completion:nil];
}

난 당신이 왼쪽으로 생각 popover.sourceView = self.view;
— GHR을

이 질문은 Objective-C가 아닌 Swift를 구체적으로 요구합니다.
— Eric Aya

4
나는 그것을 알고 있지만, 당신이 목표 -C를 찾고 있더라도 구글은 당신을 여기로 데려옵니다. 그것이 내가 여기까지 온 방법입니다.
— narco

3

xcode 9.1 / swift 4에 대한 내 2 센트.

class ViewController: UIViewController, UIPopoverPresentationControllerDelegate {

    override func viewDidLoad(){
        super.viewDidLoad()

        let when = DispatchTime.now() + 0.5

        DispatchQueue.main.asyncAfter(deadline: when, execute: { () -> Void in
            // to test after 05.secs... :)
            self.showPopover(base: self.view)

        })

}


func showPopover(base: UIView) {
    if let viewController = self.storyboard?.instantiateViewController(withIdentifier: "popover") as? PopOverViewController {

        let navController = UINavigationController(rootViewController: viewController)
        navController.modalPresentationStyle = .popover

        if let pctrl = navController.popoverPresentationController {
            pctrl.delegate = self

            pctrl.sourceView = base
            pctrl.sourceRect = base.bounds

            self.present(navController, animated: true, completion: nil)
        }
    }
}


@IBAction func onShow(sender: UIButton){
    self.showPopover(base: sender)
}

func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle{
    return .none
}

및 실험 :

func adaptivePresentationStyle ...

    return .popover

또는 : return .pageSheet .... 등등 ..


2

Viewcontroller에서 UIAdaptivePresentationControllerDelegate를 구현하십시오. 그런 다음 다음을 추가하십시오.

func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle{
    return .none
}

1

다음은 팝 오버를 구성하고 표시하는 방법에 대한 매우 포괄적 인 가이드입니다. https://www.appcoda.com/presentation-controllers-tutorial/

요약하면, 실행 가능한 구현 ( Swift 4.2 의 원본 문서 구문에서 일부 업데이트 포함 )을 다른 곳에서 호출하면 다음과 같습니다.

func showPopover(ofViewController popoverViewController: UIViewController, originView: UIView) {
    popoverViewController.modalPresentationStyle = UIModalPresentationStyle.popover
    if let popoverController = popoverViewController.popoverPresentationController {
        popoverController.delegate = self
        popoverController.sourceView = originView
        popoverController.sourceRect = originView.bounds
        popoverController.permittedArrowDirections = UIPopoverArrowDirection.any
    }
    self.present(popoverViewController, animated: true)
}

이것의 많은 부분은 이미 @mmc의 답변에서 다루어졌지만이 기사는 사용 된 코드 요소 중 일부를 설명하고 확장 방법을 보여줍니다.

또한 iPhone 대 iPad의 프레젠테이션 스타일을 처리하고 전체 화면으로 표시되는 경우 팝 오버를 해제 할 수 있도록 위임을 사용하는 방법에 대한 많은 추가 세부 정보를 제공합니다. 다시 Swift 4.2로 업데이트되었습니다 .

func adaptivePresentationStyle(for: UIPresentationController) -> UIModalPresentationStyle {
    //return UIModalPresentationStyle.fullScreen
    return UIModalPresentationStyle.none
}

func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
    if traitCollection.horizontalSizeClass == .compact {
        return UIModalPresentationStyle.none
        //return UIModalPresentationStyle.fullScreen
    }
    //return UIModalPresentationStyle.fullScreen
    return UIModalPresentationStyle.none
}

func presentationController(_ controller: UIPresentationController, viewControllerForAdaptivePresentationStyle style: UIModalPresentationStyle) -> UIViewController? {
    switch style {
    case .fullScreen:
        let navigationController = UINavigationController(rootViewController: controller.presentedViewController)
        let doneButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.done, target: self, action: #selector(doneWithPopover))
        navigationController.topViewController?.navigationItem.rightBarButtonItem = doneButton
        return navigationController
    default:
        return controller.presentedViewController
    }
}

// As of Swift 4, functions used in selectors must be declared as @objc
@objc private func doneWithPopover() {
    self.dismiss(animated: true, completion: nil)
}

도움이 되었기를 바랍니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.