Delegate is not being set - delegates

I have a class Document (subclass of NSDocument) with a property (called documentString) which, when changed, should call it's delegate. In my case, the delegate is a ViewController. Though the delegate is being set in the ViewController, it appears to be nil and the function with which the ViewController should respond is not being called
This is the property whose change should be reported to the delegate(always prints "no").
var documentString: String {
didSet {
if self.delegate != nil {
self.delegate?.documentContentDidChange()
} else {
println("no")
}
}
}
This is the ViewController.
class ViewController: NSViewController, DocumentDelegate {
#IBOutlet var codeView: NSTextView!
var code: Document = Document()
override func viewDidLoad() {
super.viewDidLoad()
self.code.delegate = self
self.updateUI()
}
func documentContentDidChange() {
self.updateUI()
}
func updateUI() {
self.codeView.string = self.code.documentString
}
}
What am I doing wrong?
EDIT: I added println("no1") after self.code.delegate = self. no gets printed before no1. So it means that delegate is not being set when documentString is changed. But then, updateUI should work properly with codeView displaying the text in documentString. However, codeView remains blank.

Related

InputAccessoryView not removed

I'm making an iOS app, in which i use the inputaccessoryview to the UIViewController,
the problem is
Controller A
class ControllerA: UIViewController {
override var inputAccessoryView: UIView? {
return saveView
}
override var canBecomeFirstResponder: Bool {
return true
}
#IBAction func openVCB(_ sender: UIButton) {
let controllerB = controllerB.instantiate(fromAppStoryboard: .main)
let navigationController = UINavigationController(rootViewController: controllerB)
navigationController.navigationBar.isTranslucent = false
self.present(navigationController, animated: true)
}
}
Controller B
class ControllerB: UIViewController {
override var inputAccessoryView: UIView? {
return nil
}
override var canBecomeFirstResponder: Bool {
return false
}
}
in the controller A the view is working as expected, but in controller B if i opened a keyboard and closed it the AccossoryView it will be visible, and it supposed not to be visible, any ideas?
Full Project InpoutViewTest
Follow this approach:
var shouldBecomeFirstResponder:Bool = false
override var canBecomeFirstResponder: Bool {
return shouldBecomeFirstResponder
}
and don't forget to set this flag to false in viewWillDisappear as well
shouldBecomeFirstResponder = false
I've run into this problem too. Try putting this in your viewWillDisappear(_ animated: Bool) function:
override func viewWillDisappear(_ animated: Bool) {
if let myInputAccessoryView = saveView {
myInputAccessoryView.removeFromSuperview()
}
}
It should remove the input accessory view before transitioning to controller B. Just remember to add the input accessory view back when returning to controller A. You could also try myInputAccessoryView.isHidden = true instead of removeFromSuperview() if you prefer.

Obtaining a View Controller Reference

I read quite a few questions and answers no this problem. Some are for Ojective C. Some are for iOS. The ones that were close to what I need didn't work.
I've set up a protocol for delegation. It doesn't work. The problem is that delegate variable isn't set. I need the reference to an active controller.
Delegator
protocol SwitchTabDelegate: class {
func selectTab(tab: Int)
}
class ViewController: NSViewController {
weak var delegate: SwitchTabDelegate?
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func selectCompositions(_ sender: NSButton) {
if let delegate = self.delegate {
delegate.selectTab(tab: 2)
}
else {
print("self.delegate is nil")
}
print("delegate called")
}
}
Delegatee
class TabViewController: NSTabViewController, SwitchTabDelegate {
var viewController : ViewController?;
override func viewDidLoad() {
super.viewDidLoad()
//viewController = storyboard?.instantiateController(withIdentifier: "viewController") as? ViewController
// viewController?.delegate = self
// print(viewController)
}
func selectTab(tab: Int) {
print("In the delegate")
switchToDataTab()
}
func switchToDataTab() {
Timer.scheduledTimer(timeInterval: 0.2, target: self,
selector: #selector(switchToDataTabCont),
userInfo: nil, repeats: false)
}
func switchToDataTabCont(){
self.selectedTabViewItemIndex = 2
}
}
The delegatee is the main NSViewContoller. On the storyboard, it contains two buttons and a Container view controller. Embedded in the container view controller is the TabViewController, the delegatee. You can see in the delegatee where I tried to get a reference. It does get a reference, presumably to the newly instantiated instance. I need a reference to the original view controller that was spun up when the application started.
Answer
I added the following code to the delegator:
override func prepare(for segue: NSStoryboardSegue, sender: Any?) {
let controller = segue.destinationController as! TabViewController
self.delegate = controller as SwitchTabDelegate
}
That's not how it should work following the design pattern. The delegator should have no knowledge of the delegatee. I've spent way too much time on this issue so a hack is going to do.
When using storyboards, you want to "push" references to children when they are created vs. pulling them from an upstream controller. This is what -prepareForSegue:sender: is used for.

Losing reference to NSWindows in AppDelegate

I'm running into issues where I lose reference to NSWindows that are declared in AppDelegate, with the code below.
class AppDelegate: NSObject, NSApplicationDelegate {
var window1: CustomWindow1!
var window2: CustomWindow2!
func setupWindows() {
self.window1 = CustomWindow1()
self.window2 = CustomWindow2()
let vc2 = VIEWOFSOMEVIEWCONTROLLER()
self.window2.contentView.addSubview(vc2.view)
self.window1.grandchildVC = vc2
self.window1.addChildWindow(self.window2!, ordered: NSWindowOrderingMode.Above)
// etc.
}
#IBAction addWindowsAgain(sender: AnyObject) {
// This is where if fails
if self.window1 != nil {
self.window1 == nil
}
}
}
class CustomWindow1() {
var grandchildVC: NSViewController
func deleteChildWindowThenSelf() {
self.grandchildVC.view.window.close()
self.close()
}
}
I am able to call deleteChildWindowThenSelf(), and get rid of the windows as expected, but when calling addWindowsAgain in AppDelegate, if fails with lldb error. Does AppDelegate lose those window vars when close is called, or am I misunderstanding something?
NSWindow has a variable releasedWhenClosed which is true by default for custom created windows unless the window is owned by a window controller.
Set the variable to false.

Label is nil in custom controller class

// This is in ViewController.swift
import Cocoa
class ViewController: NSViewController {
#IBOutlet weak var oneLabel: NSTextField!
override func viewDidLoad() {
super.viewDidLoad()
oneLabel.stringValue = "All is well" // Here it works
//...
}
}
// Separate Swift code file
import Cocoa
import Foundation
var si = Simulate()
class Simulate: NSViewController {
#IBOutlet weak var aLabel: NSTextField!
func simulationManager() -> Bool {
var ni: Int
var breakPoint = false
rd.simStatus = .Running
do {
if rd.rchIndex >= ld.NodeCount(.Reach) {
if InterStepConvergence() {
NextTimeStep()
if aLabel != nil { // This is always false
aLabel.stringValue = String(rd.elapsedSec)
}
else {
println("Label is nil")
}
//...
}
}
}
}
}
I am trying to set up a custom controller to update the interface while a
simulation is running. I need to show the status of the simulation. The simulation runs in a separate thread, but even if I do it in the main thread, same problem as described below.
The label text can be changed if I do it in the ViewController class as above.
But if I try to modify the text on the label in the Simulate class the label
is always nil and so it doesn't work. But the code compiles OK. What am I missing here such that the label is always nil in the Simulate class? Thanks much, in advance.

Xcode Swift: How to call UIPickerView from UIButton?

I need to open UIPickerView once a user touch a UIButton and to return the text value choosen on UIPickerview to UIButton label.
I'm not able to change the UIButton'n inputview like for UITextField, so making the property writable seems to be the right way. Unfortunatelly nothing happens when the button is touched.
import UIKit
class ABButton: UIButton {
var modInputView: UIView!
override var inputView: UIView { get {
if modInputView != nil {
return modInputView
}
else {
return super.inputView!
}
}}
override func canBecomeFirstResponder() -> Bool {
return true
}
}
class LiczydloViewController: UIViewController {
#IBOutlet weak var buttonTempo10: ABButton!
override func viewDidLoad() {
super.viewDidLoad()
var tempoPicker = UIDatePicker()
buttonTempo10.modInputView = tempoPicker
}
Add an action for touchUpInside for the button, and call button.becomeFirstResponder()
try to set the frame of UIDatePicker. I tried it with luck.
class ZYInputButton: UIButton {
var zyInputView: UIView?
var zyInputAccessoryView: UIView?
override var inputView: UIView? {
get {
return self.zyInputView
}
set {
self.zyInputView = newValue
}
}
override var inputAccessoryView: UIView? {
get {
return self.zyInputAccessoryView
}
set {
self.zyInputAccessoryView = newValue
}
}
override func canBecomeFirstResponder() -> Bool {
return true
}
}

Resources