如何将值从 NSViewController 传递到 NSPopover 的自定义 NSView?
How to pass value from NSViewController to custom NSView of NSPopover?
通过使用委托协议,我尝试将字符串 (inputFromUser.string) 从 NSViewController - mainController 传递给自定义NSPopover 的 NSView 的子类 - PlasmidMapView,到 drawRect 函数,见下面的代码。但是,它没有用。我不知道错误在哪里。也许还有另一种方法可以传递这个字符串。
更新
文件 1.
protocol PlasmidMapDelegate {
func giveDataForPLasmidMap(dna: String)
}
class MainController: NSViewController {
@IBOutlet var inputFromUser: NSTextView!
var delegate: plasmidMapDelegate?
@IBAction func actionPopoverPlasmidMap(sender: AnyObject) {
popoverPlasmidMap.showRelativeToRect(sender.bounds,
ofView: sender as! NSView, preferredEdge: NSRectEdge.MinY)
let dna = inputDnaFromUser.string
delegate?.giveDataForPLasmidMap(dna!)
}
}
文件 2
class PlasmidMapView: NSView, PlasmidMapDelegate {
var dnaForMap = String()
func giveDataForPLasmidMap(dna: String) {
dnaForMap = dna
}
override func drawRect(dirtyRect: NSRect) {
let objectOfMainController = MainController()
objectOfMainController.delegate = self
//here I have checked if the string dnaForMap is passed
let lengthOfString = CGFloat(dnaForMap.characters.count / 10)
let pathRect = NSInsetRect(self.bounds, 10, 45)
let path = NSBezierPath(roundedRect: pathRect,
xRadius: 5, yRadius: 5)
path.lineWidth = lengthOfString //the thickness of the line should vary in dependence on the number of typed letter in the NSTextView window - inputDnaFromUser
NSColor.lightGrayColor().setStroke()
path.stroke()
}
}
为了使用委托,您的 class PlasmidMapView 需要有一个 MainController 的实例(顺便说一下,名称约定是Class,而不是 class) 并符合 PlasmidMapDelegate(再次命名约定规定它应该是 PlasmidMapDelegate)。使用该实例,您可以:
mainController.delegate = self
好的,存在一些架构错误。您根本不需要委托方法和协议。您只需要定义明确的 setter 方法:
我。将你的 PlasmidMapView
放入 NSViewController
-subclass。此视图控制器必须设置为 NSPopover
-control 的 contentViewController
-属性。不要忘记在 viewDidLoad
方法或其他方法中按照您需要的方式进行设置。
class PlasmidMapController : NSViewController {
weak var mapView: PlacmidMapView!
}
二.在你的 PlacmidMapView
中,不要忘记在 dna
上调用 needsDisplay
方法 did set:
class PlasmidMapView: NSView {
//...
var dnaForMap = String() {
didSet {
needsDisplay()
}
//...
}
三。在需要时从 MainController
-class 设置 dna
-string。
@IBAction func actionPopoverPlasmidMap(sender: AnyObject) {
popoverPlasmidMap.showRelativeToRect(sender.bounds,
ofView: sender as! NSView, preferredEdge: NSRectEdge.MinY)
let dna = inputDnaFromUser.string
if let controller = popoverPlasmidMap.contentViewController as? PlasmidMapController {
controller.mapView.dna = dna
} else {
fatalError("Invalid popover content view controller")
}
}
所以,几天后,我找到了一个解决方案,没有任何协议和授权,正如 Astoria 提到的那样。我需要做的就是在 MainController class 中为我的自定义 NSView 创建 @IBOutlet var plasmidMapIBOutlet: PlasmidMapView!
,然后使用它来设置 dnaForMap 在 @IBAction func actionPopoverPlasmidMap(sender: AnyObject)
。
class PlasmidMapView: NSView
{
var dnaForMap = String()
}
class MainController: NSViewController
{
@IBOutlet var inputFromUser: NSTextView!
@IBOutlet var plasmidMapIBOutlet: PlasmidMapView!
@IBAction func actionPopoverPlasmidMap(sender: AnyObject)
{
plasmidMapIBOutlet.dnaForMap = inputDnaFromUser.string!
popoverPlasmidMap.showRelativeToRect(sender.bounds,
ofView: sender as! NSView, preferredEdge: NSRectEdge.MinY)
}
}
通过使用委托协议,我尝试将字符串 (inputFromUser.string) 从 NSViewController - mainController 传递给自定义NSPopover 的 NSView 的子类 - PlasmidMapView,到 drawRect 函数,见下面的代码。但是,它没有用。我不知道错误在哪里。也许还有另一种方法可以传递这个字符串。
更新
文件 1.
protocol PlasmidMapDelegate {
func giveDataForPLasmidMap(dna: String)
}
class MainController: NSViewController {
@IBOutlet var inputFromUser: NSTextView!
var delegate: plasmidMapDelegate?
@IBAction func actionPopoverPlasmidMap(sender: AnyObject) {
popoverPlasmidMap.showRelativeToRect(sender.bounds,
ofView: sender as! NSView, preferredEdge: NSRectEdge.MinY)
let dna = inputDnaFromUser.string
delegate?.giveDataForPLasmidMap(dna!)
}
}
文件 2
class PlasmidMapView: NSView, PlasmidMapDelegate {
var dnaForMap = String()
func giveDataForPLasmidMap(dna: String) {
dnaForMap = dna
}
override func drawRect(dirtyRect: NSRect) {
let objectOfMainController = MainController()
objectOfMainController.delegate = self
//here I have checked if the string dnaForMap is passed
let lengthOfString = CGFloat(dnaForMap.characters.count / 10)
let pathRect = NSInsetRect(self.bounds, 10, 45)
let path = NSBezierPath(roundedRect: pathRect,
xRadius: 5, yRadius: 5)
path.lineWidth = lengthOfString //the thickness of the line should vary in dependence on the number of typed letter in the NSTextView window - inputDnaFromUser
NSColor.lightGrayColor().setStroke()
path.stroke()
}
}
为了使用委托,您的 class PlasmidMapView 需要有一个 MainController 的实例(顺便说一下,名称约定是Class,而不是 class) 并符合 PlasmidMapDelegate(再次命名约定规定它应该是 PlasmidMapDelegate)。使用该实例,您可以:
mainController.delegate = self
好的,存在一些架构错误。您根本不需要委托方法和协议。您只需要定义明确的 setter 方法:
我。将你的 PlasmidMapView
放入 NSViewController
-subclass。此视图控制器必须设置为 NSPopover
-control 的 contentViewController
-属性。不要忘记在 viewDidLoad
方法或其他方法中按照您需要的方式进行设置。
class PlasmidMapController : NSViewController {
weak var mapView: PlacmidMapView!
}
二.在你的 PlacmidMapView
中,不要忘记在 dna
上调用 needsDisplay
方法 did set:
class PlasmidMapView: NSView {
//...
var dnaForMap = String() {
didSet {
needsDisplay()
}
//...
}
三。在需要时从 MainController
-class 设置 dna
-string。
@IBAction func actionPopoverPlasmidMap(sender: AnyObject) {
popoverPlasmidMap.showRelativeToRect(sender.bounds,
ofView: sender as! NSView, preferredEdge: NSRectEdge.MinY)
let dna = inputDnaFromUser.string
if let controller = popoverPlasmidMap.contentViewController as? PlasmidMapController {
controller.mapView.dna = dna
} else {
fatalError("Invalid popover content view controller")
}
}
所以,几天后,我找到了一个解决方案,没有任何协议和授权,正如 Astoria 提到的那样。我需要做的就是在 MainController class 中为我的自定义 NSView 创建 @IBOutlet var plasmidMapIBOutlet: PlasmidMapView!
,然后使用它来设置 dnaForMap 在 @IBAction func actionPopoverPlasmidMap(sender: AnyObject)
。
class PlasmidMapView: NSView
{
var dnaForMap = String()
}
class MainController: NSViewController
{
@IBOutlet var inputFromUser: NSTextView!
@IBOutlet var plasmidMapIBOutlet: PlasmidMapView!
@IBAction func actionPopoverPlasmidMap(sender: AnyObject)
{
plasmidMapIBOutlet.dnaForMap = inputDnaFromUser.string!
popoverPlasmidMap.showRelativeToRect(sender.bounds,
ofView: sender as! NSView, preferredEdge: NSRectEdge.MinY)
}
}