Во-первых, убедитесь, что ваш поповер действительно NSPopover
, а не просто NSViewController
. Предполагая, что контроллер представления, который вы хотите обернуть во всплывающее окно, имеет идентификатор раскадровки «vcPopover», получение содержимого vc будет выглядеть так:
let popoverContentController = NSStoryboard(name: NSStoryboard.Name(rawValue: "Main"), bundle: nil).instantiateController(withIdentifier: NSStoryboard.SceneIdentifier(rawValue: "vcPopover")) as! NSViewController
Затем оберните его в поповер:
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
Затем для презентации вызовите show(relativeTo:of:preferredEdge:)
:
vcPopover.show(relativeTo: myButton.bounds, of: myButton, preferredEdge: .maxX)
Это должно обновить позицию всплывающего окна.
Обновление: вы, вероятно, используете 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
}
}
Обратите внимание, что расширение NSSegmentedControl
вычисляет приблизительный прямоугольник для сегмента, используя ширину. Этот метод предполагает равную ширину и не учитывает границы. Вы можете изменить этот метод, чтобы учесть то, что вам нужно. Информацию о получении кадра сегмента для iOS (что аналогично) можно найти здесь< /а>.
Этот пример проверен на правильность работы, если контроллер представления существует в той же раскадровке с идентификатором раскадровки "vcPopover".
person
Matthew Seaman
schedule
02.10.2017