2017-11-27 32 views
0

Mac 응용 프로그램을 수행하고 다른 클래스의 함수를 호출 할 때 NSScrollView에 텍스트를 추가하는 데 문제가 있습니다. 내가 사용하고 팝 오버에 클래스 인 PopoverVC1 클래스가보다NSScrollView에 텍스트 추가 - 치명적인 오류 : 선택적 값을 래핑하는 동안 예기치 않게 nil이 발견되었습니다.

import Cocoa 

class PopoverVC1: NSViewController { 

let popover1 = NSPopover() 

class func loadView() ->PopoverVC1 { 
    let vc = NSStoryboard(name: NSStoryboard.Name(rawValue: "Main"), 
bundle: nil).instantiateController(withIdentifier: 
NSStoryboard.SceneIdentifier(rawValue: "Popover1")) as! PopoverVC1 
    vc.popover1.contentViewController = vc 
    return vc 
} 

override func viewDidLoad() { 
    super.viewDidLoad() 

    popover1.behavior = .transient 
    popover1.contentViewController = self 
} 

func showPopover (view: NSView){ 
popover1.show(relativeTo: view.bounds, of: view, preferredEdge: .maxY) 

} 

@IBOutlet weak var radioOption1: NSButton! 
@IBOutlet weak var radioOption2: NSButton! 
@IBOutlet weak var radioOption3: NSButton! 


@IBAction func clickOption(_ sender: NSButton) { 
    switch sender { 
    case radioOption1: popover1.performClose(sender) 

    case radioOption2: let vc = ViewController() 
     vc.myPrint(string: "This is a test") 

    default: print ("hello") 

    } 
} 
} 

: 그러나

import Cocoa 

class ViewController: NSViewController { 


@IBOutlet weak var oneYes: NSButton! 
@IBOutlet weak var oneNo: NSButton! 
@IBOutlet weak var notesArea: NSScrollView! 


override func viewDidLoad() { 
    super.viewDidLoad() 
    // Do any additional setup after loading the view. 

} 

override var representedObject: Any? { 
    didSet { 
    // Update the view, if already loaded 
    } 
} 

func myPrint (string: String){ 
    let mystring = string 
    let myNotes = notesArea.documentView as? NSTextView 
    let text = myNotes?.textStorage! 
    let attr = NSAttributedString(string: mystring) 
    text?.append(attr) 

} 

let popover1 = NSPopover() 
@IBAction func oneClicked(_ sender: NSButton) { 


    switch sender { 
    case oneYes: let vc = PopoverVC1.loadView() 
     vc.showPopover(view: sender) 

    case oneNo: 
    let myNotes = notesArea.documentView as? NSTextView 
    let text = myNotes?.textStorage! 
    let attr = NSAttributedString(string: "test") 
    text?.append(attr) 

    default: print ("") 
    } 
} 
} 

를, 내가있어

내의 ViewController 클래스에이 기능이 "myPrint"함수를 호출하고 인수를 전달해야하는 라디오 버튼 "oneNo"를 누르면 오류가 발생합니다.

스레드 1 : 치명적인 오류 : 예기치 않게 나는 몇 가지 테스트를했고, 나는 ViewCotroller 클래스 내에서이 같은 기능 "myPrint"를 호출 할 때 잘 작동하는 옵션 값을

을 풀기 동안 nil을 발견했다.

아이디어가 있으십니까? 당신이 호출 할 때

+1

vc 및 notesArea는 어디에 생성됩니까? –

+1

'notesArea'는 사용할 때 nil이어야합니다. – Ryan

+0

안녕하세요 @ 라이언, 내게 모범을 보여 주겠니? 나는 신속 해지기 쉽다 : ( – Caico

답변

1

귀하의 문제는 clickOption에 있습니다

let vc = ViewController() 
vc.myPrint(string: "This is a test") 

이 코드에서 방법과 ViewController'sUIViews이 스토리 보드에 설정되어 전화

는, 스토리 보드에서 연결이되지 않습니다. 따라서 myPrint 함수를 호출 할 때 notesArea이 nil 인 이유입니다. 이 경우 ViewController의 새 복사본을 만들므로 팝업을 만든 동일한 복사본이 아닙니다.

달성하려는 문제를 해결할 수있는 몇 가지 방법이 있습니다. 그 중 하나는 delegate으로 알려져 있습니다. 이렇게하면 popover과 같은 방법으로 ViewController's 개의 메소드를 상속받을 수 있습니다. 자습서 here을 확인할 수 있습니다. Google의 popoverViewController에 대한 참조가 있으므로 의 기능을 호출 할 수 있습니다. 그런 다음 에 부합하는 ViewController이 메소드 호출을 처리합니다.

PrintableDelegate이라는 을 만들고 ViewController 클래스를 준수하도록합시다. 그런 다음 popoverViewController에 대한 참조가 delegateweak var (원하는 이름을 사용할 수 있지만 delegate은 표준)으로 참조 할 수 있습니다. 그런 다음 PrintableDelegate 프로토콜에 설명 된 방법을 delegate?.myPrint(string: "Test")으로 간단하게 작성하여 호출 할 수 있습니다. 제 예제에서 당신의 무관 한 코드 일부를 제거했습니다.

protocol PrintableDelegate { 
    func myPrint(string: String) 
} 

class ViewController : UIViewController, PrintableDelegate { 

    func myPrint (string: String){ 
     let mystring = string 
     let myNotes = notesArea.documentView as? NSTextView 
     let text = myNotes?.textStorage! 
     let attr = NSAttributedString(string: mystring) 
     text?.append(attr) 
    } 

    @IBAction func oneClicked(_ sender: NSButton) { 
     let vc = PopoverVC1.loadView() 
     // Set the delegate of the popover to this ViewController 
     vc.delegate = self 
     vc.showPopover(view: sender) 
    } 
} 

class PopoverVC1: NSViewController { 

    // Delegates should be weak to avoid a retain cycle 
    weak var delegate: PrintableDelegate? 

    @IBAction func clickOption(_ sender: NSButton) { 
     // Use the delegate that was set by the ViewController 
     // Note that it is optional so if it was not set, then this will do nothing 
     delegate?.myPrint(string: "This is a test") 
    } 
} 
+0

Brillant Allen! 3 일 후에 해결책을 찾고 마침내 성공했습니다! 고마워. 또한 설명해 주셔서 감사합니다! – Caico