Swift:带有建议标签列表的 NSTextfield 和 popover
Swift: NSTextfield and popover with suggested list of tags
我正在尝试做这样的事情:
这是我现在拥有的:
我现在是怎么做的:
我有 MainViewController
输入字段:NSTextField
。
使用 controlTextDidChange
我正在检查输入字段是否包含 #
字符。
如果是 - 我将使用 PopoverViewController
打开弹出框。
在 PopoverViewController
中,我有 NSTableView
显示可用标签列表。
通过单击该行,它应该将选定的标签添加到输入字段并关闭弹出窗口。
所以在这里我什至必须在 2 个视图控制器之间实现 2 种通信方式。
问题:
- 我觉得我做错了什么。这个 tags-popover 的逻辑对我来说看起来太复杂了。也许存在更简单的解决方案,但我只是不知道该怎么做。
- 在
NSTextField
中显示可用标签列表的最佳方式是什么?我应该将弹出窗口与另一个视图控制器一起使用吗?
- 在这种情况下,如何在 2 个不同的视图控制器之间进行最佳通信? (我必须将
InputField
值发送到 PopoverViewController
,在那里过滤结果并显示它们。然后,我必须发送回 MainViewController
选定的标签)
我的代码:
如果您想更详细地查看代码,这里是我的部分代码:
主视图控制器:
class ViewController: NSViewController, NSTextFieldDelegate {
@IBOutlet weak var InputField: NSTextField!
override func viewDidLoad() {
super.viewDidLoad()
table.delegate = self
table.dataSource = self
InputField.delegate = self
}
func controlTextDidChange(_ sender: Notification) {
if InputField.stringValue.contains("#") {
let controller = ToolTipVC.Controller()
let popover = NSPopover()
popover.contentViewController = controller
popover.behavior = .transient
popover.animates = true
popover.show(relativeTo: InputField.bounds, of: InputField!, preferredEdge: NSRectEdge.maxY)
}
}
ToolTipViewController:
import Cocoa
import EventKit
class ToolTipVC: NSViewController, NSTableViewDataSource, NSTableViewDelegate {
@IBOutlet weak var ToolTipTable: NSTableView!
override func viewDidLoad() {
super.viewDidLoad()
ToolTipTable.delegate = self
ToolTipTable.dataSource = self
}
func numberOfRows(in tableView: NSTableView) -> Int {
return ReminderLists.count
}
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
guard let cell = tableView.makeView(withIdentifier: tableColumn!.identifier, owner: self) as? NSTableCellView else { return nil }
cell.textField?.stringValue = "Row #\(row): " + ReminderLists[row].title
return cell
}
}
extension ToolTipVC {
static func Controller() -> ToolTipVC {
let storyboard = NSStoryboard(name: "Main", bundle: nil)
let identifier = NSStoryboard.SceneIdentifier("ToolTipId")
guard let viewcontroller = storyboard.instantiateController(withIdentifier: identifier) as? ToolTipVC else {
fatalError("Why cant i find viewcontroller? - Check Main.storyboard")
}
return viewcontroller
}
}
感谢您的反馈和建议。
提前致谢!
P.S.: 我不是开发人员,我是产品经理。这是我的宠物项目,所以我知道我的代码很糟糕并且有很多错误。
请不要苛刻地评判我:)
乍一看,当您调用此行时:
popover.show(relativeTo: InputField.bounds, of: InputField!, preferredEdge: NSRectEdge.maxY)
preferredEdge 设置为 NSRectEdge.maxY
尝试将其从 Y 更改为 X
popover.show(relativeTo: InputField.bounds, of: InputField!, preferredEdge: NSRectEdge.maxX)
您使用 NSPopover 有什么原因吗?
如果这不起作用试试这个:
let controller = MyPopViewController()
controller.modalPresentationStyle = UIModalPresentationStyle.popover
let popController = controller.popoverPresentationController
popController?.permittedArrowDirections = .any
popController?.delegate = self
popController?.sourceRect = //set the frame here
popController?.sourceView = //set the source view here
self.present(controller, animated: true, completion: nil)
这是另一种方法,它会将弹出窗口置于按钮上方的中心。我假设没有向上箭头,你想做什么?那是对的吗?
所以你可以点击右侧的过滤器按钮,这个弹出窗口将显示在中心。
@IBAction func buttonTap(sender: UIButton) {
// get a reference to the view controller for the popover
let popController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "popoverId")
// set the presentation style
popController.modalPresentationStyle = UIModalPresentationStyle.popover
// set up the popover presentation controller
popController.popoverPresentationController?.permittedArrowDirections = UIPopoverArrowDirection.up
popController.popoverPresentationController?.delegate = self
popController.popoverPresentationController?.sourceView = sender // button
popController.popoverPresentationController?.sourceRect = sender.bounds
// present the popover
self.present(popController, animated: true, completion: nil)
}
我正在尝试做这样的事情:
这是我现在拥有的:
我现在是怎么做的:
我有 MainViewController
输入字段:NSTextField
。
使用 controlTextDidChange
我正在检查输入字段是否包含 #
字符。
如果是 - 我将使用 PopoverViewController
打开弹出框。
在 PopoverViewController
中,我有 NSTableView
显示可用标签列表。
通过单击该行,它应该将选定的标签添加到输入字段并关闭弹出窗口。 所以在这里我什至必须在 2 个视图控制器之间实现 2 种通信方式。
问题:
- 我觉得我做错了什么。这个 tags-popover 的逻辑对我来说看起来太复杂了。也许存在更简单的解决方案,但我只是不知道该怎么做。
- 在
NSTextField
中显示可用标签列表的最佳方式是什么?我应该将弹出窗口与另一个视图控制器一起使用吗? - 在这种情况下,如何在 2 个不同的视图控制器之间进行最佳通信? (我必须将
InputField
值发送到PopoverViewController
,在那里过滤结果并显示它们。然后,我必须发送回MainViewController
选定的标签)
我的代码:
如果您想更详细地查看代码,这里是我的部分代码:
主视图控制器:
class ViewController: NSViewController, NSTextFieldDelegate {
@IBOutlet weak var InputField: NSTextField!
override func viewDidLoad() {
super.viewDidLoad()
table.delegate = self
table.dataSource = self
InputField.delegate = self
}
func controlTextDidChange(_ sender: Notification) {
if InputField.stringValue.contains("#") {
let controller = ToolTipVC.Controller()
let popover = NSPopover()
popover.contentViewController = controller
popover.behavior = .transient
popover.animates = true
popover.show(relativeTo: InputField.bounds, of: InputField!, preferredEdge: NSRectEdge.maxY)
}
}
ToolTipViewController:
import Cocoa
import EventKit
class ToolTipVC: NSViewController, NSTableViewDataSource, NSTableViewDelegate {
@IBOutlet weak var ToolTipTable: NSTableView!
override func viewDidLoad() {
super.viewDidLoad()
ToolTipTable.delegate = self
ToolTipTable.dataSource = self
}
func numberOfRows(in tableView: NSTableView) -> Int {
return ReminderLists.count
}
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
guard let cell = tableView.makeView(withIdentifier: tableColumn!.identifier, owner: self) as? NSTableCellView else { return nil }
cell.textField?.stringValue = "Row #\(row): " + ReminderLists[row].title
return cell
}
}
extension ToolTipVC {
static func Controller() -> ToolTipVC {
let storyboard = NSStoryboard(name: "Main", bundle: nil)
let identifier = NSStoryboard.SceneIdentifier("ToolTipId")
guard let viewcontroller = storyboard.instantiateController(withIdentifier: identifier) as? ToolTipVC else {
fatalError("Why cant i find viewcontroller? - Check Main.storyboard")
}
return viewcontroller
}
}
感谢您的反馈和建议。 提前致谢!
P.S.: 我不是开发人员,我是产品经理。这是我的宠物项目,所以我知道我的代码很糟糕并且有很多错误。 请不要苛刻地评判我:)
乍一看,当您调用此行时:
popover.show(relativeTo: InputField.bounds, of: InputField!, preferredEdge: NSRectEdge.maxY)
preferredEdge 设置为 NSRectEdge.maxY
尝试将其从 Y 更改为 X
popover.show(relativeTo: InputField.bounds, of: InputField!, preferredEdge: NSRectEdge.maxX)
您使用 NSPopover 有什么原因吗?
如果这不起作用试试这个:
let controller = MyPopViewController()
controller.modalPresentationStyle = UIModalPresentationStyle.popover
let popController = controller.popoverPresentationController
popController?.permittedArrowDirections = .any
popController?.delegate = self
popController?.sourceRect = //set the frame here
popController?.sourceView = //set the source view here
self.present(controller, animated: true, completion: nil)
这是另一种方法,它会将弹出窗口置于按钮上方的中心。我假设没有向上箭头,你想做什么?那是对的吗? 所以你可以点击右侧的过滤器按钮,这个弹出窗口将显示在中心。
@IBAction func buttonTap(sender: UIButton) {
// get a reference to the view controller for the popover
let popController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "popoverId")
// set the presentation style
popController.modalPresentationStyle = UIModalPresentationStyle.popover
// set up the popover presentation controller
popController.popoverPresentationController?.permittedArrowDirections = UIPopoverArrowDirection.up
popController.popoverPresentationController?.delegate = self
popController.popoverPresentationController?.sourceView = sender // button
popController.popoverPresentationController?.sourceRect = sender.bounds
// present the popover
self.present(popController, animated: true, completion: nil)
}