设置 nspopover 的位置

Gho*_*108 2 macos nsviewcontroller nspopover swift

我有一个视图控制器 (A),它将显示另一个视图控制器 (B) 作为弹出窗口。

在我的 VC (A) 中是一个带有这个 IBAction 的 NSButton:

self.presentViewController(vcPopover, asPopoverRelativeTo: myButton.bounds, of: myButton, preferredEdge: .maxX, behavior: .semitransient)
Run Code Online (Sandbox Code Playgroud)

结果:

在此处输入图片说明

现在我想改变我的弹出框的位置 - 我想把它向上移动。

我试过这个:

let position = NSRect(origin: CGPoint(x: 100.0, y: 120.0), size: CGSize(width: 0.0, height: 0.0))
self.presentViewController(vcPopover, asPopoverRelativeTo: position, of: myButton, preferredEdge: .maxX, behavior: .semitransient)
Run Code Online (Sandbox Code Playgroud)

但立场不变

另一个例子

在此处输入图片说明

我有一个分段控件。如果您单击“1”段,将显示一个弹出窗口(与上面的代码相同)。但是箭头指向段“2”而不是段“1”

Mat*_*man 5

首先,确保您的弹出框确实是一个NSPopover而不仅仅是一个NSViewController. 假设您要包装在弹出窗口中的视图控制器的故事板 ID 为“vcPopover”,则获取内容 vc 将如下所示:

let popoverContentController = NSStoryboard(name: NSStoryboard.Name(rawValue: "Main"), bundle: nil).instantiateController(withIdentifier: NSStoryboard.SceneIdentifier(rawValue: "vcPopover")) as! NSViewController
Run Code Online (Sandbox Code Playgroud)

然后,将它包装在一个弹出窗口中:

let popover = NSPopover()
popover.contentSize = NSSize(width: 200, height: 200) // Or whatever size you want, perhaps based on the size of the content controller
popover.behavior = .semitransient
popover.animates = true
popover.contentViewController = popoverContentController    
Run Code Online (Sandbox Code Playgroud)

然后,要呈现,请致电show(relativeTo:of:preferredEdge:)

vcPopover.show(relativeTo: myButton.bounds, of: myButton, preferredEdge: .maxX)
Run Code Online (Sandbox Code Playgroud)

这应该更新弹出窗口的位置。

更新:您可能正在使用NSSegmentedControl,这意味着您需要特别注意您传入的矩形show。您需要在分段控件的坐标系内传递一个边界矩形,该坐标系描述了该段的区域。这是一个详细的例子:

// The view controller doing the presenting
class ViewController: NSViewController {

    ...

    var presentedPopover: NSPopover?

    @IBAction func selectionChanged(_ sender: NSSegmentedControl) {
        let segment = sender.selectedSegment

        if let storyboard = storyboard {
            let contentVC = storyboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier("vcPopover")) as! NSViewController

            presentedPopover = NSPopover()
            presentedPopover?.contentSize = NSSize(width: 200, height: 200)
            presentedPopover?.behavior = .semitransient
            presentedPopover?.animates = true
            presentedPopover?.contentViewController = contentVC
        }

        presentedPopover?.show(relativeTo: sender.relativeBounds(forSegment: segment), of: sender, preferredEdge: .minY)
    }

}

extension NSSegmentedControl {

    func relativeBounds(forSegment index: Int) -> NSRect {
        // Assuming equal widths
        let segmentWidth = bounds.width / CGFloat(segmentCount)

        var rect = bounds
        rect.size.width = segmentWidth
        rect.origin.x = rect.origin.x + segmentWidth * CGFloat(index)

        return rect
    }

}
Run Code Online (Sandbox Code Playgroud)

请注意,扩展NSSegmentedControl使用宽度计算线段的近似矩形。此方法假定宽度相等且不考虑边框。您可以修改此方法来满足您的需要。可以在此处找到有关获取 iOS 段的帧(类似)的信息

只要视图控制器存在于故事板标识符为“vcPopover”的同一个故事板中,此示例就被验证为正常工作。