Как передать значение из NSViewController в пользовательский NSView NSPopover?

Используя протокол делегирования, я попытался передать строку (inputFromUser.string) из NSViewController — mainController в пользовательский подкласс NSView из NSPopover — 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()
    }
 }

person VYT    schedule 13.05.2016    source источник


Ответы (3)


Хорошо, есть некоторые архитектурные ошибки. Вам вообще не нужен метод делегата и протокол. Все, что вам нужно, это четко определенный метод установки:

I. Поместите свой PlasmidMapView в NSViewController-подкласс. Этот контроллер представления должен быть установлен как contentViewController-свойство вашего NSPopover-элемента управления. Не забудьте установить его так, как вам нужно в viewDidLoad-методе или другом.

class PlasmidMapController : NSViewController {
    weak var mapView: PlacmidMapView!
}

II. В вашем PlacmidMapView не забудьте вызвать needsDisplay-метод на dna, установленном:

class PlasmidMapView: NSView {
    //...
    var dnaForMap = String() {
        didSet {
            needsDisplay()
        }
    //...
}

III. Установите dna-строку, когда вам нужно, из вашего MainController-класса.

@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")
     }
}
person Daniyar    schedule 17.05.2016
comment
Непонятно одно для (я новичок) - не забудьте установить так, как вам нужно в viewDidLoad-методе или другом. Могли бы вы объяснить? - person VYT; 17.05.2016
comment
@VYT вам нужно инициализировать объект mapView, добавить в представление NSViewController, возможно, установить ограничения автомакета и т. д. - person Daniyar; 17.05.2016
comment
Ну наконец то!!! Я поиграл с тем, что вы предложили, и нашел простое решение. Это не совсем то, что вы предложили, но вы дали мне идею, и я даю вам награду. Спасибо еще раз! - person VYT; 17.05.2016
comment
@VYT, если мой ответ помог вам проверить его правильность, пожалуйста. - person Daniyar; 23.09.2016

Чтобы использовать делегирование, ваш класс PlasmidMapView должен иметь экземпляр MainController (кстати, соглашение об именах — это класс, а не класс) и соответствовать PlasmidMapDelegate. strong> (еще раз соглашение об именах диктует, что это должен быть PlasmidMapDelegate). С этим экземпляром вы можете:

mainController.delegate = self

person Diogo Antunes    schedule 13.05.2016
comment
Если я помещу mainController.delegate = self в класс PlasmidMapView, у меня будет жалоба - Ожидаемая декларация. - person VYT; 13.05.2016
comment
Является ли PlasmidMapView подвидом MainController? - person Diogo Antunes; 13.05.2016
comment
Нет, это NSView из NSPopover - person VYT; 13.05.2016

Итак, через несколько дней я нашел решение без каких-либо протоколов и делегирования, как упомянула Астория. Все, что мне нужно было сделать, это создать @IBOutlet var plasmidMapIBOutlet: PlasmidMapView!для моего пользовательского NSView в классе MainController, а затем использовать его для установки значения для 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)         
    }
}
person VYT    schedule 17.05.2016