Swift NSViewController - macos

I'm new to cococa and swift, and I'm tring to create a custom ViewController.
class StatusUpdate : NSViewController {
#IBOutlet var StatusView: NSView!
#IBOutlet var eventsFoundCell: NSTextFieldCell!
#IBAction func update(sender: AnyObject) {
StatusView.hidden = false
eventsFoundCell.stringValue = "A"
}
}
The code as shown above is working as you would expect it.
But what I tring to do is to add an other function to that class like :
func otherUpdate() {
eventsFoundCell.stringValue = "B"
}
In order to update the stringValue of the eventsFoundCell variable.
So I could call it in an other class :
var update = StatusUpdate()
update.otherUpadte()
When calling update.otherUpadte() with in n other class,
I'm always getting an error like :
Thread1: EXC_BAD_INSTRUCTION(code=EXC_1386_INVOP, subcode=0x0)
fatal error: unexpectedly found nil while unwrapping an Optional value
(lldb)
Any idea on show I could do this ?
Thank you !

It is because in this line
var update = StatusUpdate()
You are creating a new instance of StatusUpdate. The variable StatusView is not bound to any NSView

You already got the answer, so this is recommendation only. It will make your Cocoa life way easier if you follow well established conventions. So, instead of:
#IBOutlet var StatusView: NSView!
you should write
#IBOutlet var statusView: NSView!
There are many cases in Cocoa where proper capitalisation (and style in general) are assumed in order for the frameworks to work.

Related

"Initialization of immutable value never used" but is actually used

I keep getting this error of value is never used. I understand this error pops up with Swift 2.2 often, and it is because the value that is initialized is not used. BUT, I do use this value, and this error pops up 3 other times on errors that I do use and I don't know why I still get it.
Below is the code. "Difficulty" is he variable that the compiler says is not used, but as you can see from my code, it is in fact used. Anyone know why this happens?
class SettingsController: UIViewController {
// MARK: Properties
// Preferences for difficulty level of questions
let preferences = NSUserDefaults.standardUserDefaults()
let difficultyKey = "Difficulty"
let questionnumKey = "QuestionNum"
var difficulty: String = "EASY"
#IBOutlet weak var Easy: DLRadioButton!
#IBOutlet weak var Medium: DLRadioButton!
#IBOutlet weak var Hard: DLRadioButton!
override func viewDidLoad() {
super.viewDidLoad()
readUserDefaults()
setDifficulty()
}
func readUserDefaults(){
let difficulty = preferences.stringForKey(difficultyKey) // <--Error
}
func setDifficulty(){
if difficulty == "HARD"{
Hard.selected = true
}
else if difficulty == "MEDIUM"{
Medium.selected = true
}
else{
Easy.selected = true
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
In readUserDefaults() it should be
difficulty = preferences.stringForKey(difficultyKey)
You need to remove the let: you already have created the difficulty variable earlier.
You also need to use ??, the "nil coalescing operator": preferences.stringForKey(difficultyKey) ?? "EASY", for example, to give a value even if the method call returns nil.
Note: answer made from the comments by #eric-d and #leo-dabus.

Accessing a content of an IBOutlet from another class

My question is simple , I have an IBoutlet(of a label) declared in a class , I need to change it content from another class , is that possible ?
edit : The view of the IBoutlet is loaded in the other class through a scroll view
the first class :
var historyVariable = ""
class FirstViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// here a code to set a value to historyVariable when button pressed
Text().call()
}
}
the second class
class Text: UIViewController {
#IBOutlet var History: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
func call() {
History.text = "\(historyVariable)"
}
}
it gives me an error unexpectedly found nil while unwrapping an Optional value when trying to set the text to the History label
Assuming text() is actually Text(), that would create a new, empty Text object. Since it's not part of the controller hierarchy, its view and other outlets aren't loaded at the time you invoke call().
You either need to instantiate the Text controller from a storyboard (or otherwise) and present it so that it's properly initialized or else use one that's already active...if that's your intent.

PFLoginViewController´s Twitter, Facebook buttons not working when subclassing

When I subclass PFLoginViewController from Parse so that I can customise UI, both Twitter and Facebook buttons stop working as they used to if I were not subclassing.
This is the class I instantiate my subclass from:
class SettingsViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, PFLogInViewControllerDelegate, PFSignUpViewControllerDelegate, MFMailComposeViewControllerDelegate
{
#IBOutlet weak var loadingIndicator: UIActivityIndicatorView!
#IBOutlet weak var tableView: UITableView!
// THIS DOES WORK (without subclassing)
//var loginVC: PFLogInViewController = PFLogInViewController()
var loginVC:LogInViewController {
get{
let livc = LogInViewController()
livc.delegate = self
let suvc = SignUpViewController()
suvc.delegate = self
livc.signUpController? = suvc
return livc
}}
And this is my subclass of PFLogInViewController
class LogInViewController: PFLogInViewController {
static let forgotPassword = "Trouble Signing In?"
override func viewDidLoad() {
super.viewDidLoad()
let lv = self.logInView
self.facebookPermissions = ["public_profile", "email"]
self.fields = [PFLogInFields.UsernameAndPassword, .Facebook, .Twitter, .SignUpButton, .LogInButton, .PasswordForgotten, .DismissButton]
lv?.logo = UIImageView(image: UIImage(named: "myImage"))
lv?.logo?.contentMode = UIViewContentMode.ScaleAspectFit
lv?.emailAsUsername = true
self.view.backgroundColor = UIColor.whiteColor()
}
It might be a bug in Parse´s side, though. Any help would be appreciated!
This is a known issue - it looks like this bug was patched in the GitHub repo (see this commit) but not in the Cocoapod, if that's what you're using. I'm hoping they'll push the changes over soon :)
The reason for the bug in the old code is that the superclass is not updating the target/actions for the buttons when you set which fields you want in viewDidLoad. PFLoginViewController configures the target/actions in its viewDidLoad, but since you're setting the self.fields after calling super.viewDidLoad (which is what you should be doing, since you always call super first :) ), the field target/actions aren't re-updated. In other words, it looks like, the way PFLogInViewController was written, it only works if the fields don't change after its viewDidLoad is called :/. And since the default fields don't include a Facebook button, the Facebook button will never be set up. A simple solution is just to move self.fields =... before super.viewDidLoad().

(NSMenuItem): missing setter or instance variable

I am encountering a strange error:
2015-04-02 12:20:14.642 test[21167:257788] Failed to connect
(testApp) outlet from (test.AppDelegate) to (NSMenuItem): missing
setter or instance variable
inserted id: 122
I occured when a added a menuItem to a menu and connected a function to it.
I do not know what the Problem is. The app works fine but i don't think it is a smart idea to ignore the error.
What is meant by setter or instance variable? Why is it needed?
UPDATE: Here is the relevant code:
import Cocoa
import Foundation
#NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
#IBOutlet weak var window: NSWindow!
#IBOutlet weak var statusMenu: NSMenu!
let statusItem = NSStatusBar.systemStatusBar().statusItemWithLength(-1)
func applicationDidFinishLaunching(aNotification: NSNotification) {
let icon = NSImage(named: "statusIcon")
statusItem.image = icon
statusItem.menu = statusMenu
// Time for constant repeat
NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "timerRepeat", userInfo: nil, repeats: true)
}
// Method to call the tracking core
func timerRepeat() {
//....
}
#IBAction func frontEnd(sender: NSMenuItem) {
var targetURL : String = NSBundle.mainBundle().resourcePath!
targetURL = targetURL + "/" + "front.app"
let workspace = NSWorkspace()
workspace.launchApplication(targetURL)
}
#IBAction func menuClicked(sender: NSMenuItem) {
NSApplication.sharedApplication().terminate(self)
}
}
You have a broken outlet in your xib file. Usually it happens when you set up an outlet to ivar or property which is later deleted or renamed not using Xcode's rename feature.
Also make sure that your custom view or view controller class is added to your target. (Project => Target Name => Build Phases => Compile Sources). It's possible that a file is in your project but not your target.
This happens because you at one point created an #IBOutlet for a storyboard element. You then later removed the code (reference) from your swift file.
I created an example where I create two extra #IBOutlets (I named them 'correctField' and 'incorrectField'- both are incorrect though) and connected them from my storyboard to my swift file.
I then removed the code from my swift file. This generates the log as shown in the following figure :
To remove this kind of log message, you can do the following:
Go to the 'storyboard' and select the storyboard elements you created connections (#IBOutlets) from.
Open the 'connection inspector' as showed in the figure below
Remove the Referencing Outlets which are incorrect (in my case it is the 'correctField' and 'incorrectField')
Done
This was done in xCode 11

Instance of class does not initialize IBOutlets in class

I have a class called AccountPanelController that contains two variables: an IBOutlet to an NSTableView, as well as a simple Int. When I run my app, awakeFromNib: prints that both the NSTableView and the Int have been initialized. From another file, I have created and initialized an instance of the class AcountPanelController. Via a button connected to that other file, I call openPanel: on the instance. At that point accountTable does not exist but somehow number does. In other words, when I initialize the instance of my class the Int is being created, but the NSTableView, an IBOutlet, is not. Why is this? I assume it is because accountTable is an IBOutlet, and therefore will not reinitialize. What can I do about this? (Xcode Version 6.1.1 (6A2008a), Cocoa, Swift)
Thanks,
bigelerow
class AccountPanelController: NSObject, NSTableViewDataSource {
#IBOutlet weak var accountTable: NSTableView!
var number: Int = 5
override func awakeFromNib() {
println(accountTable) // prints "<NSTableView: 0x100512aa0>"
println(number) // prints "5"
}
func openPanel() {
println(number) // prints "5"
println(accountTable) // prints "nil"
accountTable.reloadData() // throws error "unexpectedly found nil while unwrapping an Optional value"
}
// NSTableView data source functions below...
}
Other File
#IBAction func buttonPressed(sender: AnyObject?) {
var instance = AccountPanelController()
instance.openPanel()
}
IB automatically creates instances of all objects with IBOutlets when their xib file is loaded. So, instead of creating my own, second, instance in another file:
var instance = AccountPanelController()
I simply made a reference to the instance IB had already made for me:
IBOutlet weak var IBInstance: AcountPanelController!
Unlike the second instance, this IB created version contained initialized IBOutlets. When I referenced AccountTable it was not nil.

Resources