NSSlider object crashes code when it's moved on view - nsslider

I've created an NSViewController with corresponding XIB in IB.
FWIW, I have the following window/view hierarchy:
class RxDemoController: NSWindowController {
#IBOutlet weak var statusPaneView: NSView!
#IBOutlet weak var annunciatorPaneView: NSView!
#IBOutlet weak var trigaStatusPaneView: NSView!
#IBOutlet weak var rxTabView: NSView!
override var windowNibName :String? { return "RxDemoController" }
override func windowDidLoad() {
super.windowDidLoad()
let statusPaneViewController = StatusPaneViewController()
statusPaneView.addSubview( statusPaneViewController.view )
let annunciatorPaneViewController = AnnunciatorPaneViewController()
annunciatorPaneView.addSubview( annunciatorPaneViewController.view )
let trigaStatusPaneController = TrigaStatusPaneController()
trigaStatusPaneView.addSubview( trigaStatusPaneController.view )
let rxTabController = RxTabController()
rxTabView.addSubview( rxTabController.view )
}
}
We can ignore the statesPaneViewController, annunciatorPaneViewController, and trigaStatusPaneController as they are all working properly. The rxTabController object is a tab view, defined in RXTabController.swift as follows:
class RxTabController: NSTabViewController {
#IBOutlet weak var rxDisplay1TabView: NSView!
override var nibName :String? { return "RxTabController" }
override func viewDidLoad() {
super.viewDidLoad()
let rxDisplay1ViewController = RxDisplay1()
rxDisplay1TabView.addSubview( rxDisplay1ViewController.view )
}
RxDisplay1.xib currently contains two objects: a bar graph object (custom component: LinearBarGraph_t which has been working fine in other projects and works fine on the view controller for the first tab), the second object is an NSSlider. The NSSlider is giving me problems. Here's the code for RxDisplay1:
class RxDisplay1: NSViewController {
#IBOutlet weak var linearPwrBG: LinearBarGraph_t!
override func viewDidLoad() {
super.viewDidLoad()
linearPwrBG.pctInRange = 50
}
#IBAction func linearPwrSlider(sender: NSSlider) {
}
}
I have right-dragged from the bar graph object to produce the #IBOutlet weak var linearPwrBG: LinearBarGraph_t! outlet; note that in viewDidLoad I set the pctInRange field to 50. This works fine when the app starts up (the bar graph is filled to the 50% mark).
The problem is with the slider. I've right dragged from the slider to the RxDisplay1 class to produce the linearPwrSlider action function. The connection seems to be fine (little filled dot next to the function declaration and right-clicking on the slider shows the action going to this function).
When I run the code, the display (and tab) properly appear. My bar graph shows 50% power. However, the moment I touch the slider with the mouse the system crashes. I get a break in AppDelegate complaining about "Bad Access".
I've used sliders all the time in past projects. However, this is the first time I've used a tabbed controller so I suspect there is something wrong with the way I've connected the tabbed controller to the rest of the system.

Related

jonkykong SideMenu presentationStyle stopped working after upgrade to 6.4.8

I am using the jonkykong SideMenu in a Swift 5 xcode project. The following code worked fine before 6.4.8.
import UIKit
import SideMenu
class SideMenuViewController: UITableViewController {
#IBOutlet weak var headerView: UIView!
#IBOutlet weak var driverNameLabel: UILabel!
#IBOutlet weak var vehicleRegoLabel: UILabel!
var menuItems = [Dictionary<String, String>]()
override func viewDidLoad() {
super.viewDidLoad()
// Config options for the Slide in side menu
SideMenuManager.default.leftMenuNavigationController?.presentationStyle = .menuSlideIn
SideMenuManager.default.leftMenuNavigationController?.presentationStyle.onTopShadowOpacity = 1
// hides the 1px bottom border on the nav bar so the header seemless merges to the navbar
self.navigationController?.navigationBar.setValue(true, forKey: "hidesShadow")
... rest of controller code
After upgrading to 6.4.8 the presentationStyle has no effect. The presentationStyle is always the default of viewSlideOut regardless of what I set in the above code.
I am unable to find anything in the README about changes to this in the latest version. Any assistance would be greatly appreciated.
Please set presentationStyle in SideMenuSettings and assign it to SideMenuNavigationController.
func makeSettings() -> SideMenuSettings{
var settings = SideMenuSettings()
settings.allowPushOfSameClassTwice = false
settings.presentationStyle = .menuSlideIn
settings.statusBarEndAlpha = 0
return settings
}
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let sideMenuNavigationController = segue.destination as? SideMenuNavigationController else { return }
sideMenuNavigationController.settings = makeSettings()
}

How to fix "cannot use instance member 'textField_1' within property initializer; property initializers run before 'self' is available"?

My compiler doesn't show any problems but at runtime, I get an unknown error. I'm trying to place textField string input into a double array. Not sure what is wrong can somebody please explain what I'm doing wrong.
Haven't really tried anything but I think I have to use lazy syntax somehow.
import UIKit
class ViewController: UIViewController {
// Outlets
// textFields
#IBOutlet weak var textField_1: UITextField!
#IBOutlet weak var textField_2: UITextField!
#IBOutlet weak var textField_3: UITextField!
#IBOutlet weak var textField_4: UITextField!
#IBOutlet weak var textField_5: UITextField!
// labels
#IBOutlet weak var label_1: UILabel!
#IBOutlet weak var label_2: UILabel!
#IBOutlet weak var label_3: UILabel!
#IBOutlet weak var label_4: UILabel!
#IBOutlet weak var label5: UILabel!
// Variables
var input : String = "0";
var a = 0
var age = "9.5"
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
var numbers : [Double] = [90, 0, 0, 0, 0]; // where textfields will be converted to double
var userinput : [String?] = [textField_1.text, textField_2.text, textField_3.text, textField_4.text, textField_5.text]!; // textField storage
// Button
#IBAction func button ()
{
// loop inserts userinput into numbers array
while (a < 3) {
numbers.insert(convert_to_double(input1: userinput[a]!) ,at: a)// inserts userinput after
a += 1 // stops loop and changes array index
}
}
// converts strings to double
func convert_to_double(input1: String) -> Double
{
let input0 : Double? = Double(input1);
return input0!
}
}
:0: error: cannot use instance member 'textField_1' within property initializer; property initializers run before 'self' is availableenter image description here
You are trying to access the user's input with an index value. Creating an array of text input values has two problems:
In your case, you can't create this array with a property initializer because self is not available until after the class has been fully initialized.
Creating an array of the user inputs will be static and won't show the latest values of the UITextFields if the user updates one before pressing the button.
You can handle this in one of two ways.
Use a computed property:
If you turn userinput into a computed property, then it will always return an array with the latest values:
var userinput : [String?] { return [textField_1.text, textField_2.text, textField_3.text, textField_4.text, textField_5.text] }
The downside is that every access of userinput will recreate this array which is a bit inefficient, but it ensures the array contains the latest values. You can assign this to a local variable at the top of button to avoid recreating the array in the loop:
#IBAction func button ()
{
let userinput = self.userinput
// loop inserts userinput into numbers array
while (a < 3) {
numbers.insert(convert_to_double(input1: userinput[a]!) ,at: a)// inserts userinput after
a += 1 // stops loop and changes array index
}
}
Create a lazy var of the UITextFields:
Create a lazy array of the textFields. This array will be created the first time it is accessed, but since it contains objects, you will always have access to the latest input values from the user.
lazy var textFields = [textField_1!, textField_2!, textField_3!, textField_4!, textField_5!]
and then change your button loop to use textFields[a].text! instead of userinput[a]!:
#IBAction func button ()
{
// loop inserts userinput into numbers array
while (a < 3) {
numbers.insert(convert_to_double(input1: textFields[a].text!) ,at: a)// inserts userinput after
a += 1 // stops loop and changes array index
}
}

manual constraints not being cuasin unwrapping issue (swift4)

My code below is causing a run time error. This works If I code a lazy var as a scrollview. But this does not work if I am just trying to add a object to the view or superview. I have connected nothing from the storyboard and do not want to.
var FIRE: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
playSound()
view.addSubview(FIRE)
FIRE.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
FIRE.topAnchor.constraint(equalTo: view.topAnchor, constant: 20).isActive = true
FIRE.widthAnchor.constraint(equalToConstant: 400).isActive = true
FIRE.heightAnchor.constraint(equalToConstant: 80).isActive = true
}
Change
var FIRE: UIImageView!
To
let FIRE = UIImageView()

Configuring WKInterfaceTable row controller at load time

I'm doing most of my watch app UI in code and would like to configure row controller's IB properties at load time, before I access it with rowController(at:).
Is there an easy way to do it? All IB properties are nil at init(), and awakeFromNib() is not available for NSObject in WatchKit.
Your IBOutlets must be already bound to your custom table row class which is used in your Interface storyboard. In the custom row class you can update the interface controls by setting the object keeping the information to display.
class TableMainCellType: NSObject {
#IBOutlet weak var label:WKInterfaceLabel!
#IBOutlet weak var group:WKInterfaceGroup!
var item:MyTableItem? {
didSet{
label.setText(item?.title)
group.setBackgroundColor(item?.color)
}
}
}
To update the table cells I would iterate in the function to update the table view in the InterfaceController like below.
// ...
for index in tableItems.indices{
if let row = self.table.rowController(at: index) as? TableMainCellType {
let item = tableItems[index]
row.item = item
}
}
// ...

Share data in paged based interface in Watchkit

I need to share a string with all the pages from the first page.
I was trying to do this with didDeactive() but its not working.
Is it possible to even do this?
It's a bit difficult to tell what you are really trying to do, so I'm going to infer a bit. I "think" you are trying to set some shared value from the first page and be able to use that value in other pages. If that's the case, then you could do something like the following:
class SharedData {
var value1 = "some initial value"
var value2 = "some other initial value"
class var sharedInstance: SharedData {
struct Singleton { static let instance = SharedData() }
return Singleton.instance
}
private init() {
// No-op
}
}
class Page1InterfaceController: WKInterfaceController {
func buttonTapped() {
SharedData.sharedInstance.value1 = "Something new that the others care about"
}
}
class Page2InterfaceController: WKInterfaceController {
#IBOutlet var label: WKInterfaceLabel!
override func willActivate() {
super.willActivate()
self.label.setText(SharedData.sharedInstance.value1)
}
}
The SharedData object is a singleton class that is a global object. Anyone can access it from anywhere. In the small example I provided, the Page1InterfaceController is handling a buttonTapped event and changing the value property of the SharedData instance to a new value. Then, when swiping to Page2InterfaceController, the new value is being displayed in label.
This is a super simple example of sharing data between objects. Hopefully that helps get you moving in the right direction.

Resources