Apple's Singleton example - iphone

Used the MyGizmoClass example in a iPhone app where I have an object that sets and maintain db info.
How do I eliminate the
'MyGizmoClass' may not respond to '+sharedManager'
Warning
The offending line of code is:
NSString *databasePath = [[MyGizmoClass sharedManager]databasePath];

It sounds like the +sharedManager method is not declared in the header. You've mentioned importing the header a couple of times but haven't said whether +sharedManager is part of that header. The error you're seeing indicates that either (a) the header's not being imported (and you've said that it is) or (b) the header is being imported but doesn't contain the method in question.

Not sure if this belonged in a comment or as and answer.
MyGizmoClass.h is imported in implementation file (and in it's header (just to see if that would stop the warning)). But the warning is still happening.

You need to import the MyGizmoClass.h file into your implementation. This lets the compiler know all the MyGizomoClass methods and will prevent the warning.
If this is already the case, then sharedManager isn't properly defined in the MyGizmoClass interface (.h file).

Related

Call methods between MainViewController.m and FlipsideViewController.m

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
*/
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" -+
(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.

How to get rid of warnings when using Category in XCode

in my code I have created a Category over UIViewController, so that every of my UIViewControllers has a error handling method. Unfortunatey now whenever I call this method from the category I get the following warning in XCode:
'MainWindowViewController' may not respond to '- (...method name...):'
We try to have our code without any warnings, so I wonder if there is any clever way to keep the Category and get rid if the "may not respond to" warning".
Thanks for your help!
Importing the header where your category is declared to implementation file where methods from that category are used should eliminate that warning.
#Vladimir is right , you need to import the header file in your implementation class.
There could be one more reason for the warning you get during compilation of your code,
if you don't declare the method in header file but implement the in implementation file
Vladimir is, of course, correct. Adding a category to class makes those functions available to all instances of that class whether the header file is #imported or not. Objective-C is a dynamic language.
However - the compiler is warning you that it can't see the declaration of those messages at compile time. The code could still be valid; which is why it raises a warning rather than an error.
I like to import the category into a class that requires the extensions that the category provides. I find it a useful way of reminding me of the dependency. Some programmers, however, think that since a category provides its methods to all instances of the class, it's pointless to add it to just one class.
If you prefer not to import the category to each class that uses it, but you would like to have clean compiles - #import the category header into the pch file instead.
Try restarting XCode and cleaning. I had the same problem, was definitely including the header file but still got the warning. Restart and clean fixed it.
When everything else sensible fails to fix the problem retype the offending call on a new line just below the offending line.
You might find that the complier is happy with the new line. Delete the old line. (Things that make you go HMMM?)
I've found this happens on more than one occasion with xcode (and other editors). When all else fails type the line again.

PageControl example code for the iPhone notation question

I'm looking through the PageControl example from Apple. They have a class called ContentController. In a subclass of the class, PhoneContentController.m, they have this:
#interface ContentController (PrivateMethods)
- (void)loadScrollViewWithPage:(int)page;
- (void)scrollViewDidScroll:(UIScrollView *)sender;
#end
Is this adding a category to the class ContentController?
Why would they put it in this file, versus the original file they created?
By declaring it in the PhoneContentController.m file, does it give this class access without having any additional directives for the compiler?
(I'm trying to understand the OOAD principles and why Apple does certain things in their example code, hierarchies, etc). Thanks!
Is this adding a category to the class ContentController?
Yes, they are adding a category.
Why would they put it in this file, versus the original file they created?
If I recall correctly, this is done because there are two UIs, (one for iPad and one for iPhone,) so that they can write the code only once and use the same handlers in the different view controllers.
By declaring it in the PhoneContentController.m file, does it give this class access without having any additional directives for the compiler?
Well, yes. It's a small matter to compile an additional 4 line file, and I think this is a template related decision rather than a compiler related one. It's simpler to distribute, say, 3 sample files instead of 4, for example.

Why does XCode warn me that a method in another class might not exist when it does?

This is more of an annoyance since the code works fine but maybe there's something here that I should be doing differently. At any rate, all my calls to methods in a class that's different from the caller are getting flagged as "No '-foo' method found" or "'ClassA' may not respond to '-bar'" by XCode. In reality the methods do exist and I've imported the associated header (that contains the method definition) so XCode should know what's going on. Ideas?
This happens when Xcode does not know about the method you are trying to call.
This can be due to a few reasons:
There is no method declaration for that method (either in the header file, or earlier in the .m file.
There is no method declaration for the method and the method is below the one you are trying to call it in.
You are not importing a header file you need.
Make sure you didn't misspell the method name (or used the wrong case, wrong parameter list, wrong parameter order, wrong parameter types, etc.) in the header. Make sure you really imported the header before the code producing the error.

Fix an error in an objective c tutorial

I'm on this step of the "Your First iOS Application" tutorial from Apple.
However, the line [self setMyViewController:aViewController]; has an error and the app appears as a blank black screen. The error message is 'HelloWorldAppDelegate' may not respond to '-setMyViewController' (2)
I've been following the tutorial carefully. How can I make this error go away? Why is it so ambiguous (it "may" not respond? under what circumstances will it?) and why am I getting this error in the first place? What step did I miss?
Go to your header-file and add - (void)setMyViewController:(UIViewController *)viewController;
Maybe you need to rename the parameter.
And btw. it's a warning not an error. Warnings are just for signalize that it could have problems if you haven't included the method.
If you declare a method in your .h file, the .m file gives out a warning if it isn't included. Don't worry it's not wrong if you forgot to declare a method in your .h file.
Are you running your code right after following that step? You should hold off doing so until you have finished following all steps on the page.
The Housekeeping section lists a step that you have to follow in order to make your property setter work:
In the #implementation block of the class, tell the compiler to synthesize the accessor methods for the view controller:
#synthesize myViewController;
After you finish adding the code as described by that section, running your code should work. If not, check your imports and your HelloWorldAppDelegate.h file — you may have missed something else too like declaring your #property.
Why is it so ambiguous (it "may" not respond? under what circumstances will it?)
It will respond if the compiler can find an implementation of the method, and the method is declared in the header file (unless it's a property accessor), and work as normal. If it does not, your program crashes.
and why am I getting this error in the first place?
You typically get that warning (it's not an error) if the property is not synthesized. By synthesizing it, the compiler creates the myViewController and setMyViewController: accessor methods in order for your code to access that property.
That should be a warning not an error.
Take heed of warnings, and you're right to want to eliminate them, but the code will compile and may run with warnings.
The warning could be occurring because there isn't a prototype for the method setMyViewController before it is referenced. The prototype is usually defined in the associated header '.h' file.
The prototype looks like the entry line of the method, up to, but not including the first '{', and with a ';' on the end.
Adding a prototype allows the compiler to verify you're calling the method correctly (and just as importantly, you typed it correctly ;-)