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"을 반환해야한다고 말합니다 . 또한, "이 방법을 구현하거나 이외의 어떤 스타일을 반환하지 않는 경우 UIModalPresentationFullScreenUIModalPresentationOverFullScreen, 프리젠 테이션 컨트롤러는에 프리젠 테이션 스타일 조정 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.