0

I have this function in my class "RunnerWindowController":

func didChangeScreenParameters(){
    runnerLayer.removeAllAnimations()
    animateRunner()
}

I try to call the function out of another class using:

var RunnerWindowC: RunnerWindowController!

@IBAction func btnSenden(sender: AnyObject) {
    RunnerWindowC.didChangeScreenParameters()
}

I get this fatal error:

fatal error: unexpectedly found nil while unwrapping an Optional value

I won't need any return, only the execute of the function.

EDIT: 05/13/2016

None of the answers help because i have a INIT in die RunnerWindowController.

SOLVED PROBLEM:

I solved the problem with a NSTimer.

RunnerWindowController:

var SetDidChange : Bool = false

class RunnerWindowController{
var startvalue : CGFloat = 0

var timer : NSTimer?

func initTimer() {
    self.timer = NSTimer.scheduledTimerWithTimeInterval(1, target:
self, selector: #selector(refresh), userInfo: nil, repeats: true)
}

@objc func refresh() {
    if (SetDidChange == true) {
        print("Refresh done")
        runnerLayer.removeAllAnimations()
        animateRunner()
        SetDidChange = false
    }
}
....
}

RunnerPrefController:

    override func viewDidAppear() {
    SetDidChange = false
}

@IBAction func btnSenden(sender: AnyObject) {
    SetDidChange = true
}
Gazzari
  • 1
  • 3
  • 4
    Your `RunnerWindowC` property is an implicitly unwrapped optional, and is `nil` when you call the function (which should be done with a single `()`, not a double) - see [this Q&A](http://stackoverflow.com/questions/32170456/what-does-fatal-error-unexpectedly-found-nil-while-unwrapping-an-optional-valu) for more info about how to safely deal with optionals. – Hamish May 05 '16 at 16:59

4 Answers4

1

try this:

class RunnerWindowController: UIViewController {
    class func didChangeScreenParameters(){
        runnerLayer.removeAllAnimations()
        animateRunner()
    }
}

class yourClassName: UIViewController {
    @IBAction func btnSenden(sender: AnyObject) {
        RunnerWindowController().didChangeScreenParameters()
    }
}
iParesh
  • 2,338
  • 1
  • 18
  • 30
0

One set of parenthesis is enough - ie. RunnerWindowC.didChangeScreenParameters(). However, the error you're getting probably has to do with RunnerWindowC being nil - make sure you assign RunnerWindowC (eg. if you're segueing from it, pass it along).

Dominic K
  • 6,975
  • 11
  • 53
  • 62
0

The problem is likely that you are trying to call a method on a variable that has not been initialized. The code you've shown will only define the class variable, not initialize it. At some point before calling that method you'll have to initialize it like this:

self.RunnerWindowC = RunnerWindowController()

If that controller is coupled to a storyboard you can initialize it like this:

let storyboard = UIStoryboard(name: "NameOfStoryboardFile", bundle: nil)
self.RunnerWindowC = storyboard.instantiateViewControllerWithIdentifier("RunnerWindowController") as! RunnerWindowController

EDIT 5-12-16:

To initialize a variable at the class level in swift, there are two main approaches:

Approach A:

Please note that the initializer you implement will depend on which class you inherit from. If you don't inherit from any class or you inherit from NSObject (like I do below) then you'll override init() If you inherit from a different class, you may have to override a different initializer. For example, inheriting from UIViewController means you should override the init(coder:) method, not init().

class MyParentClass: NSObject {
  var RunnerWindowC: RunnerWindowController!

  init() {
    RunnerWindowC = RunnerWindowController()
    super.init()
    // ^^^ All class variables need to be initialized
    // before the call to super.init() in swift!
  }

  // If you were doing this in a class that inherits UIViewController
  // you would implement the initializer like this instead:
  /****
  required init?(coder aDecoder: NSCoder) {
    RunnerWindowC = RunnerWindowController()
    super.init(coder: aDecoder)
  }
  ****/

  @IBAction func btnSenden(sender: AnyObject) {
    self.RunnerWindowC.didChangeScreenParameters()
  }
}

Approach B:

Swift also allows you to initialize the variables when they're defined at the class level, so you can do this as well:

class MyParentClass: NSObject {
  var RunnerWindowC = RunnerWindowController()

  @IBAction func btnSenden(sender: AnyObject) {
    self.RunnerWindowC.didChangeScreenParameters()
  }
}

I honestly don't know if there's any technical difference between the two other than just personal preference. I've used both and never had a problem.

JiuJitsuCoder
  • 1,866
  • 14
  • 13
  • Wehere have to initialize it? I get this Error: Expected declaration At that controller is no storyboard coupled. – Gazzari May 05 '16 at 17:20
  • Do you have any idea? – Gazzari May 05 '16 at 17:57
  • @gazzari it depends on how that 'other class' needs to create the RunnerWindowController. Is that RunnerWindowController a popup called via self.presentViewController()? Or is it shown via a segue on your storyboard? Or is it pushed onto a navigation view controller via self.navigationController?.pushViewController() ? – JiuJitsuCoder May 05 '16 at 18:21
  • none of that. The RunnerWindowController would be called by AppDelegate with the same procedures as described above. Its only a "class RunnerWindowControler { much functions }". The class isn't shown on storyboard. – Gazzari May 05 '16 at 18:35
  • @Gazzari ok then I would just initialize it in the init function for the other class that's calling the RunnerWIndowController() methods. – JiuJitsuCoder May 05 '16 at 20:38
  • But how can i do this? – Gazzari May 06 '16 at 21:27
  • can you explain how to do that? – Gazzari May 12 '16 at 13:27
  • @Gazzari sorry I must've missed your first request. I've updated my answer to show how to initialize those variables. I hope that helps! – JiuJitsuCoder May 12 '16 at 14:02
  • Thanks for your answer! I tried this, but it doesn't work... Do you have Bitbucket oder GitHub? I would be glad if you show in my project.. – Gazzari May 12 '16 at 14:21
  • @Gazzari I have a policy of keeping all of my answers open on Stack Overflow so the community can learn from them and add feedback/edits as needed (I don't know everything after all!). If you need some more help, and the answer linked to in the duplicate remark above doesn't help, I would suggest editing your question here with a larger code sample so the community can try to help. – JiuJitsuCoder May 12 '16 at 16:09
0

try to use with segue as

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

 let vc  = segue.destinationViewController as? RunnerWindowController
 vc?.didChangeScreenParameters()

}
Sucharu Hasija
  • 1,096
  • 11
  • 23