0

Please see below edit for current (minor) issue


I'm trying to call methods (methods right, not functions?) "between" the MainViewController.m and the FlipsideViewController.m -- from one file/class to another.

I guess this is what's often referred to as "Call methods from another class". There are plenty of such questions around, I know, but I just can't get it to work properly.

In my case, I have several user defined methods/functions in both above mentioned files. Sometimes, I need to call a method from within the FlipsideViewController.m that lies within the MainViewController.m File:

// in MainViewController.m

- (void) calculateDays {
    //executes caluculations
   // inserts data into labels, etc 
}

If I want to call this function simply from within the same file, I just do:

[self calculateDays];

That's easy, however, I want to call this function from within the FlipsideViewController.m file too, as well as vice versa. So how do I do this? This, this and this questions sort of answer it but it doesn't quite work to me. I'll explain why in just a second.

This is what I've tried and think should work:

MainViewController *mvs = [[MainViewController alloc] init]; //alloc init MVC
[mvs calculateDays]; //call "external" function

It gives me the error: "Unknown type name MainViewController". So I assume I have to include/import it somehow for it to work (just like in javascript or PHP). So I include it in the FlipSideViewController.m class:

 #import "MainViewController.h"

Great no errors so far. Then I try to compile/build it and runs into another error: "clang: error: linker command failed with exit code 1 (use -v to see invocation)" "ld: 3 duplicate symbols for architecture armv7s"

This leads me to think that importing the MainViewController like that isn't the way to go as I then import lots of other stuff that may interfere with some code in the FlipSideViewController class.

I've tried similar solutions but nothing seems to work. Can anyone please explain to me what I'm doing wrong, and perhaps how to do this properly: Call methods between MainViewController.m and FlipsideViewController.m and vice versa.


The proposed solution by H2CO3 did solve most of the issues (XCode bugged for a while and give me random errors which forced me to rebuild the entire project) but there's still this one thing that doesn't quite work: change the content of a UILabel (UIOutlet). Please see if anyone of you can help me with this:

When the method is called from within self (i.e. [self calculateDay]), the value is successfully inserted into the UILabel. When called from FlipsideViewController, the value to be inserted exists and is processed successfully, but can't be inserted into the UILabel. Please se below.

Some loggings:

//method called from within self on viewDidLoad: [self calculateDay];
Processed value to update label with: 26
New value in outlet after having been inserted: 26


//method called from another (FlipsideViewController) class file: [mvs calculateDay];
Processed value to update label with: 26
New value in outlet after having been inserted: (null)

/* 
  This doesn't work either from that external file: 
  [[mvs LabelName] setText:@"Hello, update label!"]; no errors but no display either

*/
Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Lindros
  • 253
  • 2
  • 12

2 Answers2

2

If you import the header instead, that should give you all the necessary declarations, but you won't have "duplicate symbol" linker errors. This is a "standard"/common practice for writing (Objective-)C code.

#import "MainViewController.h"
                            ^
      ".h" instead of ".m" -+
  • Thanks but I've already tried that, it gives me the compiler error: "No visible [at]interface for MainViewController declares the selector 'calculateDays'" so I try to add the [at]interface in a similar way as done with the FlipSideViewController: [at]interface MainViewController () @end and I get another error.. So I guess that is not the solution? – Lindros Jan 05 '13 at 17:13
  • 1
    @Lindros If your class is well-written, it should work like this, without badly hacking and filling with garbage the other source files. You have to declare your class in a way so that it is known to the compiler that it actually implements this method. If you don't have it, write `- (void)calculateDays` in the header file, inside the `@interface`. –  Jan 05 '13 at 17:16
  • that's better, it compiles and runs but crashes on this line MainViewController MainViewController *mvs = [[MainViewController alloc] init]; any ideas? Should I still add the [at] interface MainViewController () [at]end in the FlipsideViewController.m file? It runs with and without.. – Lindros Jan 05 '13 at 17:33
  • @Lindros If it crashes on `alloc-init`, then you're doing something nasty, presumably in the initialization. Check for potential dangling pointers, `nil` arguments, etc. –  Jan 05 '13 at 17:35
  • @Lindros What does the debugger say? –  Jan 05 '13 at 17:49
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/22244/discussion-between-lindros-and-h2co3) – Lindros Jan 05 '13 at 17:57
  • Ok it was nothing wrong with the actual code, XCode was just being stupid. I had to rebuild the project to get it to work.. Now, the code you suggested runs flawlessly without any errors, great stuff! One minor however noteworthy issue though is that it seems as if the method (that lies in the "external" class) fails to set a value to a label. It works perfectly when run from within self but once the **external** method call gets ran, it fails to insert a value into a label (UIOutlet). Is it possible that the "external" file can't access the label even though the .h file is imported? @H2CO3 – Lindros Jan 06 '13 at 00:40
  • I've edited my answer to describe the current issue more clearly. Please see question above. – Lindros Jan 06 '13 at 01:18
  • @Lindros Well, that's strange... You're not calling `[self calculateDay];` from the other file, but `[theOriginalViewController calculateDay];`, right? –  Jan 06 '13 at 05:25
  • No sorry, that was an uncontrolled copy paste. I've updated my question. I guess this is relevant, tried that too but with no further success: http://stackoverflow.com/questions/11807632/change-label-from-a-different-view – Lindros Jan 06 '13 at 15:39
0

(layman's terms) In Objective-C you can only use objects that each file knows about. In this example you are trying to use a MainViewController in the FlipsideController.m file. The FlipsideController.m has no idea what a MainViewController is, so it throws errors because it doesn't know what it is or how to use it. You have two options for telling the Flipsidecontroller what a MainViewController is, you can import the header (#import "MainViewController.h") which will give you full access to everything defined in the FlipSideController.h. (You should probably never import a .m unless you really know what your doing) You can also create a forward declaration - @class FilpsideControllerin the .h and import the file in the .m. This is useful to avoid circular imports etc.

Justin Meiners
  • 10,754
  • 6
  • 50
  • 92
  • Thanks but as said above, importing the header file instead leads to other errors please see my comment on H2CO3's answer. The forward declaration didn't work either unfortunately, gave me ARC Semantic issues – Lindros Jan 05 '13 at 17:18