23

i got two swift files :

main.swift and view.swift

In main.swift i have a variable (Int) initially set to 0.

With an IBACtion I set that variable to be 10, and everything is ok.

However, if I try access that variable from view.swift, with a simple call like main().getValue(), i get always 0 and not 10 even if the variable has changed it's value in main.swift.

The method getValue() in main.swift looks like this:

func getValue() -> Int {
return variable
}

EDIT

Here is the code (Translated from Italian :D )

import Cocoa

class Main: NSObject {

    var variable: Int = 0

    func getValue() -> Int {
        return variable
    }

    @IBAction func updateVar(sender: AnyObject!) {
        variable = 10
    }
}

class View: NSView {
    override func drawRect(dirtyRect: NSRect) {
       println(Main().getValue()) //Returns always 0
    }
}

Thanks in advance Alberto

Alberto
  • 4,212
  • 5
  • 22
  • 36
  • 1
    We need to see how variable is defined. Is it defined in a class or a struct? How are you trying to access the value in the other file? – drewag Jun 20 '14 at 18:06
  • It is defined in the class. I'm trying to access the variable in the other class just typing main().getValue() – Alberto Jun 20 '14 at 18:07
  • 3
    by typing `main()` you are creating a new instance of the `main` class with the default value (0) for `variable` – Jiaaro Jun 20 '14 at 18:09
  • 1
    There are so many unknowns with what you have told us so far. First, files don't really matter in swift. It is all about classes / structs and instances. Is `main` the name of your class (normally classes are capitalized)? Also, are you using a `Xib` file? It is strange to me that are using `IBAction` with a class called simply `main`. Normally it would be a subclass of a UIKit or Cocoa view or controller class. – drewag Jun 20 '14 at 18:10
  • yes, we'll need to see more code :) there's not enough to go on here – fqdn Jun 20 '14 at 18:11
  • yep, I believe Jiaaro's comment takes it! good guess! – fqdn Jun 20 '14 at 18:15
  • Of course I am using XIB file.. Everything is linked and yes , class names are Capitalized. I'm italian and therefore i changed the names to make it easy for you to help me, sorry for the mess – Alberto Jun 20 '14 at 18:15
  • Jiaaro, I imagined that, but then , how to access that var ? I need it inside a drawrect method and should be updated by the user, so via IBAction – Alberto Jun 20 '14 at 18:16
  • @FoxNos I completely sympathize with your need to translate your code for us to help you and I don't blame you at all :). I am just trying to help you to create a question that we can answer confidently and also a question where other people might benefit from the answer. – drewag Jun 20 '14 at 18:25
  • It's hard to me to explain, but the task is very easy i think. I got two files, not class, made pressing CMD+N. I gave them 2 different names. One is a subclass of NSObject and the other is a subclass of NSView. In one file i want to control IBactions and user-stuff, in the other I want to make changes to a view using BezierPath. However, if the user changes some parameters of drawing, saved in main file (Subclass of NSObject, as I said), I will then need to access in the DrawRect method. Enough clear ? Thanks a lot, really :) – Alberto Jun 20 '14 at 18:35

2 Answers2

44

I have solved this by creating a generic main class which is accessible to all views. Create an empty swift file, name it 'global.swift' and include it in your project:

global.swift:

class Main {
  var name:String
  init(name:String) {
    self.name = name
  }
}
var mainInstance = Main(name:"My Global Class")

You can now access this mainInstance from all your view controllers and the name will always be "My Global Class". Example from a viewController:

viewController:

override func viewDidLoad() {
        super.viewDidLoad()
        println("global class is " + mainInstance.name)
    }
Kokodoko
  • 26,167
  • 33
  • 120
  • 197
  • 3
    Thank you. I have been wondering about this for 6 months (my entire swift career...) I have now learned how to store global variables accessible, settable and gettable, with modification from anywhere...!!!! ahhhh, thank you !!! – KML Mar 27 '15 at 14:23
  • 3
    This seems like a nice answer, but isn't one of our goals as programmers to refrain from using global variables? – jeffery_the_wind Apr 01 '16 at 21:24
  • 1
    Yes, but it's almost always just very handy to have a single "manager" class that everyone can access. There are many ways to achieve this, you could also pass a reference to your manager class around as a function argument - but I find that messy. – Kokodoko Apr 05 '16 at 11:01
  • 2
    Thank you very much for this!!!! Saved me all that trouble with using structs, NSUserDefaults, instances of classes etc etc! – Has May 17 '16 at 14:49
  • 2
    Thank you! saved me so much time and frustration :P – kishorer747 May 30 '16 at 14:33
  • 2
    OMG thank you so much. You have no idea how relief I am now lol – nodyor90z Dec 22 '16 at 02:27
  • What about a singleton.? – Ivan Cantarino May 17 '17 at 00:12
  • Can with this approach change `mainInstance `? – S At Oct 01 '17 at 21:10
  • If you needed to change the name in mainInstance from another ViewController, how would you go about doing that? – Cobie Fisher Dec 25 '17 at 20:31
  • how would I make the whole instance of Main accessible? So that I can call functions within the Main instance... – Robbie Jan 18 '20 at 16:14
  • Perhaps you could make Main a Singleton! Then Main would be accessible anywhere using `Main.getInstance()` – Kokodoko Jan 18 '20 at 16:56
  • Well done! Global instance of the class should be the ultimate solution' – Talha Shahab Oct 29 '20 at 13:23
18

There is an important distinction to be made between "files" in Swift and "classes". Files do not have anything to do with classes. You can define 1000 classes in one file or 1 class in 1000 files (using extensions). Data is held in instances of classes, not in files themselves.

So now to the problem. By calling Main() you are creating a completely new instance of the Main class that has nothing to do with the instance that you have hooked up to your Xib file. That is why the value comes out as the default.

What you need to do, is find a way to get a reference to the same instance as the one in your Xib. Without knowing more of the architecture of your app, it is hard for me to make a suggestion as to do that.

One thought, is that you can add a reference to your Main instance in your Xib using an IBOutlet in your View. Then you can simply do self.main.getValue() and it will be called on the correct instance.

drewag
  • 93,393
  • 28
  • 139
  • 128